1 /*
2  * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the licence, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <glib.h>
19 #include <glib-object.h>
20 
21 #include "matemixer-enums.h"
22 #include "matemixer-enum-types.h"
23 #include "matemixer-stream.h"
24 #include "matemixer-stream-control.h"
25 #include "matemixer-stream-control-private.h"
26 
27 /**
28  * SECTION:matemixer-stream-control
29  * @include: libmatemixer/matemixer.h
30  */
31 
32 struct _MateMixerStreamControlPrivate
33 {
34     gchar                          *name;
35     gchar                          *label;
36     gboolean                        mute;
37     gfloat                          balance;
38     gfloat                          fade;
39     MateMixerStream                *stream;
40     MateMixerStreamControlFlags     flags;
41     MateMixerStreamControlRole      role;
42     MateMixerStreamControlMediaRole media_role;
43 };
44 
45 enum {
46     PROP_0,
47     PROP_NAME,
48     PROP_LABEL,
49     PROP_FLAGS,
50     PROP_ROLE,
51     PROP_MEDIA_ROLE,
52     PROP_STREAM,
53     PROP_MUTE,
54     PROP_VOLUME,
55     PROP_BALANCE,
56     PROP_FADE,
57     N_PROPERTIES
58 };
59 
60 static GParamSpec *properties[N_PROPERTIES] = { NULL, };
61 
62 enum {
63     MONITOR_VALUE,
64     N_SIGNALS
65 };
66 
67 static guint signals[N_SIGNALS] = { 0, };
68 
69 static void mate_mixer_stream_control_get_property (GObject                     *object,
70                                                     guint                        param_id,
71                                                     GValue                      *value,
72                                                     GParamSpec                  *pspec);
73 static void mate_mixer_stream_control_set_property (GObject                     *object,
74                                                     guint                        param_id,
75                                                     const GValue                *value,
76                                                     GParamSpec                  *pspec);
77 
78 static void mate_mixer_stream_control_finalize     (GObject                     *object);
79 
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(MateMixerStreamControl,mate_mixer_stream_control,G_TYPE_OBJECT)80 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MateMixerStreamControl, mate_mixer_stream_control, G_TYPE_OBJECT)
81 
82 static void
83 mate_mixer_stream_control_class_init (MateMixerStreamControlClass *klass)
84 {
85     GObjectClass *object_class;
86 
87     object_class = G_OBJECT_CLASS (klass);
88     object_class->finalize     = mate_mixer_stream_control_finalize;
89     object_class->get_property = mate_mixer_stream_control_get_property;
90     object_class->set_property = mate_mixer_stream_control_set_property;
91 
92     properties[PROP_NAME] =
93         g_param_spec_string ("name",
94                              "Name",
95                              "Name of the stream control",
96                              NULL,
97                              G_PARAM_READWRITE |
98                              G_PARAM_CONSTRUCT_ONLY |
99                              G_PARAM_STATIC_STRINGS);
100 
101     properties[PROP_LABEL] =
102         g_param_spec_string ("label",
103                              "Label",
104                              "Label of the stream control",
105                              NULL,
106                              G_PARAM_READWRITE |
107                              G_PARAM_CONSTRUCT_ONLY |
108                              G_PARAM_STATIC_STRINGS);
109 
110     properties[PROP_FLAGS] =
111         g_param_spec_flags ("flags",
112                             "Flags",
113                             "Capability flags of the stream control",
114                             MATE_MIXER_TYPE_STREAM_CONTROL_FLAGS,
115                             MATE_MIXER_STREAM_CONTROL_NO_FLAGS,
116                             G_PARAM_READWRITE |
117                             G_PARAM_CONSTRUCT_ONLY |
118                             G_PARAM_STATIC_STRINGS);
119 
120     properties[PROP_ROLE] =
121         g_param_spec_enum ("role",
122                            "Role",
123                            "Role of the stream control",
124                            MATE_MIXER_TYPE_STREAM_CONTROL_ROLE,
125                            MATE_MIXER_STREAM_CONTROL_ROLE_UNKNOWN,
126                            G_PARAM_READWRITE |
127                            G_PARAM_CONSTRUCT_ONLY |
128                            G_PARAM_STATIC_STRINGS);
129 
130     properties[PROP_MEDIA_ROLE] =
131         g_param_spec_enum ("media-role",
132                            "Media role",
133                            "Media role of the stream control",
134                            MATE_MIXER_TYPE_STREAM_CONTROL_MEDIA_ROLE,
135                            MATE_MIXER_STREAM_CONTROL_MEDIA_ROLE_UNKNOWN,
136                            G_PARAM_READWRITE |
137                            G_PARAM_CONSTRUCT_ONLY |
138                            G_PARAM_STATIC_STRINGS);
139 
140     properties[PROP_STREAM] =
141         g_param_spec_object ("stream",
142                              "Stream",
143                              "Stream which owns the control",
144                              MATE_MIXER_TYPE_STREAM,
145                              G_PARAM_READWRITE |
146                              G_PARAM_CONSTRUCT_ONLY |
147                              G_PARAM_STATIC_STRINGS);
148 
149     properties[PROP_MUTE] =
150         g_param_spec_boolean ("mute",
151                               "Mute",
152                               "Mute state of the stream control",
153                               FALSE,
154                               G_PARAM_READABLE |
155                               G_PARAM_STATIC_STRINGS);
156 
157     properties[PROP_VOLUME] =
158         g_param_spec_uint ("volume",
159                            "Volume",
160                            "Volume of the stream control",
161                            0,
162                            G_MAXUINT,
163                            0,
164                            G_PARAM_READABLE |
165                            G_PARAM_STATIC_STRINGS);
166 
167     properties[PROP_BALANCE] =
168         g_param_spec_float ("balance",
169                             "Balance",
170                             "Balance value of the stream control",
171                             -1.0f,
172                             1.0f,
173                             0.0f,
174                             G_PARAM_READABLE |
175                             G_PARAM_STATIC_STRINGS);
176 
177     properties[PROP_FADE] =
178         g_param_spec_float ("fade",
179                             "Fade",
180                             "Fade value of the stream control",
181                             -1.0f,
182                             1.0f,
183                             0.0f,
184                             G_PARAM_READABLE |
185                             G_PARAM_STATIC_STRINGS);
186 
187     g_object_class_install_properties (object_class, N_PROPERTIES, properties);
188 
189     signals[MONITOR_VALUE] =
190         g_signal_new ("monitor-value",
191                       G_TYPE_FROM_CLASS (klass),
192                       G_SIGNAL_RUN_FIRST,
193                       G_STRUCT_OFFSET (MateMixerStreamControlClass, monitor_value),
194                       NULL,
195                       NULL,
196                       g_cclosure_marshal_VOID__DOUBLE,
197                       G_TYPE_NONE,
198                       1,
199                       G_TYPE_DOUBLE);
200 }
201 
202 static void
mate_mixer_stream_control_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)203 mate_mixer_stream_control_get_property (GObject    *object,
204                                         guint       param_id,
205                                         GValue     *value,
206                                         GParamSpec *pspec)
207 {
208     MateMixerStreamControl *control;
209 
210     control = MATE_MIXER_STREAM_CONTROL (object);
211 
212     switch (param_id) {
213     case PROP_NAME:
214         g_value_set_string (value, control->priv->name);
215         break;
216     case PROP_LABEL:
217         g_value_set_string (value, control->priv->label);
218         break;
219     case PROP_FLAGS:
220         g_value_set_flags (value, control->priv->flags);
221         break;
222     case PROP_ROLE:
223         g_value_set_enum (value, control->priv->role);
224         break;
225     case PROP_MEDIA_ROLE:
226         g_value_set_enum (value, control->priv->media_role);
227         break;
228     case PROP_STREAM:
229         g_value_set_object (value, control->priv->stream);
230         break;
231 
232     default:
233         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
234         break;
235     }
236 }
237 
238 static void
mate_mixer_stream_control_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)239 mate_mixer_stream_control_set_property (GObject      *object,
240                                         guint         param_id,
241                                         const GValue *value,
242                                         GParamSpec   *pspec)
243 {
244     MateMixerStreamControl *control;
245 
246     control = MATE_MIXER_STREAM_CONTROL (object);
247 
248     switch (param_id) {
249     case PROP_NAME:
250         /* Construct-only string */
251         control->priv->name = g_value_dup_string (value);
252         break;
253     case PROP_LABEL:
254         /* Construct-only string */
255         control->priv->label = g_value_dup_string (value);
256         break;
257     case PROP_FLAGS:
258         control->priv->flags = g_value_get_flags (value);
259         break;
260     case PROP_ROLE:
261         control->priv->role = g_value_get_enum (value);
262         break;
263     case PROP_MEDIA_ROLE:
264         control->priv->media_role = g_value_get_enum (value);
265         break;
266     case PROP_STREAM:
267         /* Construct-only object */
268         control->priv->stream = g_value_get_object (value);
269 
270         if (control->priv->stream != NULL)
271             g_object_add_weak_pointer (G_OBJECT (control->priv->stream),
272                                        (gpointer *) &control->priv->stream);
273         break;
274 
275     default:
276         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
277         break;
278     }
279 }
280 
281 static void
mate_mixer_stream_control_init(MateMixerStreamControl * control)282 mate_mixer_stream_control_init (MateMixerStreamControl *control)
283 {
284     control->priv = mate_mixer_stream_control_get_instance_private (control);
285 }
286 
287 static void
mate_mixer_stream_control_finalize(GObject * object)288 mate_mixer_stream_control_finalize (GObject *object)
289 {
290     MateMixerStreamControl *control;
291 
292     control = MATE_MIXER_STREAM_CONTROL (object);
293 
294     g_free (control->priv->name);
295     g_free (control->priv->label);
296 
297     G_OBJECT_CLASS (mate_mixer_stream_control_parent_class)->finalize (object);
298 }
299 
300 /**
301  * mate_mixer_stream_control_get_name:
302  * @control: a #MateMixerStreamControl
303  */
304 const gchar *
mate_mixer_stream_control_get_name(MateMixerStreamControl * control)305 mate_mixer_stream_control_get_name (MateMixerStreamControl *control)
306 {
307     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), NULL);
308 
309     return control->priv->name;
310 }
311 
312 /**
313  * mate_mixer_stream_control_get_label:
314  * @control: a #MateMixerStreamControl
315  */
316 const gchar *
mate_mixer_stream_control_get_label(MateMixerStreamControl * control)317 mate_mixer_stream_control_get_label (MateMixerStreamControl *control)
318 {
319     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), NULL);
320 
321     return control->priv->label;
322 }
323 
324 /**
325  * mate_mixer_stream_control_get_flags:
326  * @control: a #MateMixerStreamControl
327  */
328 MateMixerStreamControlFlags
mate_mixer_stream_control_get_flags(MateMixerStreamControl * control)329 mate_mixer_stream_control_get_flags (MateMixerStreamControl *control)
330 {
331     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), MATE_MIXER_STREAM_CONTROL_NO_FLAGS);
332 
333     return control->priv->flags;
334 }
335 
336 /**
337  * mate_mixer_stream_control_get_role:
338  * @control: a #MateMixerStreamControl
339  */
340 MateMixerStreamControlRole
mate_mixer_stream_control_get_role(MateMixerStreamControl * control)341 mate_mixer_stream_control_get_role (MateMixerStreamControl *control)
342 {
343     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), MATE_MIXER_STREAM_CONTROL_ROLE_UNKNOWN);
344 
345     return control->priv->role;
346 }
347 
348 /**
349  * mate_mixer_stream_control_get_media_role:
350  * @control: a #MateMixerStreamControl
351  */
352 MateMixerStreamControlMediaRole
mate_mixer_stream_control_get_media_role(MateMixerStreamControl * control)353 mate_mixer_stream_control_get_media_role (MateMixerStreamControl *control)
354 {
355     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), MATE_MIXER_STREAM_CONTROL_MEDIA_ROLE_UNKNOWN);
356 
357     return control->priv->media_role;
358 }
359 
360 /**
361  * mate_mixer_stream_control_get_app_info:
362  * @control: a #MateMixerStreamControl
363  */
364 MateMixerAppInfo *
mate_mixer_stream_control_get_app_info(MateMixerStreamControl * control)365 mate_mixer_stream_control_get_app_info (MateMixerStreamControl *control)
366 {
367     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), NULL);
368 
369     if (control->priv->role == MATE_MIXER_STREAM_CONTROL_ROLE_APPLICATION) {
370         MateMixerStreamControlClass *klass =
371             MATE_MIXER_STREAM_CONTROL_GET_CLASS (control);
372 
373         /* Implementation required for application role controls */
374         return klass->get_app_info (control);
375     }
376     return NULL;
377 }
378 
379 /**
380  * mate_mixer_stream_control_get_stream:
381  * @control: a #MateMixerStreamControl
382  */
383 MateMixerStream *
mate_mixer_stream_control_get_stream(MateMixerStreamControl * control)384 mate_mixer_stream_control_get_stream (MateMixerStreamControl *control)
385 {
386     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), NULL);
387 
388     return control->priv->stream;
389 }
390 
391 /**
392  * mate_mixer_stream_control_set_stream:
393  * @control: a #MateMixerStreamControl
394  * @stream: a #MateMixerStream
395  */
396 gboolean
mate_mixer_stream_control_set_stream(MateMixerStreamControl * control,MateMixerStream * stream)397 mate_mixer_stream_control_set_stream (MateMixerStreamControl *control,
398                                       MateMixerStream        *stream)
399 {
400     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), FALSE);
401     g_return_val_if_fail (stream == NULL || MATE_MIXER_IS_STREAM (stream), FALSE);
402 
403     if ((control->priv->flags & MATE_MIXER_STREAM_CONTROL_MOVABLE) == 0)
404         return FALSE;
405 
406     if (control->priv->stream != stream) {
407         MateMixerStreamControlClass *klass =
408             MATE_MIXER_STREAM_CONTROL_GET_CLASS (control);
409 
410         /* Implementation required when the flag is available */
411         if (klass->set_stream (control, stream) == FALSE)
412             return FALSE;
413 
414         _mate_mixer_stream_control_set_stream (control, stream);
415     }
416     return TRUE;
417 }
418 
419 /**
420  * mate_mixer_stream_control_get_mute:
421  * @control: a #MateMixerStreamControl
422  */
423 gboolean
mate_mixer_stream_control_get_mute(MateMixerStreamControl * control)424 mate_mixer_stream_control_get_mute (MateMixerStreamControl *control)
425 {
426     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), FALSE);
427 
428     return control->priv->mute;
429 }
430 
431 /**
432  * mate_mixer_stream_control_set_mute:
433  * @control: a #MateMixerStreamControl
434  * @mute: the mute toggle state to set
435  */
436 gboolean
mate_mixer_stream_control_set_mute(MateMixerStreamControl * control,gboolean mute)437 mate_mixer_stream_control_set_mute (MateMixerStreamControl *control, gboolean mute)
438 {
439     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), FALSE);
440 
441     if ((control->priv->flags & MATE_MIXER_STREAM_CONTROL_MUTE_WRITABLE) == 0)
442         return FALSE;
443 
444     if (control->priv->mute != mute) {
445         MateMixerStreamControlClass *klass =
446             MATE_MIXER_STREAM_CONTROL_GET_CLASS (control);
447 
448         /* Implementation required when the flag is available */
449         if (klass->set_mute (control, mute) == FALSE)
450             return FALSE;
451 
452         _mate_mixer_stream_control_set_mute (control, mute);
453     }
454     return TRUE;
455 }
456 
457 /**
458  * mate_mixer_stream_control_get_num_channels:
459  * @control: a #MateMixerStreamControl
460  */
461 guint
mate_mixer_stream_control_get_num_channels(MateMixerStreamControl * control)462 mate_mixer_stream_control_get_num_channels (MateMixerStreamControl *control)
463 {
464     MateMixerStreamControlClass *klass;
465 
466     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), 0);
467 
468     klass = MATE_MIXER_STREAM_CONTROL_GET_CLASS (control);
469 
470     if (klass->get_num_channels != NULL)
471         return klass->get_num_channels (control);
472 
473     return 0;
474 }
475 
476 /**
477  * mate_mixer_stream_control_get_volume:
478  * @control: a #MateMixerStreamControl
479  */
480 guint
mate_mixer_stream_control_get_volume(MateMixerStreamControl * control)481 mate_mixer_stream_control_get_volume (MateMixerStreamControl *control)
482 {
483     MateMixerStreamControlClass *klass;
484 
485     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), 0);
486 
487     klass = MATE_MIXER_STREAM_CONTROL_GET_CLASS (control);
488 
489     if (control->priv->flags & MATE_MIXER_STREAM_CONTROL_VOLUME_READABLE) {
490         /* Implementation required when the flag is available */
491         return klass->get_volume (control);
492     }
493     return klass->get_min_volume (control);
494 }
495 
496 /**
497  * mate_mixer_stream_control_set_volume:
498  * @control: a #MateMixerStreamControl
499  * @volume: the volume to set
500  */
501 gboolean
mate_mixer_stream_control_set_volume(MateMixerStreamControl * control,guint volume)502 mate_mixer_stream_control_set_volume (MateMixerStreamControl *control, guint volume)
503 {
504     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), FALSE);
505 
506     if (control->priv->flags & MATE_MIXER_STREAM_CONTROL_VOLUME_WRITABLE) {
507         MateMixerStreamControlClass *klass =
508             MATE_MIXER_STREAM_CONTROL_GET_CLASS (control);
509 
510         /* Implementation required when the flag is available */
511         return klass->set_volume (control, volume);
512     }
513     return FALSE;
514 }
515 
516 /**
517  * mate_mixer_stream_control_get_decibel:
518  * @control: a #MateMixerStreamControl
519  */
520 gdouble
mate_mixer_stream_control_get_decibel(MateMixerStreamControl * control)521 mate_mixer_stream_control_get_decibel (MateMixerStreamControl *control)
522 {
523     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), -MATE_MIXER_INFINITY);
524 
525     if (control->priv->flags & MATE_MIXER_STREAM_CONTROL_HAS_DECIBEL &&
526         control->priv->flags & MATE_MIXER_STREAM_CONTROL_VOLUME_READABLE) {
527         MateMixerStreamControlClass *klass =
528             MATE_MIXER_STREAM_CONTROL_GET_CLASS (control);
529 
530         /* Implementation required when the flags are available */
531         return klass->get_decibel (control);
532     }
533     return -MATE_MIXER_INFINITY;
534 }
535 
536 /**
537  * mate_mixer_stream_control_set_decibel:
538  * @control: a #MateMixerStreamControl
539  * @decibel: the volume to set in decibels
540  */
541 gboolean
mate_mixer_stream_control_set_decibel(MateMixerStreamControl * control,gdouble decibel)542 mate_mixer_stream_control_set_decibel (MateMixerStreamControl *control, gdouble decibel)
543 {
544     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), FALSE);
545 
546     if (control->priv->flags & MATE_MIXER_STREAM_CONTROL_HAS_DECIBEL &&
547         control->priv->flags & MATE_MIXER_STREAM_CONTROL_VOLUME_WRITABLE) {
548         MateMixerStreamControlClass *klass =
549             MATE_MIXER_STREAM_CONTROL_GET_CLASS (control);
550 
551         /* Implementation required when the flags are available */
552         return klass->set_decibel (control, decibel);
553     }
554     return FALSE;
555 }
556 
557 /**
558  * mate_mixer_stream_control_has_channel_position:
559  * @control: a #MateMixerStreamControl
560  * @position: to channel position to check
561  */
562 gboolean
mate_mixer_stream_control_has_channel_position(MateMixerStreamControl * control,MateMixerChannelPosition position)563 mate_mixer_stream_control_has_channel_position (MateMixerStreamControl  *control,
564                                                 MateMixerChannelPosition position)
565 {
566     MateMixerStreamControlClass *klass;
567 
568     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), FALSE);
569 
570     klass = MATE_MIXER_STREAM_CONTROL_GET_CLASS (control);
571 
572     if (klass->has_channel_position != NULL)
573         return klass->has_channel_position (control, position);
574 
575     return FALSE;
576 }
577 
578 /**
579  * mate_mixer_stream_control_get_channel_position:
580  * @control: a #MateMixerStreamControl
581  * @channel: a channel index
582  */
583 MateMixerChannelPosition
mate_mixer_stream_control_get_channel_position(MateMixerStreamControl * control,guint channel)584 mate_mixer_stream_control_get_channel_position (MateMixerStreamControl *control, guint channel)
585 {
586     MateMixerStreamControlClass *klass;
587 
588     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), MATE_MIXER_CHANNEL_UNKNOWN);
589 
590     klass = MATE_MIXER_STREAM_CONTROL_GET_CLASS (control);
591 
592     if (klass->get_channel_position != NULL)
593         return klass->get_channel_position (control, channel);
594 
595     return MATE_MIXER_CHANNEL_UNKNOWN;
596 }
597 
598 /**
599  * mate_mixer_stream_control_get_channel_volume:
600  * @control: a #MateMixerStreamControl
601  * @channel: a channel index
602  */
603 guint
mate_mixer_stream_control_get_channel_volume(MateMixerStreamControl * control,guint channel)604 mate_mixer_stream_control_get_channel_volume (MateMixerStreamControl *control, guint channel)
605 {
606     MateMixerStreamControlClass *klass;
607 
608     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), 0);
609 
610     klass = MATE_MIXER_STREAM_CONTROL_GET_CLASS (control);
611 
612     if (control->priv->flags & MATE_MIXER_STREAM_CONTROL_VOLUME_READABLE) {
613         /* Implementation required when the flag is available */
614         return klass->get_channel_volume (control, channel);
615     }
616     return klass->get_min_volume (control);
617 }
618 
619 /**
620  * mate_mixer_stream_control_set_channel_volume:
621  * @control: a #MateMixerStreamControl
622  * @channel: a channel index
623  * @volume: the volume to set
624  */
625 gboolean
mate_mixer_stream_control_set_channel_volume(MateMixerStreamControl * control,guint channel,guint volume)626 mate_mixer_stream_control_set_channel_volume (MateMixerStreamControl *control,
627                                               guint                   channel,
628                                               guint                   volume)
629 {
630     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), FALSE);
631 
632     if (control->priv->flags & MATE_MIXER_STREAM_CONTROL_VOLUME_WRITABLE) {
633         MateMixerStreamControlClass *klass =
634             MATE_MIXER_STREAM_CONTROL_GET_CLASS (control);
635 
636         /* Implementation required when the flag is available */
637         return klass->set_channel_volume (control, channel, volume);
638     }
639     return FALSE;
640 }
641 
642 /**
643  * mate_mixer_stream_control_get_channel_decibel:
644  * @control: a #MateMixerStreamControl
645  * @channel: a channel index
646  */
647 gdouble
mate_mixer_stream_control_get_channel_decibel(MateMixerStreamControl * control,guint channel)648 mate_mixer_stream_control_get_channel_decibel (MateMixerStreamControl *control, guint channel)
649 {
650     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), -MATE_MIXER_INFINITY);
651 
652     if (control->priv->flags & MATE_MIXER_STREAM_CONTROL_HAS_DECIBEL &&
653         control->priv->flags & MATE_MIXER_STREAM_CONTROL_VOLUME_READABLE) {
654         MateMixerStreamControlClass *klass =
655             MATE_MIXER_STREAM_CONTROL_GET_CLASS (control);
656 
657         /* Implementation required when the flags are available */
658         return klass->get_channel_decibel (control, channel);
659     }
660     return -MATE_MIXER_INFINITY;
661 }
662 
663 /**
664  * mate_mixer_stream_control_set_channel_decibel:
665  * @control: a #MateMixerStreamControl
666  * @channel: a channel index
667  * @decibel: the volume to set in decibels
668  */
669 gboolean
mate_mixer_stream_control_set_channel_decibel(MateMixerStreamControl * control,guint channel,gdouble decibel)670 mate_mixer_stream_control_set_channel_decibel (MateMixerStreamControl *control,
671                                                guint                   channel,
672                                                gdouble                 decibel)
673 {
674     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), FALSE);
675 
676     if (control->priv->flags & MATE_MIXER_STREAM_CONTROL_HAS_DECIBEL &&
677         control->priv->flags & MATE_MIXER_STREAM_CONTROL_VOLUME_WRITABLE) {
678         MateMixerStreamControlClass *klass =
679             MATE_MIXER_STREAM_CONTROL_GET_CLASS (control);
680 
681         /* Implementation required when the flags are available */
682         return klass->set_channel_decibel (control, channel, decibel);
683     }
684     return FALSE;
685 }
686 
687 /**
688  * mate_mixer_stream_control_get_balance:
689  * @control: a #MateMixerStreamControl
690  */
691 gfloat
mate_mixer_stream_control_get_balance(MateMixerStreamControl * control)692 mate_mixer_stream_control_get_balance (MateMixerStreamControl *control)
693 {
694     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), 0.0f);
695 
696     if (control->priv->flags & MATE_MIXER_STREAM_CONTROL_CAN_BALANCE)
697         return control->priv->balance;
698     else
699         return 0.0f;
700 }
701 
702 /**
703  * mate_mixer_stream_control_set_balance:
704  * @control: a #MateMixerStreamControl
705  * @balance: the balance value
706  */
707 gboolean
mate_mixer_stream_control_set_balance(MateMixerStreamControl * control,gfloat balance)708 mate_mixer_stream_control_set_balance (MateMixerStreamControl *control, gfloat balance)
709 {
710     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), FALSE);
711     g_return_val_if_fail (balance >= -1.0f && balance <= 1.0f, FALSE);
712 
713     if ((control->priv->flags & MATE_MIXER_STREAM_CONTROL_CAN_BALANCE) == 0)
714         return FALSE;
715 
716     if (control->priv->balance != balance) {
717         MateMixerStreamControlClass *klass =
718             MATE_MIXER_STREAM_CONTROL_GET_CLASS (control);
719 
720         /* Implementation required when the flag is available */
721         if (klass->set_balance (control, balance) == FALSE)
722             return FALSE;
723 
724         _mate_mixer_stream_control_set_balance (control, balance);
725     }
726     return TRUE;
727 }
728 
729 /**
730  * mate_mixer_stream_control_get_fade:
731  * @control: a #MateMixerStreamControl
732  */
733 gfloat
mate_mixer_stream_control_get_fade(MateMixerStreamControl * control)734 mate_mixer_stream_control_get_fade (MateMixerStreamControl *control)
735 {
736     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), 0.0f);
737 
738     if (control->priv->flags & MATE_MIXER_STREAM_CONTROL_CAN_FADE)
739         return control->priv->fade;
740     else
741         return 0.0f;
742 }
743 
744 /**
745  * mate_mixer_stream_control_set_fade:
746  * @control: a #MateMixerStreamControl
747  * @fade: the fade value
748  */
749 gboolean
mate_mixer_stream_control_set_fade(MateMixerStreamControl * control,gfloat fade)750 mate_mixer_stream_control_set_fade (MateMixerStreamControl *control, gfloat fade)
751 {
752     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), FALSE);
753     g_return_val_if_fail (fade >= -1.0f && fade <= 1.0f, FALSE);
754 
755     if ((control->priv->flags & MATE_MIXER_STREAM_CONTROL_CAN_FADE) == 0)
756         return FALSE;
757 
758     if (control->priv->fade != fade) {
759         MateMixerStreamControlClass *klass =
760             MATE_MIXER_STREAM_CONTROL_GET_CLASS (control);
761 
762         /* Implementation required when the flag is available */
763         if (klass->set_fade (control, fade) == FALSE)
764             return FALSE;
765 
766         _mate_mixer_stream_control_set_fade (control, fade);
767     }
768     return TRUE;
769 }
770 
771 /**
772  * mate_mixer_stream_control_get_monitor_enabled:
773  * @control: a #MateMixerStreamControl
774  */
775 gboolean
mate_mixer_stream_control_get_monitor_enabled(MateMixerStreamControl * control)776 mate_mixer_stream_control_get_monitor_enabled (MateMixerStreamControl *control)
777 {
778     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), FALSE);
779 
780     if (control->priv->flags & MATE_MIXER_STREAM_CONTROL_HAS_MONITOR) {
781         MateMixerStreamControlClass *klass =
782             MATE_MIXER_STREAM_CONTROL_GET_CLASS (control);
783 
784         /* Implementation required when the flag is available */
785         return klass->get_monitor_enabled (control);
786     }
787     return FALSE;
788 }
789 
790 /**
791  * mate_mixer_stream_control_set_monitor_enabled:
792  * @control: a #MateMixerStreamControl
793  * @enabled: a boolean value
794  */
795 gboolean
mate_mixer_stream_control_set_monitor_enabled(MateMixerStreamControl * control,gboolean enabled)796 mate_mixer_stream_control_set_monitor_enabled (MateMixerStreamControl *control, gboolean enabled)
797 {
798     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), FALSE);
799 
800     if ((control->priv->flags & MATE_MIXER_STREAM_CONTROL_HAS_MONITOR) == 0)
801         return FALSE;
802 
803     /* Implementation required when the flag is available */
804     return MATE_MIXER_STREAM_CONTROL_GET_CLASS (control)->set_monitor_enabled (control, enabled);
805 }
806 
807 /**
808  * mate_mixer_stream_control_get_min_volume:
809  * @control: a #MateMixerStreamControl
810  */
811 guint
mate_mixer_stream_control_get_min_volume(MateMixerStreamControl * control)812 mate_mixer_stream_control_get_min_volume (MateMixerStreamControl *control)
813 {
814     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), 0);
815 
816     /* Implementation required */
817     return MATE_MIXER_STREAM_CONTROL_GET_CLASS (control)->get_min_volume (control);
818 }
819 
820 /**
821  * mate_mixer_stream_control_get_max_volume:
822  * @control: a #MateMixerStreamControl
823  */
824 guint
mate_mixer_stream_control_get_max_volume(MateMixerStreamControl * control)825 mate_mixer_stream_control_get_max_volume (MateMixerStreamControl *control)
826 {
827     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), 0);
828 
829     /* Implementation required */
830     return MATE_MIXER_STREAM_CONTROL_GET_CLASS (control)->get_max_volume (control);
831 }
832 
833 /**
834  * mate_mixer_stream_control_get_normal_volume:
835  * @control: a #MateMixerStreamControl
836  */
837 guint
mate_mixer_stream_control_get_normal_volume(MateMixerStreamControl * control)838 mate_mixer_stream_control_get_normal_volume (MateMixerStreamControl *control)
839 {
840     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), 0);
841 
842     /* Implementation required */
843     return MATE_MIXER_STREAM_CONTROL_GET_CLASS (control)->get_normal_volume (control);
844 }
845 
846 /**
847  * mate_mixer_stream_control_get_base_volume:
848  * @control: a #MateMixerStreamControl
849  */
850 guint
mate_mixer_stream_control_get_base_volume(MateMixerStreamControl * control)851 mate_mixer_stream_control_get_base_volume (MateMixerStreamControl *control)
852 {
853     g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control), 0);
854 
855     /* Implementation required */
856     return MATE_MIXER_STREAM_CONTROL_GET_CLASS (control)->get_base_volume (control);
857 }
858 
859 /* Protected functions */
860 void
_mate_mixer_stream_control_set_flags(MateMixerStreamControl * control,MateMixerStreamControlFlags flags)861 _mate_mixer_stream_control_set_flags (MateMixerStreamControl     *control,
862                                       MateMixerStreamControlFlags flags)
863 {
864     g_return_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control));
865 
866     if (control->priv->flags == flags)
867         return;
868 
869     control->priv->flags = flags;
870 
871     g_object_notify_by_pspec (G_OBJECT (control), properties[PROP_FLAGS]);
872 }
873 
874 void
_mate_mixer_stream_control_set_stream(MateMixerStreamControl * control,MateMixerStream * stream)875 _mate_mixer_stream_control_set_stream (MateMixerStreamControl *control,
876                                        MateMixerStream        *stream)
877 {
878     g_return_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control));
879     g_return_if_fail (stream == NULL || MATE_MIXER_IS_STREAM (stream));
880 
881     if (control->priv->stream == stream)
882         return;
883 
884     if (control->priv->stream != NULL)
885         g_object_remove_weak_pointer (G_OBJECT (control->priv->stream),
886                                       (gpointer *) &control->priv->stream);
887 
888     if (stream != NULL) {
889         control->priv->stream = stream;
890         g_object_add_weak_pointer (G_OBJECT (control->priv->stream),
891                                    (gpointer *) &control->priv->stream);
892     } else
893         control->priv->stream = NULL;
894 
895     g_object_notify_by_pspec (G_OBJECT (control), properties[PROP_STREAM]);
896 }
897 
898 void
_mate_mixer_stream_control_set_mute(MateMixerStreamControl * control,gboolean mute)899 _mate_mixer_stream_control_set_mute (MateMixerStreamControl *control, gboolean mute)
900 {
901     g_return_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control));
902 
903     if (control->priv->mute == mute)
904         return;
905 
906     control->priv->mute = mute;
907 
908     g_object_notify_by_pspec (G_OBJECT (control), properties[PROP_MUTE]);
909 }
910 
911 void
_mate_mixer_stream_control_set_balance(MateMixerStreamControl * control,gfloat balance)912 _mate_mixer_stream_control_set_balance (MateMixerStreamControl *control, gfloat balance)
913 {
914     g_return_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control));
915 
916     if (control->priv->balance == balance)
917         return;
918 
919     control->priv->balance = balance;
920 
921     g_object_notify_by_pspec (G_OBJECT (control), properties[PROP_BALANCE]);
922 }
923 
924 void
_mate_mixer_stream_control_set_fade(MateMixerStreamControl * control,gfloat fade)925 _mate_mixer_stream_control_set_fade (MateMixerStreamControl *control, gfloat fade)
926 {
927     g_return_if_fail (MATE_MIXER_IS_STREAM_CONTROL (control));
928 
929     if (control->priv->fade == fade)
930         return;
931 
932     control->priv->fade = fade;
933 
934     g_object_notify_by_pspec (G_OBJECT (control), properties[PROP_FADE]);
935 }
936