Package updated to version mafw-gst-renderer-0.2.2010.07-2+0m5-1.
[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 #ifdef MAFW_GST_RENDERER_ENABLE_MUTE
127                 || wvolume->pending_operation_mute != mute
128 #endif
129         ))) {
130                 g_debug("volume notification, but operation running, ignoring");
131                 return;
132         }
133
134         wvolume->pulse_volume = volume;
135         wvolume->pulse_mute = mute;
136
137         /* EMIT VOLUME */
138         g_debug("ext stream volume is %lf (mute: %d) for role %s in device %s",
139                 wvolume->pulse_volume, wvolume->pulse_mute, i->name, i->device);
140         if (!wvolume->pending_operation &&
141             wvolume->pulse_volume != wvolume->current_volume) {
142                 wvolume->current_volume = wvolume->pulse_volume;
143                 if (wvolume->cb != NULL) {
144                         g_debug("signalling volume");
145                         wvolume->cb(wvolume, wvolume->current_volume,
146                                     wvolume->user_data);
147                 }
148         }
149 #ifdef MAFW_GST_RENDERER_ENABLE_MUTE
150         if (!wvolume->pending_operation &&
151             wvolume->pulse_mute != wvolume->current_mute) {
152                 wvolume->current_mute = wvolume->pulse_mute;
153                 if (wvolume->mute_cb != NULL) {
154                         g_debug("signalling mute");
155                         wvolume->mute_cb(wvolume, wvolume->current_mute,
156                                          wvolume->mute_user_data);
157                 }
158         }
159 #endif
160
161         wvolume->pending_operation = FALSE;
162 }
163
164 static void _destroy_context(MafwGstRendererWorkerVolume *wvolume)
165 {
166         if (wvolume->pa_operation != NULL) {
167                 if (pa_operation_get_state(wvolume->pa_operation) ==
168                     PA_OPERATION_RUNNING) {
169                         pa_operation_cancel(wvolume->pa_operation);
170                 }
171                 pa_operation_unref(wvolume->pa_operation);
172                 wvolume->pa_operation = NULL;
173         }
174         pa_context_unref(wvolume->context);
175 }
176
177 static InitCbClosure *_init_cb_closure_new(MafwGstRendererWorkerVolume *wvolume,
178                                            MafwGstRendererWorkerVolumeInitCb cb,
179                                            gpointer user_data)
180 {
181         InitCbClosure *closure;
182
183         closure = g_new(InitCbClosure, 1);
184         closure->wvolume = wvolume;
185         closure->cb = cb;
186         closure->user_data = user_data;
187
188         return closure;
189 }
190
191 static void _connect(gpointer user_data)
192 {
193         gchar *name = NULL;
194         pa_mainloop_api *api = NULL;
195         InitCbClosure *closure = user_data;
196         MafwGstRendererWorkerVolume *wvolume = closure->wvolume;
197
198         name = _get_client_name();
199
200         /* get the mainloop api and create a context */
201         api = pa_glib_mainloop_get_api(wvolume->mainloop);
202         wvolume->context = pa_context_new(api, name);
203         g_assert(wvolume->context != NULL);
204
205         /* register some essential callbacks */
206         pa_context_set_state_callback(wvolume->context, _state_cb_init,
207                                       closure);
208
209         g_debug("connecting to pulse");
210
211         g_assert(pa_context_connect(wvolume->context,
212                                     MAFW_GST_RENDERER_WORKER_VOLUME_SERVER,
213                                     PA_CONTEXT_NOAUTOSPAWN | PA_CONTEXT_NOFAIL,
214                                     NULL) >= 0);
215         g_free(name);
216 }
217
218 static gboolean _reconnect(gpointer user_data)
219 {
220         InitCbClosure *closure = user_data;
221         MafwGstRendererWorkerVolume *wvolume = closure->wvolume;
222
223         g_warning("got disconnected from pulse, reconnecting");
224         _destroy_context(wvolume);
225         _connect(user_data);
226
227         return FALSE;
228 }
229
230 static void
231 _state_cb(pa_context *c, void *data)
232 {
233         MafwGstRendererWorkerVolume *wvolume = data;
234         pa_context_state_t state;
235
236         state = pa_context_get_state(c);
237
238         switch (state) {
239         case PA_CONTEXT_TERMINATED:
240         case PA_CONTEXT_FAILED:
241         {
242                 InitCbClosure *closure;
243
244                 closure = _init_cb_closure_new(wvolume, NULL, NULL);
245                 g_idle_add(_reconnect, closure);
246                 break;
247         }
248         case PA_CONTEXT_READY: {
249                 pa_operation *o;
250
251                 o = pa_ext_stream_restore2_read(c, _ext_stream_restore_read_cb,
252                                                wvolume);
253                 g_assert(o != NULL);
254                 pa_operation_unref(o);
255
256                 break;
257         }
258         default:
259                 break;
260         }
261 }
262
263 static void _ext_stream_restore_read_cb_init(pa_context *c,
264                                              const pa_ext_stream_restore2_info *i,
265                                              int eol,
266                                              void *userdata)
267 {
268         InitCbClosure *closure = userdata;
269
270         if (eol < 0) {
271                 g_critical("eol parameter should not be < 1");
272         }
273
274         if (i == NULL ||
275             strcmp(i->name, MAFW_GST_RENDERER_WORKER_VOLUME_ROLE_PREFIX
276                    MAFW_GST_RENDERER_WORKER_VOLUME_ROLE) != 0)
277                 return;
278
279         closure->wvolume->pulse_volume =
280                 _pa_volume_to_per_one(pa_cvolume_max(&i->volume));
281         closure->wvolume->pulse_mute = i->mute != 0 ? TRUE : FALSE;
282         closure->wvolume->current_volume = closure->wvolume->pulse_volume;
283         closure->wvolume->current_mute = closure->wvolume->pulse_mute;
284
285         /* NOT EMIT VOLUME, BUT DEBUG */
286         g_debug("ext stream volume is %lf (mute: %d) for role %s in device %s",
287                 closure->wvolume->pulse_volume, i->mute, i->name, i->device);
288
289         if (closure->cb != NULL) {
290                 g_debug("initialized: returning volume manager");
291                 closure->cb(closure->wvolume, closure->user_data);
292         } else {
293                 if (closure->wvolume->cb != NULL) {
294                         g_debug("signalling volume after reconnection");
295                         closure->wvolume->cb(closure->wvolume,
296                                              closure->wvolume->current_volume,
297                                              closure->wvolume->user_data);
298                 }
299                 if (closure->wvolume->mute_cb != NULL) {
300                         g_debug("signalling mute after reconnection");
301                         closure->wvolume->mute_cb(closure->wvolume,
302                                                   closure->wvolume->
303                                                   current_mute,
304                                                   closure->wvolume->
305                                                   mute_user_data);
306                 }
307         }
308
309         pa_context_set_state_callback(closure->wvolume->context, _state_cb,
310                                       closure->wvolume);
311
312         g_free(closure);
313 }
314
315 static void _ext_stream_restore_subscribe_cb(pa_context *c, void *userdata)
316 {
317     pa_operation *o;
318
319     o = pa_ext_stream_restore2_read(c, _ext_stream_restore_read_cb, userdata);
320     g_assert(o != NULL);
321     pa_operation_unref(o);
322 }
323
324 static void
325 _state_cb_init(pa_context *c, void *data)
326 {
327         InitCbClosure *closure = data;
328         MafwGstRendererWorkerVolume *wvolume = closure->wvolume;
329         pa_context_state_t state;
330
331         state = pa_context_get_state(c);
332
333         g_debug("state: %d", state);
334
335         switch (state) {
336         case PA_CONTEXT_TERMINATED:
337         case PA_CONTEXT_FAILED:
338                 g_critical("Connection to pulse failed, reconnection in 1 "
339                            "second");
340                 g_timeout_add_seconds(1, _reconnect, closure);
341                 break;
342         case PA_CONTEXT_READY: {
343                 pa_operation *o;
344
345                 g_debug("PA_CONTEXT_READY");
346
347                 o = pa_ext_stream_restore2_read(c,
348                                                _ext_stream_restore_read_cb_init,
349                                                closure);
350                 g_assert(o != NULL);
351                 pa_operation_unref(o);
352
353                 pa_ext_stream_restore_set_subscribe_cb(
354                         c, _ext_stream_restore_subscribe_cb, wvolume);
355
356                 o = pa_ext_stream_restore_subscribe(c, 1, NULL, NULL);
357                 g_assert(o != NULL);
358                 pa_operation_unref(o);
359
360                 break;
361         }
362         default:
363                 break;
364         }
365 }
366
367 static gboolean _destroy_idle(gpointer data)
368 {
369         MafwGstRendererWorkerVolume *wvolume = data;
370
371         g_debug("destroying");
372
373         _destroy_context(wvolume);
374         pa_glib_mainloop_free(wvolume->mainloop);
375         g_free(wvolume);
376
377         return FALSE;
378 }
379
380 static void
381 _state_cb_destroy(pa_context *c, void *data)
382 {
383         pa_context_state_t state;
384
385         state = pa_context_get_state(c);
386
387         switch (state) {
388         case PA_CONTEXT_TERMINATED:
389                 g_idle_add(_destroy_idle, data);
390                 break;
391         case PA_CONTEXT_FAILED:
392                 g_error("Unexpected problem in volume management");
393                 break;
394         default:
395                 break;
396         }
397 }
398
399 static void _success_cb(pa_context *c, int success, void *userdata)
400 {
401         if (success == 0) {
402                 g_critical("Setting volume to pulse operation failed");
403         }
404 }
405
406 static void _remove_set_timeout(MafwGstRendererWorkerVolume *wvolume)
407 {
408         if (wvolume->change_request_id != 0) {
409                 g_source_remove(wvolume->change_request_id);
410         }
411         wvolume->change_request_id = 0;
412 }
413
414 static gboolean _set_timeout(gpointer data)
415 {
416         pa_ext_stream_restore2_info info;
417         pa_ext_stream_restore2_info *infos[1];
418         MafwGstRendererWorkerVolume *wvolume = data;
419
420         if (wvolume->pending_operation) {
421                 g_debug("setting volume ignored as there is still a pending "
422                         "operation. Waiting till next iteration");
423         } else if (wvolume->pulse_volume != wvolume->current_volume
424 #ifdef MAFW_GST_RENDERER_ENABLE_MUTE
425                         || wvolume->pulse_mute != wvolume->current_mute
426 #endif
427                         ) {
428
429                 info.name = MAFW_GST_RENDERER_WORKER_VOLUME_ROLE_PREFIX
430                         MAFW_GST_RENDERER_WORKER_VOLUME_ROLE;
431                 info.channel_map.channels = 1;
432                 info.channel_map.map[0] = PA_CHANNEL_POSITION_MONO;
433                 info.device = NULL;
434                 info.volume_is_absolute = TRUE;
435                 infos[0] = &info;
436
437                 info.mute = wvolume->current_mute;
438                 pa_cvolume_init(&info.volume);
439                 pa_cvolume_set(&info.volume, info.channel_map.channels,
440                                _pa_volume_from_per_one(wvolume->
441                                                        current_volume));
442
443                 g_debug("setting volume to %lf and mute to %d",
444                         wvolume->current_volume, wvolume->current_mute);
445
446                 if (wvolume->pa_operation != NULL) {
447                         pa_operation_unref(wvolume->pa_operation);
448                 }
449
450                 wvolume->pending_operation = TRUE;
451                 wvolume->pending_operation_volume = wvolume->current_volume;
452                 wvolume->pending_operation_mute = wvolume->current_mute;
453
454                 wvolume->pa_operation = pa_ext_stream_restore2_write(
455                         wvolume->context,
456                         PA_UPDATE_REPLACE,
457                         (const pa_ext_stream_restore2_info*
458                          const *)infos,
459                         1, TRUE, _success_cb, wvolume);
460
461                 if (wvolume->pa_operation == NULL) {
462                         g_critical("NULL operation when writing volume to "
463                                    "pulse");
464                         _remove_set_timeout(wvolume);
465                 }
466         } else {
467                 g_debug("removing volume timeout");
468                 _remove_set_timeout(wvolume);
469         }
470
471         return wvolume->change_request_id != 0;
472 }
473
474 void mafw_gst_renderer_worker_volume_init(GMainContext *main_context,
475                                           MafwGstRendererWorkerVolumeInitCb cb,
476                                           gpointer user_data,
477                                           MafwGstRendererWorkerVolumeChangedCb
478                                           changed_cb,
479                                           gpointer changed_user_data,
480                                           MafwGstRendererWorkerVolumeMuteCb
481                                           mute_cb, gpointer mute_user_data)
482 {
483         MafwGstRendererWorkerVolume *wvolume = NULL;
484         InitCbClosure *closure;
485
486         g_return_if_fail(cb != NULL);
487
488         g_assert(g_setenv(MAFW_GST_RENDERER_WORKER_VOLUME_ROLE_PROPERTY,
489                           MAFW_GST_RENDERER_WORKER_VOLUME_ROLE, FALSE));
490
491         g_debug("initializing volume manager");
492
493         wvolume = g_new0(MafwGstRendererWorkerVolume, 1);
494
495         wvolume->pulse_volume = 1.0;
496         wvolume->pulse_mute = FALSE;
497         wvolume->cb = changed_cb;
498         wvolume->user_data = changed_user_data;
499         wvolume->mute_cb = mute_cb;
500         wvolume->mute_user_data = mute_user_data;
501
502         wvolume->mainloop = pa_glib_mainloop_new(main_context);
503         g_assert(wvolume->mainloop != NULL);
504
505         closure = _init_cb_closure_new(wvolume, cb, user_data);
506         _connect(closure);
507 }
508
509 void mafw_gst_renderer_worker_volume_set(MafwGstRendererWorkerVolume *wvolume,
510                                          gdouble volume, gboolean mute)
511 {
512         gboolean signal_volume, signal_mute;
513
514         g_return_if_fail(wvolume != NULL);
515         g_return_if_fail(pa_context_get_state(wvolume->context) ==
516                          PA_CONTEXT_READY);
517
518 #ifndef MAFW_GST_RENDERER_ENABLE_MUTE
519         mute = FALSE;
520 #endif
521
522         signal_volume = wvolume->current_volume != volume &&
523                 wvolume->cb != NULL;
524         signal_mute = wvolume->current_mute != mute && wvolume->mute_cb != NULL;
525
526         wvolume->current_volume = volume;
527         wvolume->current_mute = mute;
528
529         g_debug("volume set: %lf (mute %d)", volume, mute);
530
531         if (signal_volume) {
532                 g_debug("signalling volume");
533                 wvolume->cb(wvolume, volume, wvolume->user_data);
534         }
535
536         if (signal_mute) {
537                 g_debug("signalling mute");
538                 wvolume->mute_cb(wvolume, mute, wvolume->mute_user_data);
539         }
540
541         if ((signal_mute || signal_volume) && wvolume->change_request_id == 0) {
542                 wvolume->change_request_id =
543                         g_timeout_add(MAFW_GST_RENDERER_WORKER_SET_TIMEOUT,
544                                       _set_timeout, wvolume);
545
546                 _set_timeout(wvolume);
547         }
548 }
549
550 gdouble mafw_gst_renderer_worker_volume_get(
551         MafwGstRendererWorkerVolume *wvolume)
552 {
553         g_return_val_if_fail(wvolume != NULL, 0.0);
554
555         g_debug("getting volume; %lf", wvolume->current_volume);
556
557         return wvolume->current_volume;
558 }
559
560 gboolean mafw_gst_renderer_worker_volume_is_muted(
561         MafwGstRendererWorkerVolume *wvolume)
562 {
563         g_return_val_if_fail(wvolume != NULL, FALSE);
564
565         g_debug("getting mute; %d", wvolume->current_mute);
566
567         return wvolume->current_mute;
568 }
569
570 void mafw_gst_renderer_worker_volume_destroy(
571         MafwGstRendererWorkerVolume *wvolume)
572 {
573         g_return_if_fail(wvolume != NULL);
574
575         g_debug("disconnecting");
576
577         pa_ext_stream_restore_set_subscribe_cb(wvolume->context, NULL, NULL);
578         pa_context_set_state_callback(wvolume->context, _state_cb_destroy,
579                                       wvolume);
580         pa_context_disconnect(wvolume->context);
581 }
582
583
584
585 #else
586
587
588 #include "mafw-gst-renderer-worker-volume.h"
589
590 #undef  G_LOG_DOMAIN
591 #define G_LOG_DOMAIN "mafw-gst-renderer-worker-volume-fake"
592
593 struct _MafwGstRendererWorkerVolume {
594         MafwGstRendererWorkerVolumeChangedCb cb;
595         gpointer user_data;
596         MafwGstRendererWorkerVolumeMuteCb mute_cb;
597         gpointer mute_user_data;
598         gdouble current_volume;
599         gboolean current_mute;
600 };
601
602 typedef struct {
603         MafwGstRendererWorkerVolume *wvolume;
604         MafwGstRendererWorkerVolumeInitCb cb;
605         gpointer user_data;
606 } InitCbClosure;
607
608 static gboolean _init_cb_closure(gpointer user_data)
609 {
610         InitCbClosure *closure = user_data;
611
612         if (closure->cb != NULL) {
613                 closure->cb(closure->wvolume, closure->user_data);
614         }
615         g_free(closure);
616
617         return FALSE;
618 }
619
620 void mafw_gst_renderer_worker_volume_init(GMainContext *main_context,
621                                           MafwGstRendererWorkerVolumeInitCb cb,
622                                           gpointer user_data,
623                                           MafwGstRendererWorkerVolumeChangedCb
624                                           changed_cb,
625                                           gpointer changed_user_data,
626                                           MafwGstRendererWorkerVolumeMuteCb
627                                           mute_cb, gpointer mute_user_data)
628 {
629         MafwGstRendererWorkerVolume *wvolume = NULL;
630         InitCbClosure *closure;
631
632         g_return_if_fail(cb != NULL);
633
634         g_debug("initializing volume manager");
635
636         wvolume = g_new0(MafwGstRendererWorkerVolume, 1);
637
638         wvolume->cb = changed_cb;
639         wvolume->user_data = changed_user_data;
640         wvolume->mute_cb = mute_cb;
641         wvolume->mute_user_data = mute_user_data;
642         wvolume->current_volume = 0.485;
643
644         closure = g_new0(InitCbClosure, 1);
645         closure->wvolume = wvolume;
646         closure->cb = cb;
647         closure->user_data = user_data;
648         g_idle_add(_init_cb_closure, closure);
649 }
650
651 void mafw_gst_renderer_worker_volume_set(MafwGstRendererWorkerVolume *wvolume,
652                                          gdouble volume, gboolean mute)
653 {
654         gboolean signal_volume, signal_mute;
655
656         g_return_if_fail(wvolume != NULL);
657
658 #ifndef MAFW_GST_RENDERER_ENABLE_MUTE
659         mute = FALSE;
660 #endif
661
662         signal_volume = wvolume->current_volume != volume &&
663                 wvolume->cb != NULL;
664         signal_mute = wvolume->current_mute != mute && wvolume->mute_cb != NULL;
665
666         wvolume->current_volume = volume;
667         wvolume->current_mute = mute;
668
669         g_debug("volume set: %lf (mute %d)", volume, mute);
670
671         if (signal_volume) {
672                 g_debug("signalling volume");
673                 wvolume->cb(wvolume, volume, wvolume->user_data);
674         }
675
676         if (signal_mute) {
677                 g_debug("signalling mute");
678                 wvolume->mute_cb(wvolume, mute, wvolume->mute_user_data);
679         }
680 }
681
682 gdouble mafw_gst_renderer_worker_volume_get(
683         MafwGstRendererWorkerVolume *wvolume)
684 {
685         g_return_val_if_fail(wvolume != NULL, 0.0);
686
687         g_debug("getting volume; %lf", wvolume->current_volume);
688
689         return wvolume->current_volume;
690 }
691
692 gboolean mafw_gst_renderer_worker_volume_is_muted(
693         MafwGstRendererWorkerVolume *wvolume)
694 {
695         g_return_val_if_fail(wvolume != NULL, FALSE);
696
697         g_debug("getting mute; %d", wvolume->current_mute);
698
699         return wvolume->current_mute;
700 }
701
702 void mafw_gst_renderer_worker_volume_destroy(
703         MafwGstRendererWorkerVolume *wvolume)
704 {
705         g_return_if_fail(wvolume != NULL);
706
707         g_free(wvolume);
708 }
709
710 #endif