gnome-shell-3.6.3.1/src/gvc/gvc-mixer-stream.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found gvc/gvc-mixer-stream.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
  1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
  2  *
  3  * Copyright (C) 2008 William Jon McCann
  4  *
  5  * This program is free software; you can redistribute it and/or modify
  6  * it under the terms of the GNU General Public License as published by
  7  * the Free Software Foundation; either version 2 of the License, or
  8  * (at your option) any later version.
  9  *
 10  * This program is distributed in the hope that it will be useful,
 11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13  * GNU General Public License for more details.
 14  *
 15  * You should have received a copy of the GNU General Public License
 16  * along with this program; if not, write to the Free Software
 17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 18  *
 19  */
 20 
 21 #include "config.h"
 22 
 23 #include <stdlib.h>
 24 #include <stdio.h>
 25 #include <unistd.h>
 26 
 27 #include <glib.h>
 28 #include <glib/gi18n-lib.h>
 29 
 30 #include <pulse/pulseaudio.h>
 31 
 32 #include "gvc-mixer-stream.h"
 33 #include "gvc-mixer-stream-private.h"
 34 #include "gvc-channel-map-private.h"
 35 
 36 #define GVC_MIXER_STREAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_STREAM, GvcMixerStreamPrivate))
 37 
 38 static guint32 stream_serial = 1;
 39 
 40 struct GvcMixerStreamPrivate
 41 {
 42         pa_context    *pa_context;
 43         guint          id;
 44         guint          index;
 45         gint           card_index;
 46         GvcChannelMap *channel_map;
 47         char          *name;
 48         char          *description;
 49         char          *application_id;
 50         char          *icon_name;
 51         gboolean       is_muted;
 52         gboolean       can_decibel;
 53         gboolean       is_event_stream;
 54         gboolean       is_virtual;
 55         pa_volume_t    base_volume;
 56         pa_operation  *change_volume_op;
 57         char          *port;
 58         char          *human_port;
 59         GList         *ports;
 60 };
 61 
 62 enum
 63 {
 64         PROP_0,
 65         PROP_ID,
 66         PROP_PA_CONTEXT,
 67         PROP_CHANNEL_MAP,
 68         PROP_INDEX,
 69         PROP_NAME,
 70         PROP_DESCRIPTION,
 71         PROP_APPLICATION_ID,
 72         PROP_ICON_NAME,
 73         PROP_VOLUME,
 74         PROP_DECIBEL,
 75         PROP_IS_MUTED,
 76         PROP_CAN_DECIBEL,
 77         PROP_IS_EVENT_STREAM,
 78         PROP_IS_VIRTUAL,
 79         PROP_CARD_INDEX,
 80         PROP_PORT,
 81 };
 82 
 83 static void     gvc_mixer_stream_class_init (GvcMixerStreamClass *klass);
 84 static void     gvc_mixer_stream_init       (GvcMixerStream      *mixer_stream);
 85 static void     gvc_mixer_stream_finalize   (GObject            *object);
 86 
 87 G_DEFINE_ABSTRACT_TYPE (GvcMixerStream, gvc_mixer_stream, G_TYPE_OBJECT)
 88 
 89 static guint32
 90 get_next_stream_serial (void)
 91 {
 92         guint32 serial;
 93 
 94         serial = stream_serial++;
 95 
 96         if ((gint32)stream_serial < 0) {
 97                 stream_serial = 1;
 98         }
 99 
100         return serial;
101 }
102 
103 pa_context *
104 gvc_mixer_stream_get_pa_context (GvcMixerStream *stream)
105 {
106         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
107         return stream->priv->pa_context;
108 }
109 
110 guint
111 gvc_mixer_stream_get_index (GvcMixerStream *stream)
112 {
113         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
114         return stream->priv->index;
115 }
116 
117 guint
118 gvc_mixer_stream_get_id (GvcMixerStream *stream)
119 {
120         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
121         return stream->priv->id;
122 }
123 
124 const GvcChannelMap *
125 gvc_mixer_stream_get_channel_map (GvcMixerStream *stream)
126 {
127         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
128         return stream->priv->channel_map;
129 }
130 
131 /**
132  * gvc_mixer_stream_get_volume:
133  * @stream:
134  *
135  * Returns: (type guint32) (transfer none):
136  */
137 pa_volume_t
138 gvc_mixer_stream_get_volume (GvcMixerStream *stream)
139 {
140         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
141 
142         return (pa_volume_t) gvc_channel_map_get_volume(stream->priv->channel_map)[VOLUME];
143 }
144 
145 gdouble
146 gvc_mixer_stream_get_decibel (GvcMixerStream *stream)
147 {
148         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
149 
150         return pa_sw_volume_to_dB(
151                         (pa_volume_t) gvc_channel_map_get_volume(stream->priv->channel_map)[VOLUME]);
152 }
153 
154 /**
155  * gvc_mixer_stream_set_volume:
156  * @stream:
157  * @volume: (type guint32):
158  *
159  * Returns:
160  */
161 gboolean
162 gvc_mixer_stream_set_volume (GvcMixerStream *stream,
163                               pa_volume_t     volume)
164 {
165         pa_cvolume cv;
166 
167         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
168 
169         cv = *gvc_channel_map_get_cvolume(stream->priv->channel_map);
170         pa_cvolume_scale(&cv, volume);
171 
172         if (!pa_cvolume_equal(gvc_channel_map_get_cvolume(stream->priv->channel_map), &cv)) {
173                 gvc_channel_map_volume_changed(stream->priv->channel_map, &cv, FALSE);
174                 g_object_notify (G_OBJECT (stream), "volume");
175                 return TRUE;
176         }
177 
178         return FALSE;
179 }
180 
181 gboolean
182 gvc_mixer_stream_set_decibel (GvcMixerStream *stream,
183                               gdouble         db)
184 {
185         pa_cvolume cv;
186 
187         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
188 
189         cv = *gvc_channel_map_get_cvolume(stream->priv->channel_map);
190         pa_cvolume_scale(&cv, pa_sw_volume_from_dB(db));
191 
192         if (!pa_cvolume_equal(gvc_channel_map_get_cvolume(stream->priv->channel_map), &cv)) {
193                 gvc_channel_map_volume_changed(stream->priv->channel_map, &cv, FALSE);
194                 g_object_notify (G_OBJECT (stream), "volume");
195         }
196 
197         return TRUE;
198 }
199 
200 gboolean
201 gvc_mixer_stream_get_is_muted  (GvcMixerStream *stream)
202 {
203         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
204         return stream->priv->is_muted;
205 }
206 
207 gboolean
208 gvc_mixer_stream_get_can_decibel (GvcMixerStream *stream)
209 {
210         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
211         return stream->priv->can_decibel;
212 }
213 
214 gboolean
215 gvc_mixer_stream_set_is_muted  (GvcMixerStream *stream,
216                                 gboolean        is_muted)
217 {
218         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
219 
220         if (is_muted != stream->priv->is_muted) {
221                 stream->priv->is_muted = is_muted;
222                 g_object_notify (G_OBJECT (stream), "is-muted");
223         }
224 
225         return TRUE;
226 }
227 
228 gboolean
229 gvc_mixer_stream_set_can_decibel  (GvcMixerStream *stream,
230                                    gboolean        can_decibel)
231 {
232         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
233 
234         if (can_decibel != stream->priv->can_decibel) {
235                 stream->priv->can_decibel = can_decibel;
236                 g_object_notify (G_OBJECT (stream), "can-decibel");
237         }
238 
239         return TRUE;
240 }
241 
242 const char *
243 gvc_mixer_stream_get_name (GvcMixerStream *stream)
244 {
245         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
246         return stream->priv->name;
247 }
248 
249 const char *
250 gvc_mixer_stream_get_description (GvcMixerStream *stream)
251 {
252         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
253         return stream->priv->description;
254 }
255 
256 gboolean
257 gvc_mixer_stream_set_name (GvcMixerStream *stream,
258                            const char     *name)
259 {
260         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
261 
262         g_free (stream->priv->name);
263         stream->priv->name = g_strdup (name);
264         g_object_notify (G_OBJECT (stream), "name");
265 
266         return TRUE;
267 }
268 
269 gboolean
270 gvc_mixer_stream_set_description (GvcMixerStream *stream,
271                                   const char     *description)
272 {
273         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
274 
275         g_free (stream->priv->description);
276         stream->priv->description = g_strdup (description);
277         g_object_notify (G_OBJECT (stream), "description");
278 
279         return TRUE;
280 }
281 
282 gboolean
283 gvc_mixer_stream_is_event_stream (GvcMixerStream *stream)
284 {
285         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
286 
287         return stream->priv->is_event_stream;
288 }
289 
290 gboolean
291 gvc_mixer_stream_set_is_event_stream (GvcMixerStream *stream,
292                                       gboolean is_event_stream)
293 {
294         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
295 
296         stream->priv->is_event_stream = is_event_stream;
297         g_object_notify (G_OBJECT (stream), "is-event-stream");
298 
299         return TRUE;
300 }
301 
302 gboolean
303 gvc_mixer_stream_is_virtual (GvcMixerStream *stream)
304 {
305         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
306 
307         return stream->priv->is_virtual;
308 }
309 
310 gboolean
311 gvc_mixer_stream_set_is_virtual (GvcMixerStream *stream,
312                                  gboolean is_virtual)
313 {
314         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
315 
316         stream->priv->is_virtual = is_virtual;
317         g_object_notify (G_OBJECT (stream), "is-virtual");
318 
319         return TRUE;
320 }
321 
322 const char *
323 gvc_mixer_stream_get_application_id (GvcMixerStream *stream)
324 {
325         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
326         return stream->priv->application_id;
327 }
328 
329 gboolean
330 gvc_mixer_stream_set_application_id (GvcMixerStream *stream,
331                                      const char *application_id)
332 {
333         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
334 
335         g_free (stream->priv->application_id);
336         stream->priv->application_id = g_strdup (application_id);
337         g_object_notify (G_OBJECT (stream), "application-id");
338 
339         return TRUE;
340 }
341 
342 static void
343 on_channel_map_volume_changed (GvcChannelMap  *channel_map,
344                                gboolean        set,
345                                GvcMixerStream *stream)
346 {
347         if (set == TRUE)
348                 gvc_mixer_stream_push_volume (stream);
349 
350         g_object_notify (G_OBJECT (stream), "volume");
351 }
352 
353 static gboolean
354 gvc_mixer_stream_set_channel_map (GvcMixerStream *stream,
355                                   GvcChannelMap  *channel_map)
356 {
357         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
358 
359         if (channel_map != NULL) {
360                 g_object_ref (channel_map);
361         }
362 
363         if (stream->priv->channel_map != NULL) {
364                 g_signal_handlers_disconnect_by_func (stream->priv->channel_map,
365                                                       on_channel_map_volume_changed,
366                                                       stream);
367                 g_object_unref (stream->priv->channel_map);
368         }
369 
370         stream->priv->channel_map = channel_map;
371 
372         if (stream->priv->channel_map != NULL) {
373                 g_signal_connect (stream->priv->channel_map,
374                                   "volume-changed",
375                                   G_CALLBACK (on_channel_map_volume_changed),
376                                   stream);
377 
378                 g_object_notify (G_OBJECT (stream), "channel-map");
379         }
380 
381         return TRUE;
382 }
383 
384 const char *
385 gvc_mixer_stream_get_icon_name (GvcMixerStream *stream)
386 {
387         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
388         return stream->priv->icon_name;
389 }
390 
391 /**
392  * gvc_mixer_stream_get_gicon:
393  * @stream: a #GvcMixerStream
394  *
395  * Returns: (transfer full): a new #GIcon
396  */
397 GIcon *
398 gvc_mixer_stream_get_gicon (GvcMixerStream *stream)
399 {
400         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
401         if (stream->priv->icon_name == NULL)
402                 return NULL;
403         return g_themed_icon_new_with_default_fallbacks (stream->priv->icon_name);
404 }
405 
406 gboolean
407 gvc_mixer_stream_set_icon_name (GvcMixerStream *stream,
408                                 const char     *icon_name)
409 {
410         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
411 
412         g_free (stream->priv->icon_name);
413         stream->priv->icon_name = g_strdup (icon_name);
414         g_object_notify (G_OBJECT (stream), "icon-name");
415 
416         return TRUE;
417 }
418 
419 /**
420  * gvc_mixer_stream_get_base_volume:
421  * @stream:
422  *
423  * Returns: (type guint32) (transfer none):
424  */
425 pa_volume_t
426 gvc_mixer_stream_get_base_volume (GvcMixerStream *stream)
427 {
428         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
429 
430         return stream->priv->base_volume;
431 }
432 
433 /**
434  * gvc_mixer_stream_set_base_volume:
435  * @stream:
436  * @base_volume: (type guint32):
437  *
438  * Returns:
439  */
440 gboolean
441 gvc_mixer_stream_set_base_volume (GvcMixerStream *stream,
442                                   pa_volume_t base_volume)
443 {
444         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
445 
446         stream->priv->base_volume = base_volume;
447 
448         return TRUE;
449 }
450 
451 const GvcMixerStreamPort *
452 gvc_mixer_stream_get_port (GvcMixerStream *stream)
453 {
454         GList *l;
455 
456         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
457         g_return_val_if_fail (stream->priv->ports != NULL, NULL);
458 
459         for (l = stream->priv->ports; l != NULL; l = l->next) {
460                 GvcMixerStreamPort *p = l->data;
461                 if (g_strcmp0 (stream->priv->port, p->port) == 0) {
462                         return p;
463                 }
464         }
465 
466         g_assert_not_reached ();
467 
468         return NULL;
469 }
470 
471 gboolean
472 gvc_mixer_stream_set_port (GvcMixerStream *stream,
473                            const char     *port)
474 {
475         GList *l;
476 
477         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
478         g_return_val_if_fail (stream->priv->ports != NULL, FALSE);
479 
480         g_free (stream->priv->port);
481         stream->priv->port = g_strdup (port);
482 
483         g_free (stream->priv->human_port);
484         stream->priv->human_port = NULL;
485 
486         for (l = stream->priv->ports; l != NULL; l = l->next) {
487                 GvcMixerStreamPort *p = l->data;
488                 if (g_str_equal (stream->priv->port, p->port)) {
489                         stream->priv->human_port = g_strdup (p->human_port);
490                         break;
491                 }
492         }
493 
494         g_object_notify (G_OBJECT (stream), "port");
495 
496         return TRUE;
497 }
498 
499 gboolean
500 gvc_mixer_stream_change_port (GvcMixerStream *stream,
501                               const char     *port)
502 {
503         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
504         return GVC_MIXER_STREAM_GET_CLASS (stream)->change_port (stream, port);
505 }
506 
507 /**
508  * gvc_mixer_stream_get_ports:
509  *
510  * Return value: (transfer none) (element-type GvcMixerStreamPort):
511  */
512 const GList *
513 gvc_mixer_stream_get_ports (GvcMixerStream *stream)
514 {
515         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
516         return stream->priv->ports;
517 }
518 
519 static int
520 sort_ports (GvcMixerStreamPort *a,
521             GvcMixerStreamPort *b)
522 {
523         if (a->priority == b->priority)
524                 return 0;
525         if (a->priority > b->priority)
526                 return 1;
527         return -1;
528 }
529 
530 /**
531  * gvc_mixer_stream_set_ports:
532  * @ports: (transfer full) (element-type GvcMixerStreamPort):
533  */
534 gboolean
535 gvc_mixer_stream_set_ports (GvcMixerStream *stream,
536                             GList          *ports)
537 {
538         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
539         g_return_val_if_fail (stream->priv->ports == NULL, FALSE);
540 
541         stream->priv->ports = g_list_sort (ports, (GCompareFunc) sort_ports);
542 
543         return TRUE;
544 }
545 
546 gint
547 gvc_mixer_stream_get_card_index (GvcMixerStream *stream)
548 {
549         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), PA_INVALID_INDEX);
550         return stream->priv->card_index;
551 }
552 
553 gboolean
554 gvc_mixer_stream_set_card_index (GvcMixerStream *stream,
555                                  gint            card_index)
556 {
557         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
558 
559         stream->priv->card_index = card_index;
560         g_object_notify (G_OBJECT (stream), "card-index");
561 
562         return TRUE;
563 }
564 
565 static void
566 gvc_mixer_stream_set_property (GObject       *object,
567                                guint          prop_id,
568                                const GValue  *value,
569                                GParamSpec    *pspec)
570 {
571         GvcMixerStream *self = GVC_MIXER_STREAM (object);
572 
573         switch (prop_id) {
574         case PROP_PA_CONTEXT:
575                 self->priv->pa_context = g_value_get_pointer (value);
576                 break;
577         case PROP_INDEX:
578                 self->priv->index = g_value_get_ulong (value);
579                 break;
580         case PROP_ID:
581                 self->priv->id = g_value_get_ulong (value);
582                 break;
583         case PROP_CHANNEL_MAP:
584                 gvc_mixer_stream_set_channel_map (self, g_value_get_object (value));
585                 break;
586         case PROP_NAME:
587                 gvc_mixer_stream_set_name (self, g_value_get_string (value));
588                 break;
589         case PROP_DESCRIPTION:
590                 gvc_mixer_stream_set_description (self, g_value_get_string (value));
591                 break;
592         case PROP_APPLICATION_ID:
593                 gvc_mixer_stream_set_application_id (self, g_value_get_string (value));
594                 break;
595         case PROP_ICON_NAME:
596                 gvc_mixer_stream_set_icon_name (self, g_value_get_string (value));
597                 break;
598         case PROP_VOLUME:
599                 gvc_mixer_stream_set_volume (self, g_value_get_ulong (value));
600                 break;
601         case PROP_DECIBEL:
602                 gvc_mixer_stream_set_decibel (self, g_value_get_double (value));
603                 break;
604         case PROP_IS_MUTED:
605                 gvc_mixer_stream_set_is_muted (self, g_value_get_boolean (value));
606                 break;
607         case PROP_IS_EVENT_STREAM:
608                 gvc_mixer_stream_set_is_event_stream (self, g_value_get_boolean (value));
609                 break;
610         case PROP_IS_VIRTUAL:
611                 gvc_mixer_stream_set_is_virtual (self, g_value_get_boolean (value));
612                 break;
613         case PROP_CAN_DECIBEL:
614                 gvc_mixer_stream_set_can_decibel (self, g_value_get_boolean (value));
615                 break;
616         case PROP_PORT:
617                 gvc_mixer_stream_set_port (self, g_value_get_string (value));
618                 break;
619         case PROP_CARD_INDEX:
620                 self->priv->card_index = g_value_get_long (value);
621                 break;
622         default:
623                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
624                 break;
625         }
626 }
627 
628 static void
629 gvc_mixer_stream_get_property (GObject     *object,
630                                guint        prop_id,
631                                GValue      *value,
632                                GParamSpec  *pspec)
633 {
634         GvcMixerStream *self = GVC_MIXER_STREAM (object);
635 
636         switch (prop_id) {
637         case PROP_PA_CONTEXT:
638                 g_value_set_pointer (value, self->priv->pa_context);
639                 break;
640         case PROP_INDEX:
641                 g_value_set_ulong (value, self->priv->index);
642                 break;
643         case PROP_ID:
644                 g_value_set_ulong (value, self->priv->id);
645                 break;
646         case PROP_CHANNEL_MAP:
647                 g_value_set_object (value, self->priv->channel_map);
648                 break;
649         case PROP_NAME:
650                 g_value_set_string (value, self->priv->name);
651                 break;
652         case PROP_DESCRIPTION:
653                 g_value_set_string (value, self->priv->description);
654                 break;
655         case PROP_APPLICATION_ID:
656                 g_value_set_string (value, self->priv->application_id);
657                 break;
658         case PROP_ICON_NAME:
659                 g_value_set_string (value, self->priv->icon_name);
660                 break;
661         case PROP_VOLUME:
662                 g_value_set_ulong (value,
663                                    pa_cvolume_max(gvc_channel_map_get_cvolume(self->priv->channel_map)));
664                 break;
665         case PROP_DECIBEL:
666                 g_value_set_double (value,
667                                     pa_sw_volume_to_dB(pa_cvolume_max(gvc_channel_map_get_cvolume(self->priv->channel_map))));
668                 break;
669         case PROP_IS_MUTED:
670                 g_value_set_boolean (value, self->priv->is_muted);
671                 break;
672         case PROP_IS_EVENT_STREAM:
673                 g_value_set_boolean (value, self->priv->is_event_stream);
674                 break;
675         case PROP_IS_VIRTUAL:
676                 g_value_set_boolean (value, self->priv->is_virtual);
677                 break;
678         case PROP_CAN_DECIBEL:
679                 g_value_set_boolean (value, self->priv->can_decibel);
680                 break;
681         case PROP_PORT:
682                 g_value_set_string (value, self->priv->port);
683                 break;
684         case PROP_CARD_INDEX:
685                 g_value_set_long (value, self->priv->card_index);
686                 break;
687         default:
688                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
689                 break;
690         }
691 }
692 
693 static GObject *
694 gvc_mixer_stream_constructor (GType                  type,
695                               guint                  n_construct_properties,
696                               GObjectConstructParam *construct_params)
697 {
698         GObject       *object;
699         GvcMixerStream *self;
700 
701         object = G_OBJECT_CLASS (gvc_mixer_stream_parent_class)->constructor (type, n_construct_properties, construct_params);
702 
703         self = GVC_MIXER_STREAM (object);
704 
705         self->priv->id = get_next_stream_serial ();
706 
707         return object;
708 }
709 
710 static gboolean
711 gvc_mixer_stream_real_change_port (GvcMixerStream *stream,
712                                    const char     *port)
713 {
714         return FALSE;
715 }
716 
717 static gboolean
718 gvc_mixer_stream_real_push_volume (GvcMixerStream *stream, gpointer *op)
719 {
720         return FALSE;
721 }
722 
723 static gboolean
724 gvc_mixer_stream_real_change_is_muted (GvcMixerStream *stream,
725                                        gboolean        is_muted)
726 {
727         return FALSE;
728 }
729 
730 gboolean
731 gvc_mixer_stream_push_volume (GvcMixerStream *stream)
732 {
733         pa_operation *op;
734         gboolean ret;
735 
736         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
737 
738         if (stream->priv->is_event_stream != FALSE)
739                 return TRUE;
740 
741         g_debug ("Pushing new volume to stream '%s' (%s)",
742                  stream->priv->description, stream->priv->name);
743 
744         ret = GVC_MIXER_STREAM_GET_CLASS (stream)->push_volume (stream, (gpointer *) &op);
745         if (ret) {
746                 if (stream->priv->change_volume_op != NULL)
747                         pa_operation_unref (stream->priv->change_volume_op);
748                 stream->priv->change_volume_op = op;
749         }
750         return ret;
751 }
752 
753 gboolean
754 gvc_mixer_stream_change_is_muted (GvcMixerStream *stream,
755                                   gboolean        is_muted)
756 {
757         gboolean ret;
758         g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
759         ret = GVC_MIXER_STREAM_GET_CLASS (stream)->change_is_muted (stream, is_muted);
760         return ret;
761 }
762 
763 gboolean
764 gvc_mixer_stream_is_running (GvcMixerStream *stream)
765 {
766         if (stream->priv->change_volume_op == NULL)
767                 return FALSE;
768 
769         if ((pa_operation_get_state(stream->priv->change_volume_op) == PA_OPERATION_RUNNING))
770                 return TRUE;
771 
772         pa_operation_unref(stream->priv->change_volume_op);
773         stream->priv->change_volume_op = NULL;
774 
775         return FALSE;
776 }
777 
778 static void
779 gvc_mixer_stream_class_init (GvcMixerStreamClass *klass)
780 {
781         GObjectClass   *gobject_class = G_OBJECT_CLASS (klass);
782 
783         gobject_class->constructor = gvc_mixer_stream_constructor;
784         gobject_class->finalize = gvc_mixer_stream_finalize;
785         gobject_class->set_property = gvc_mixer_stream_set_property;
786         gobject_class->get_property = gvc_mixer_stream_get_property;
787 
788         klass->push_volume = gvc_mixer_stream_real_push_volume;
789         klass->change_port = gvc_mixer_stream_real_change_port;
790         klass->change_is_muted = gvc_mixer_stream_real_change_is_muted;
791 
792         g_object_class_install_property (gobject_class,
793                                          PROP_INDEX,
794                                          g_param_spec_ulong ("index",
795                                                              "Index",
796                                                              "The index for this stream",
797                                                              0, G_MAXULONG, 0,
798                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
799         g_object_class_install_property (gobject_class,
800                                          PROP_ID,
801                                          g_param_spec_ulong ("id",
802                                                              "id",
803                                                              "The id for this stream",
804                                                              0, G_MAXULONG, 0,
805                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
806         g_object_class_install_property (gobject_class,
807                                          PROP_CHANNEL_MAP,
808                                          g_param_spec_object ("channel-map",
809                                                               "channel map",
810                                                               "The channel map for this stream",
811                                                               GVC_TYPE_CHANNEL_MAP,
812                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
813         g_object_class_install_property (gobject_class,
814                                          PROP_PA_CONTEXT,
815                                          g_param_spec_pointer ("pa-context",
816                                                                "PulseAudio context",
817                                                                "The PulseAudio context for this stream",
818                                                                G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
819         g_object_class_install_property (gobject_class,
820                                          PROP_VOLUME,
821                                          g_param_spec_ulong ("volume",
822                                                              "Volume",
823                                                              "The volume for this stream",
824                                                              0, G_MAXULONG, 0,
825                                                              G_PARAM_READWRITE));
826         g_object_class_install_property (gobject_class,
827                                          PROP_DECIBEL,
828                                          g_param_spec_double ("decibel",
829                                                               "Decibel",
830                                                               "The decibel level for this stream",
831                                                               -G_MAXDOUBLE, G_MAXDOUBLE, 0,
832                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
833 
834         g_object_class_install_property (gobject_class,
835                                          PROP_NAME,
836                                          g_param_spec_string ("name",
837                                                               "Name",
838                                                               "Name to display for this stream",
839                                                               NULL,
840                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
841         g_object_class_install_property (gobject_class,
842                                          PROP_DESCRIPTION,
843                                          g_param_spec_string ("description",
844                                                               "Description",
845                                                               "Description to display for this stream",
846                                                               NULL,
847                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
848         g_object_class_install_property (gobject_class,
849                                          PROP_APPLICATION_ID,
850                                          g_param_spec_string ("application-id",
851                                                               "Application identifier",
852                                                               "Application identifier for this stream",
853                                                               NULL,
854                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
855         g_object_class_install_property (gobject_class,
856                                          PROP_ICON_NAME,
857                                          g_param_spec_string ("icon-name",
858                                                               "Icon Name",
859                                                               "Name of icon to display for this stream",
860                                                               NULL,
861                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
862         g_object_class_install_property (gobject_class,
863                                          PROP_IS_MUTED,
864                                          g_param_spec_boolean ("is-muted",
865                                                                "is muted",
866                                                                "Whether stream is muted",
867                                                                FALSE,
868                                                                G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
869         g_object_class_install_property (gobject_class,
870                                          PROP_CAN_DECIBEL,
871                                          g_param_spec_boolean ("can-decibel",
872                                                                "can decibel",
873                                                                "Whether stream volume can be converted to decibel units",
874                                                                FALSE,
875                                                                G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
876         g_object_class_install_property (gobject_class,
877                                          PROP_IS_EVENT_STREAM,
878                                          g_param_spec_boolean ("is-event-stream",
879                                                                "is event stream",
880                                                                "Whether stream's role is to play an event",
881                                                                FALSE,
882                                                                G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
883         g_object_class_install_property (gobject_class,
884                                          PROP_IS_VIRTUAL,
885                                          g_param_spec_boolean ("is-virtual",
886                                                                "is virtual stream",
887                                                                "Whether the stream is virtual",
888                                                                FALSE,
889                                                                G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
890         g_object_class_install_property (gobject_class,
891                                          PROP_PORT,
892                                          g_param_spec_string ("port",
893                                                               "Port",
894                                                               "The name of the current port for this stream",
895                                                               NULL,
896                                                               G_PARAM_READWRITE));
897         g_object_class_install_property (gobject_class,
898                                          PROP_CARD_INDEX,
899                                          g_param_spec_long ("card-index",
900                                                              "Card index",
901                                                              "The index of the card for this stream",
902                                                              PA_INVALID_INDEX, G_MAXLONG, PA_INVALID_INDEX,
903                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
904         g_type_class_add_private (klass, sizeof (GvcMixerStreamPrivate));
905 }
906 
907 static void
908 gvc_mixer_stream_init (GvcMixerStream *stream)
909 {
910         stream->priv = GVC_MIXER_STREAM_GET_PRIVATE (stream);
911 }
912 
913 static void
914 free_port (GvcMixerStreamPort *p)
915 {
916         g_free (p->port);
917         g_free (p->human_port);
918         g_free (p);
919 }
920 
921 static void
922 gvc_mixer_stream_finalize (GObject *object)
923 {
924         GvcMixerStream *mixer_stream;
925 
926         g_return_if_fail (object != NULL);
927         g_return_if_fail (GVC_IS_MIXER_STREAM (object));
928 
929         mixer_stream = GVC_MIXER_STREAM (object);
930 
931         g_return_if_fail (mixer_stream->priv != NULL);
932 
933         g_object_unref (mixer_stream->priv->channel_map);
934         mixer_stream->priv->channel_map = NULL;
935 
936         g_free (mixer_stream->priv->name);
937         mixer_stream->priv->name = NULL;
938 
939         g_free (mixer_stream->priv->description);
940         mixer_stream->priv->description = NULL;
941 
942         g_free (mixer_stream->priv->application_id);
943         mixer_stream->priv->application_id = NULL;
944 
945         g_free (mixer_stream->priv->icon_name);
946         mixer_stream->priv->icon_name = NULL;
947 
948         g_free (mixer_stream->priv->port);
949         mixer_stream->priv->port = NULL;
950 
951         g_free (mixer_stream->priv->human_port);
952         mixer_stream->priv->human_port = NULL;
953 
954         g_list_foreach (mixer_stream->priv->ports, (GFunc) free_port, NULL);
955         g_list_free (mixer_stream->priv->ports);
956         mixer_stream->priv->ports = NULL;
957 
958        if (mixer_stream->priv->change_volume_op) {
959                pa_operation_unref(mixer_stream->priv->change_volume_op);
960                mixer_stream->priv->change_volume_op = NULL;
961        }
962 
963         G_OBJECT_CLASS (gvc_mixer_stream_parent_class)->finalize (object);
964 }