Imported mafw-gst-renderer_0.1.2009.47-1+0m5
[mafwsubrenderer] / libmafw-gst-renderer / mafw-gst-renderer-worker-volume.c
1 /*
2  * This file is a part of MAFW
3  *
4  * Copyright (C) 2007, 2008, 2009 Nokia Corporation, all rights reserved.
5  *
6  * Contact: Visa Smolander <visa.smolander@nokia.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  */
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #ifndef MAFW_GST_RENDERER_DISABLE_PULSE_VOLUME
29
30 #include <pulse/pulseaudio.h>
31 #include <pulse/glib-mainloop.h>
32 #include <pulse/ext-stream-restore.h>
33 #include <string.h>
34
35 #include "mafw-gst-renderer-worker-volume.h"
36 #include "config.h"
37
38 #undef  G_LOG_DOMAIN
39 #define G_LOG_DOMAIN "mafw-gst-renderer-worker-volume"
40
41 #define MAFW_GST_RENDERER_WORKER_VOLUME_SERVER NULL
42
43 #define MAFW_GST_RENDERER_WORKER_VOLUME_ROLE_PROPERTY "PULSE_PROP_media.role"
44 #define MAFW_GST_RENDERER_WORKER_VOLUME_ROLE_PREFIX "sink-input-by-media-role:"
45 #define MAFW_GST_RENDERER_WORKER_VOLUME_ROLE "x-maemo"
46
47 #define MAFW_GST_RENDERER_WORKER_SET_TIMEOUT 200
48
49
50 struct _MafwGstRendererWorkerVolume {
51         pa_glib_mainloop *mainloop;
52         pa_context *context;
53         gdouble pulse_volume;
54         gboolean pulse_mute;
55         MafwGstRendererWorkerVolumeChangedCb cb;
56         gpointer user_data;
57         MafwGstRendererWorkerVolumeMuteCb mute_cb;
58         gpointer mute_user_data;
59         gdouble current_volume;
60         gboolean current_mute;
61         gboolean pending_operation;
62         gdouble pending_operation_volume;
63         gboolean pending_operation_mute;
64         guint change_request_id;
65         pa_operation *pa_operation;
66 };
67
68 typedef struct {
69         MafwGstRendererWorkerVolume *wvolume;
70         MafwGstRendererWorkerVolumeInitCb cb;
71         gpointer user_data;
72 } InitCbClosure;
73
74 #define _pa_volume_to_per_one(volume) \
75         ((guint) ((((gdouble)(volume) / (gdouble) PA_VOLUME_NORM) + \
76                    (gdouble) 0.005) * (gdouble) 100.0) / (gdouble) 100.0)
77 #define _pa_volume_from_per_one(volume) \
78         ((pa_volume_t)((gdouble)(volume) * (gdouble) PA_VOLUME_NORM))
79
80 #define _pa_operation_running(wvolume) \
81         (wvolume->pa_operation != NULL && \
82          pa_operation_get_state(wvolume->pa_operation) == PA_OPERATION_RUNNING)
83
84 static void _state_cb_init(pa_context *c, void *data);
85
86
87 static gchar *_get_client_name(void) {
88         gchar buf[PATH_MAX];
89         gchar *name = NULL;
90
91         if (pa_get_binary_name(buf, sizeof(buf)))
92                 name = g_strdup_printf("mafw-gst-renderer[%s]", buf);
93         else
94                 name = g_strdup("mafw-gst-renderer");
95
96         return name;
97 }
98
99 static void _ext_stream_restore_read_cb(pa_context *c,
100                                         const pa_ext_stream_restore2_info *i,
101                                         int eol,
102                                         void *userdata)
103 {
104         MafwGstRendererWorkerVolume *wvolume = userdata;
105         gdouble volume;
106         gboolean mute;
107
108         if (eol < 0) {
109                 g_critical("eol parameter should not be < 1. "
110                            "Discarding volume event");
111                 return;
112         }
113
114         if (i == NULL ||
115             strcmp(i->name, MAFW_GST_RENDERER_WORKER_VOLUME_ROLE_PREFIX
116                    MAFW_GST_RENDERER_WORKER_VOLUME_ROLE) != 0) {
117                 return;
118         }
119
120         volume = _pa_volume_to_per_one(pa_cvolume_max(&i->volume));
121         mute = i->mute != 0 ? TRUE : FALSE;
122
123         if (_pa_operation_running(wvolume) ||
124             (wvolume->pending_operation &&
125              (wvolume->pending_operation_volume != volume ||
126               wvolume->pending_operation_mute != mute))) {
127                 g_debug("volume notification, but operation running, ignoring");
128                 return;
129         }
130
131         wvolume->pulse_volume = volume;
132         wvolume->pulse_mute = mute;
133
134         /* EMIT VOLUME */
135         g_debug("ext stream volume is %lf (mute: %d) for role %s in device %s",
136                 wvolume->pulse_volume, wvolume->pulse_mute, i->name, i->device);
137         if (!wvolume->pending_operation &&
138             wvolume->pulse_volume != wvolume->current_volume) {
139                 wvolume->current_volume = wvolume->pulse_volume;
140                 if (wvolume->cb != NULL) {
141                         g_debug("signalling volume");
142                         wvolume->cb(wvolume, wvolume->current_volume,
143                                     wvolume->user_data);
144                 }
145         }
146         if (!wvolume->pending_operation &&
147             wvolume->pulse_mute != wvolume->current_mute) {
148                 wvolume->current_mute = wvolume->pulse_mute;
149                 if (wvolume->mute_cb != NULL) {
150                         g_debug("signalling mute");
151                         wvolume->mute_cb(wvolume, wvolume->current_mute,
152                                          wvolume->mute_user_data);
153                 }
154         }
155
156         wvolume->pending_operation = FALSE;
157 }
158
159 static void _destroy_context(MafwGstRendererWorkerVolume *wvolume)
160 {
161         if (wvolume->pa_operation != NULL) {
162                 if (pa_operation_get_state(wvolume->pa_operation) ==
163                     PA_OPERATION_RUNNING) {
164                         pa_operation_cancel(wvolume->pa_operation);
165                 }
166                 pa_operation_unref(wvolume->pa_operation);
167                 wvolume->pa_operation = NULL;
168         }
169         pa_context_unref(wvolume->context);
170 }
171
172 static InitCbClosure *_init_cb_closure_new(MafwGstRendererWorkerVolume *wvolume,
173                                            MafwGstRendererWorkerVolumeInitCb cb,
174                                            gpointer user_data)
175 {
176         InitCbClosure *closure;
177
178         closure = g_new(InitCbClosure, 1);
179         closure->wvolume = wvolume;
180         closure->cb = cb;
181         closure->user_data = user_data;
182
183         return closure;
184 }
185
186 static void _connect(gpointer user_data)
187 {
188         gchar *name = NULL;
189         pa_mainloop_api *api = NULL;
190         InitCbClosure *closure = user_data;
191         MafwGstRendererWorkerVolume *wvolume = closure->wvolume;
192
193         name = _get_client_name();
194
195         /* get the mainloop api and create a context */
196         api = pa_glib_mainloop_get_api(wvolume->mainloop);
197         wvolume->context = pa_context_new(api, name);
198         g_assert(wvolume->context != NULL);
199
200         /* register some essential callbacks */
201         pa_context_set_state_callback(wvolume->context, _state_cb_init,
202                                       closure);
203
204         g_debug("connecting to pulse");
205
206         g_assert(pa_context_connect(wvolume->context,
207                                     MAFW_GST_RENDERER_WORKER_VOLUME_SERVER,
208                                     PA_CONTEXT_NOAUTOSPAWN | PA_CONTEXT_NOFAIL,
209                                     NULL) >= 0);
210         g_free(name);
211 }
212
213 static gboolean _reconnect(gpointer user_data)
214 {
215         InitCbClosure *closure = user_data;
216         MafwGstRendererWorkerVolume *wvolume = closure->wvolume;
217
218         g_warning("got disconnected from pulse, reconnecting");
219         _destroy_context(wvolume);
220         _connect(user_data);
221
222         return FALSE;
223 }
224
225 static void
226 _state_cb(pa_context *c, void *data)
227 {
228         MafwGstRendererWorkerVolume *wvolume = data;
229         pa_context_state_t state;
230
231         state = pa_context_get_state(c);
232
233         switch (state) {
234         case PA_CONTEXT_TERMINATED:
235         case PA_CONTEXT_FAILED:
236         {
237                 InitCbClosure *closure;
238
239                 closure = _init_cb_closure_new(wvolume, NULL, NULL);
240                 g_idle_add(_reconnect, closure);
241                 break;
242         }
243         case PA_CONTEXT_READY: {
244                 pa_operation *o;
245
246                 o = pa_ext_stream_restore2_read(c, _ext_stream_restore_read_cb,
247                                                wvolume);
248                 g_assert(o != NULL);
249                 pa_operation_unref(o);
250
251                 break;
252         }
253         default:
254                 break;
255         }
256 }
257
258 static void _ext_stream_restore_read_cb_init(pa_context *c,
259                                              const pa_ext_stream_restore2_info *i,
260                                              int eol,
261                                              void *userdata)
262 {
263         InitCbClosure *closure = userdata;
264
265         if (eol < 0) {
266                 g_critical("eol parameter should not be < 1");
267         }
268
269         if (i == NULL ||
270             strcmp(i->name, MAFW_GST_RENDERER_WORKER_VOLUME_ROLE_PREFIX
271                    MAFW_GST_RENDERER_WORKER_VOLUME_ROLE) != 0)
272                 return;
273
274         closure->wvolume->pulse_volume =
275                 _pa_volume_to_per_one(pa_cvolume_max(&i->volume));
276         closure->wvolume->pulse_mute = i->mute != 0 ? TRUE : FALSE;
277         closure->wvolume->current_volume = closure->wvolume->pulse_volume;
278         closure->wvolume->current_mute = closure->wvolume->pulse_mute;
279
280         /* NOT EMIT VOLUME, BUT DEBUG */
281         g_debug("ext stream volume is %lf (mute: %d) for role %s in device %s",
282                 closure->wvolume->pulse_volume, i->mute, i->name, i->device);
283
284         if (closure->cb != NULL) {
285                 g_debug("initialized: returning volume manager");
286                 closure->cb(closure->wvolume, closure->user_data);
287         } else {
288                 if (closure->wvolume->cb != NULL) {
289                         g_debug("signalling volume after reconnection");
290                         closure->wvolume->cb(closure->wvolume,
291                                              closure->wvolume->current_volume,
292                                              closure->wvolume->user_data);
293                 }
294                 if (closure->wvolume->mute_cb != NULL) {
295                         g_debug("signalling mute after reconnection");
296                         closure->wvolume->mute_cb(closure->wvolume,
297                                                   closure->wvolume->
298                                                   current_mute,
299                                                   closure->wvolume->
300                                                   mute_user_data);
301                 }
302         }
303
304         pa_context_set_state_callback(closure->wvolume->context, _state_cb,
305                                       closure->wvolume);
306
307         g_free(closure);
308 }
309
310 static void _ext_stream_restore_subscribe_cb(pa_context *c, void *userdata)
311 {
312     pa_operation *o;
313
314     o = pa_ext_stream_restore2_read(c, _ext_stream_restore_read_cb, userdata);
315     g_assert(o != NULL);
316     pa_operation_unref(o);
317 }
318
319 static void
320 _state_cb_init(pa_context *c, void *data)
321 {
322         InitCbClosure *closure = data;
323         MafwGstRendererWorkerVolume *wvolume = closure->wvolume;
324         pa_context_state_t state;
325
326         state = pa_context_get_state(c);
327
328         g_debug("state: %d", state);
329
330         switch (state) {
331         case PA_CONTEXT_TERMINATED:
332         case PA_CONTEXT_FAILED:
333                 g_critical("Connection to pulse failed, reconnection in 1 "
334                            "second");
335                 g_timeout_add_seconds(1, _reconnect, closure);
336                 break;
337         case PA_CONTEXT_READY: {
338                 pa_operation *o;
339
340                 g_debug("PA_CONTEXT_READY");
341
342                 o = pa_ext_stream_restore2_read(c,
343                                                _ext_stream_restore_read_cb_init,
344                                                closure);
345                 g_assert(o != NULL);
346                 pa_operation_unref(o);
347
348                 pa_ext_stream_restore_set_subscribe_cb(
349                         c, _ext_stream_restore_subscribe_cb, wvolume);
350
351                 o = pa_ext_stream_restore_subscribe(c, 1, NULL, NULL);
352                 g_assert(o != NULL);
353                 pa_operation_unref(o);
354
355                 break;
356         }
357         default:
358                 break;
359         }
360 }
361
362 static gboolean _destroy_idle(gpointer data)
363 {
364         MafwGstRendererWorkerVolume *wvolume = data;
365
366         g_debug("destroying");
367
368         _destroy_context(wvolume);
369         pa_glib_mainloop_free(wvolume->mainloop);
370         g_free(wvolume);
371
372         return FALSE;
373 }
374
375 static void
376 _state_cb_destroy(pa_context *c, void *data)
377 {
378         pa_context_state_t state;
379
380         state = pa_context_get_state(c);
381
382         switch (state) {
383         case PA_CONTEXT_TERMINATED:
384                 g_idle_add(_destroy_idle, data);
385                 break;
386         case PA_CONTEXT_FAILED:
387                 g_error("Unexpected problem in volume management");
388                 break;
389         default:
390                 break;
391         }
392 }
393
394 static void _success_cb(pa_context *c, int success, void *userdata)
395 {
396         if (success == 0) {
397                 g_critical("Setting volume to pulse operation failed");
398         }
399 }
400
401 static void _remove_set_timeout(MafwGstRendererWorkerVolume *wvolume)
402 {
403         if (wvolume->change_request_id != 0) {
404                 g_source_remove(wvolume->change_request_id);
405         }
406         wvolume->change_request_id = 0;
407 }
408
409 static gboolean _set_timeout(gpointer data)
410 {
411         pa_ext_stream_restore2_info info;
412         pa_ext_stream_restore2_info *infos[1];
413         MafwGstRendererWorkerVolume *wvolume = data;
414
415         if (wvolume->pending_operation) {
416                 g_debug("setting volume ignored as there is still a pending "
417                         "operation. Waiting till next iteration");
418         } else if (wvolume->pulse_mute != wvolume->current_mute ||
419                    wvolume->pulse_volume != wvolume->current_volume) {
420
421                 info.name = MAFW_GST_RENDERER_WORKER_VOLUME_ROLE_PREFIX
422                         MAFW_GST_RENDERER_WORKER_VOLUME_ROLE;
423                 info.channel_map.channels = 1;
424                 info.channel_map.map[0] = PA_CHANNEL_POSITION_MONO;
425                 info.device = NULL;
426                 info.volume_is_absolute = TRUE;
427                 infos[0] = &info;
428
429                 info.mute = wvolume->current_mute;
430                 pa_cvolume_init(&info.volume);
431                 pa_cvolume_set(&info.volume, info.channel_map.channels,
432                                _pa_volume_from_per_one(wvolume->
433                                                        current_volume));
434
435                 g_debug("setting volume to %lf and mute to %d",
436                         wvolume->current_volume, wvolume->current_mute);
437
438                 if (wvolume->pa_operation != NULL) {
439                         pa_operation_unref(wvolume->pa_operation);
440                 }
441
442                 wvolume->pending_operation = TRUE;
443                 wvolume->pending_operation_volume = wvolume->current_volume;
444                 wvolume->pending_operation_mute = wvolume->current_mute;
445
446                 wvolume->pa_operation = pa_ext_stream_restore2_write(
447                         wvolume->context,
448                         PA_UPDATE_REPLACE,
449                         (const pa_ext_stream_restore2_info*
450                          const *)infos,
451                         1, TRUE, _success_cb, wvolume);
452
453                 if (wvolume->pa_operation == NULL) {
454                         g_critical("NULL operation when writing volume to "
455                                    "pulse");
456                         _remove_set_timeout(wvolume);
457                 }
458         } else {
459                 g_debug("removing volume timeout");
460                 _remove_set_timeout(wvolume);
461         }
462
463         return wvolume->change_request_id != 0;
464 }
465
466 void mafw_gst_renderer_worker_volume_init(GMainContext *main_context,
467                                           MafwGstRendererWorkerVolumeInitCb cb,
468                                           gpointer user_data,
469                                           MafwGstRendererWorkerVolumeChangedCb
470                                           changed_cb,
471                                           gpointer changed_user_data,
472                                           MafwGstRendererWorkerVolumeMuteCb
473                                           mute_cb, gpointer mute_user_data)
474 {
475         MafwGstRendererWorkerVolume *wvolume = NULL;
476         InitCbClosure *closure;
477
478         g_return_if_fail(cb != NULL);
479
480         g_assert(g_setenv(MAFW_GST_RENDERER_WORKER_VOLUME_ROLE_PROPERTY,
481                           MAFW_GST_RENDERER_WORKER_VOLUME_ROLE, FALSE));
482
483         g_debug("initializing volume manager");
484
485         wvolume = g_new0(MafwGstRendererWorkerVolume, 1);
486
487         wvolume->pulse_volume = 1.0;
488         wvolume->pulse_mute = FALSE;
489         wvolume->cb = changed_cb;
490         wvolume->user_data = changed_user_data;
491         wvolume->mute_cb = mute_cb;
492         wvolume->mute_user_data = mute_user_data;
493
494         wvolume->mainloop = pa_glib_mainloop_new(main_context);
495         g_assert(wvolume->mainloop != NULL);
496
497         closure = _init_cb_closure_new(wvolume, cb, user_data);
498         _connect(closure);
499 }
500
501 void mafw_gst_renderer_worker_volume_set(MafwGstRendererWorkerVolume *wvolume,
502                                          gdouble volume, gboolean mute)
503 {
504         gboolean signal_volume, signal_mute;
505
506         g_return_if_fail(wvolume != NULL);
507         g_return_if_fail(pa_context_get_state(wvolume->context) ==
508                          PA_CONTEXT_READY);
509
510 #ifndef MAFW_GST_RENDERER_ENABLE_MUTE
511         mute = FALSE;
512 #endif
513
514         signal_volume = wvolume->current_volume != volume &&
515                 wvolume->cb != NULL;
516         signal_mute = wvolume->current_mute != mute && wvolume->mute_cb != NULL;
517
518         wvolume->current_volume = volume;
519         wvolume->current_mute = mute;
520
521         g_debug("volume set: %lf (mute %d)", volume, mute);
522
523         if (signal_volume) {
524                 g_debug("signalling volume");
525                 wvolume->cb(wvolume, volume, wvolume->user_data);
526         }
527
528         if (signal_mute) {
529                 g_debug("signalling mute");
530                 wvolume->mute_cb(wvolume, mute, wvolume->mute_user_data);
531         }
532
533         if ((signal_mute || signal_volume) && wvolume->change_request_id == 0) {
534                 wvolume->change_request_id =
535                         g_timeout_add(MAFW_GST_RENDERER_WORKER_SET_TIMEOUT,
536                                       _set_timeout, wvolume);
537
538                 _set_timeout(wvolume);
539         }
540 }
541
542 gdouble mafw_gst_renderer_worker_volume_get(
543         MafwGstRendererWorkerVolume *wvolume)
544 {
545         g_return_val_if_fail(wvolume != NULL, 0.0);
546
547         g_debug("getting volume; %lf", wvolume->current_volume);
548
549         return wvolume->current_volume;
550 }
551
552 gboolean mafw_gst_renderer_worker_volume_is_muted(
553         MafwGstRendererWorkerVolume *wvolume)
554 {
555         g_return_val_if_fail(wvolume != NULL, FALSE);
556
557         g_debug("getting mute; %d", wvolume->current_mute);
558
559         return wvolume->current_mute;
560 }
561
562 void mafw_gst_renderer_worker_volume_destroy(
563         MafwGstRendererWorkerVolume *wvolume)
564 {
565         g_return_if_fail(wvolume != NULL);
566
567         g_debug("disconnecting");
568
569         pa_ext_stream_restore_set_subscribe_cb(wvolume->context, NULL, NULL);
570         pa_context_set_state_callback(wvolume->context, _state_cb_destroy,
571                                       wvolume);
572         pa_context_disconnect(wvolume->context);
573 }
574
575
576
577 #else
578
579
580 #include "mafw-gst-renderer-worker-volume.h"
581
582 #undef  G_LOG_DOMAIN
583 #define G_LOG_DOMAIN "mafw-gst-renderer-worker-volume-fake"
584
585 struct _MafwGstRendererWorkerVolume {
586         MafwGstRendererWorkerVolumeChangedCb cb;
587         gpointer user_data;
588         MafwGstRendererWorkerVolumeMuteCb mute_cb;
589         gpointer mute_user_data;
590         gdouble current_volume;
591         gboolean current_mute;
592 };
593
594 typedef struct {
595         MafwGstRendererWorkerVolume *wvolume;
596         MafwGstRendererWorkerVolumeInitCb cb;
597         gpointer user_data;
598 } InitCbClosure;
599
600 static gboolean _init_cb_closure(gpointer user_data)
601 {
602         InitCbClosure *closure = user_data;
603
604         if (closure->cb != NULL) {
605                 closure->cb(closure->wvolume, closure->user_data);
606         }
607         g_free(closure);
608
609         return FALSE;
610 }
611
612 void mafw_gst_renderer_worker_volume_init(GMainContext *main_context,
613                                           MafwGstRendererWorkerVolumeInitCb cb,
614                                           gpointer user_data,
615                                           MafwGstRendererWorkerVolumeChangedCb
616                                           changed_cb,
617                                           gpointer changed_user_data,
618                                           MafwGstRendererWorkerVolumeMuteCb
619                                           mute_cb, gpointer mute_user_data)
620 {
621         MafwGstRendererWorkerVolume *wvolume = NULL;
622         InitCbClosure *closure;
623
624         g_return_if_fail(cb != NULL);
625
626         g_debug("initializing volume manager");
627
628         wvolume = g_new0(MafwGstRendererWorkerVolume, 1);
629
630         wvolume->cb = changed_cb;
631         wvolume->user_data = changed_user_data;
632         wvolume->mute_cb = mute_cb;
633         wvolume->mute_user_data = mute_user_data;
634         wvolume->current_volume = 0.485;
635
636         closure = g_new0(InitCbClosure, 1);
637         closure->wvolume = wvolume;
638         closure->cb = cb;
639         closure->user_data = user_data;
640         g_idle_add(_init_cb_closure, closure);
641 }
642
643 void mafw_gst_renderer_worker_volume_set(MafwGstRendererWorkerVolume *wvolume,
644                                          gdouble volume, gboolean mute)
645 {
646         gboolean signal_volume, signal_mute;
647
648         g_return_if_fail(wvolume != NULL);
649
650 #ifndef MAFW_GST_RENDERER_ENABLE_MUTE
651         mute = FALSE;
652 #endif
653
654         signal_volume = wvolume->current_volume != volume &&
655                 wvolume->cb != NULL;
656         signal_mute = wvolume->current_mute != mute && wvolume->mute_cb != NULL;
657
658         wvolume->current_volume = volume;
659         wvolume->current_mute = mute;
660
661         g_debug("volume set: %lf (mute %d)", volume, mute);
662
663         if (signal_volume) {
664                 g_debug("signalling volume");
665                 wvolume->cb(wvolume, volume, wvolume->user_data);
666         }
667
668         if (signal_mute) {
669                 g_debug("signalling mute");
670                 wvolume->mute_cb(wvolume, mute, wvolume->mute_user_data);
671         }
672 }
673
674 gdouble mafw_gst_renderer_worker_volume_get(
675         MafwGstRendererWorkerVolume *wvolume)
676 {
677         g_return_val_if_fail(wvolume != NULL, 0.0);
678
679         g_debug("getting volume; %lf", wvolume->current_volume);
680
681         return wvolume->current_volume;
682 }
683
684 gboolean mafw_gst_renderer_worker_volume_is_muted(
685         MafwGstRendererWorkerVolume *wvolume)
686 {
687         g_return_val_if_fail(wvolume != NULL, FALSE);
688
689         g_debug("getting mute; %d", wvolume->current_mute);
690
691         return wvolume->current_mute;
692 }
693
694 void mafw_gst_renderer_worker_volume_destroy(
695         MafwGstRendererWorkerVolume *wvolume)
696 {
697         g_return_if_fail(wvolume != NULL);
698
699         g_free(wvolume);
700 }
701
702 #endif