1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3
* Copyright (C) 2008 William Jon McCann
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.
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.
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.
28
#include <glib/gi18n-lib.h>
30
#include <pulse/pulseaudio.h>
32
#include "gvc-mixer-stream.h"
33
#include "gvc-mixer-stream-private.h"
34
#include "gvc-channel-map-private.h"
36
#define GVC_MIXER_STREAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_STREAM, GvcMixerStreamPrivate))
38
static guint32 stream_serial = 1;
40
struct GvcMixerStreamPrivate
42
pa_context *pa_context;
46
GvcChannelMap *channel_map;
55
gboolean is_event_stream;
57
pa_volume_t base_volume;
58
pa_operation *change_volume_op;
87
static void gvc_mixer_stream_class_init (GvcMixerStreamClass *klass);
88
static void gvc_mixer_stream_init (GvcMixerStream *mixer_stream);
89
static void gvc_mixer_stream_finalize (GObject *object);
91
G_DEFINE_ABSTRACT_TYPE (GvcMixerStream, gvc_mixer_stream, G_TYPE_OBJECT)
94
free_port (GvcMixerStreamPort *p)
97
g_free (p->human_port);
98
g_slice_free (GvcMixerStreamPort, p);
101
static GvcMixerStreamPort *
102
dup_port (GvcMixerStreamPort *p)
104
GvcMixerStreamPort *m;
106
m = g_slice_new (GvcMixerStreamPort);
109
m->port = g_strdup (p->port);
110
m->human_port = g_strdup (p->human_port);
115
G_DEFINE_BOXED_TYPE (GvcMixerStreamPort, gvc_mixer_stream_port, dup_port, free_port)
118
get_next_stream_serial (void)
122
serial = stream_serial++;
124
if ((gint32)stream_serial < 0) {
132
gvc_mixer_stream_get_pa_context (GvcMixerStream *stream)
134
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
135
return stream->priv->pa_context;
139
gvc_mixer_stream_get_index (GvcMixerStream *stream)
141
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
142
return stream->priv->index;
146
gvc_mixer_stream_get_id (GvcMixerStream *stream)
148
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
149
return stream->priv->id;
152
const GvcChannelMap *
153
gvc_mixer_stream_get_channel_map (GvcMixerStream *stream)
155
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
156
return stream->priv->channel_map;
160
* gvc_mixer_stream_get_volume:
163
* Returns: (type guint32) (transfer none):
166
gvc_mixer_stream_get_volume (GvcMixerStream *stream)
168
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
170
return (pa_volume_t) gvc_channel_map_get_volume(stream->priv->channel_map)[VOLUME];
174
gvc_mixer_stream_get_decibel (GvcMixerStream *stream)
176
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
178
return pa_sw_volume_to_dB(
179
(pa_volume_t) gvc_channel_map_get_volume(stream->priv->channel_map)[VOLUME]);
183
* gvc_mixer_stream_set_volume:
185
* @volume: (type guint32):
190
gvc_mixer_stream_set_volume (GvcMixerStream *stream,
195
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
197
cv = *gvc_channel_map_get_cvolume(stream->priv->channel_map);
198
pa_cvolume_scale(&cv, volume);
200
if (!pa_cvolume_equal(gvc_channel_map_get_cvolume(stream->priv->channel_map), &cv)) {
201
gvc_channel_map_volume_changed(stream->priv->channel_map, &cv, FALSE);
202
g_object_notify (G_OBJECT (stream), "volume");
210
gvc_mixer_stream_set_decibel (GvcMixerStream *stream,
215
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
217
cv = *gvc_channel_map_get_cvolume(stream->priv->channel_map);
218
pa_cvolume_scale(&cv, pa_sw_volume_from_dB(db));
220
if (!pa_cvolume_equal(gvc_channel_map_get_cvolume(stream->priv->channel_map), &cv)) {
221
gvc_channel_map_volume_changed(stream->priv->channel_map, &cv, FALSE);
222
g_object_notify (G_OBJECT (stream), "volume");
229
gvc_mixer_stream_get_is_muted (GvcMixerStream *stream)
231
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
232
return stream->priv->is_muted;
236
gvc_mixer_stream_get_can_decibel (GvcMixerStream *stream)
238
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
239
return stream->priv->can_decibel;
243
gvc_mixer_stream_set_is_muted (GvcMixerStream *stream,
246
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
248
if (is_muted != stream->priv->is_muted) {
249
stream->priv->is_muted = is_muted;
250
g_object_notify (G_OBJECT (stream), "is-muted");
257
gvc_mixer_stream_set_can_decibel (GvcMixerStream *stream,
258
gboolean can_decibel)
260
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
262
if (can_decibel != stream->priv->can_decibel) {
263
stream->priv->can_decibel = can_decibel;
264
g_object_notify (G_OBJECT (stream), "can-decibel");
271
gvc_mixer_stream_get_name (GvcMixerStream *stream)
273
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
274
return stream->priv->name;
278
gvc_mixer_stream_get_description (GvcMixerStream *stream)
280
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
281
return stream->priv->description;
285
gvc_mixer_stream_set_name (GvcMixerStream *stream,
288
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
290
g_free (stream->priv->name);
291
stream->priv->name = g_strdup (name);
292
g_object_notify (G_OBJECT (stream), "name");
298
gvc_mixer_stream_set_description (GvcMixerStream *stream,
299
const char *description)
301
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
303
g_free (stream->priv->description);
304
stream->priv->description = g_strdup (description);
305
g_object_notify (G_OBJECT (stream), "description");
311
gvc_mixer_stream_is_event_stream (GvcMixerStream *stream)
313
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
315
return stream->priv->is_event_stream;
319
gvc_mixer_stream_set_is_event_stream (GvcMixerStream *stream,
320
gboolean is_event_stream)
322
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
324
stream->priv->is_event_stream = is_event_stream;
325
g_object_notify (G_OBJECT (stream), "is-event-stream");
331
gvc_mixer_stream_is_virtual (GvcMixerStream *stream)
333
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
335
return stream->priv->is_virtual;
339
gvc_mixer_stream_set_is_virtual (GvcMixerStream *stream,
342
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
344
stream->priv->is_virtual = is_virtual;
345
g_object_notify (G_OBJECT (stream), "is-virtual");
351
gvc_mixer_stream_get_application_id (GvcMixerStream *stream)
353
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
354
return stream->priv->application_id;
358
gvc_mixer_stream_set_application_id (GvcMixerStream *stream,
359
const char *application_id)
361
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
363
g_free (stream->priv->application_id);
364
stream->priv->application_id = g_strdup (application_id);
365
g_object_notify (G_OBJECT (stream), "application-id");
371
on_channel_map_volume_changed (GvcChannelMap *channel_map,
373
GvcMixerStream *stream)
376
gvc_mixer_stream_push_volume (stream);
378
g_object_notify (G_OBJECT (stream), "volume");
382
gvc_mixer_stream_set_channel_map (GvcMixerStream *stream,
383
GvcChannelMap *channel_map)
385
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
387
if (channel_map != NULL) {
388
g_object_ref (channel_map);
391
if (stream->priv->channel_map != NULL) {
392
g_signal_handlers_disconnect_by_func (stream->priv->channel_map,
393
on_channel_map_volume_changed,
395
g_object_unref (stream->priv->channel_map);
398
stream->priv->channel_map = channel_map;
400
if (stream->priv->channel_map != NULL) {
401
g_signal_connect (stream->priv->channel_map,
403
G_CALLBACK (on_channel_map_volume_changed),
406
g_object_notify (G_OBJECT (stream), "channel-map");
413
gvc_mixer_stream_get_icon_name (GvcMixerStream *stream)
415
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
416
return stream->priv->icon_name;
420
gvc_mixer_stream_get_form_factor (GvcMixerStream *stream)
422
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
423
return stream->priv->form_factor;
427
gvc_mixer_stream_get_sysfs_path (GvcMixerStream *stream)
429
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
430
return stream->priv->sysfs_path;
434
* gvc_mixer_stream_get_gicon:
435
* @stream: a #GvcMixerStream
437
* Returns: (transfer full): a new #GIcon
440
gvc_mixer_stream_get_gicon (GvcMixerStream *stream)
442
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
443
if (stream->priv->icon_name == NULL)
445
return g_themed_icon_new_with_default_fallbacks (stream->priv->icon_name);
449
gvc_mixer_stream_set_icon_name (GvcMixerStream *stream,
450
const char *icon_name)
452
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
454
g_free (stream->priv->icon_name);
455
stream->priv->icon_name = g_strdup (icon_name);
456
g_object_notify (G_OBJECT (stream), "icon-name");
462
gvc_mixer_stream_set_form_factor (GvcMixerStream *stream,
463
const char *form_factor)
465
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
467
g_free (stream->priv->form_factor);
468
stream->priv->form_factor = g_strdup (form_factor);
469
g_object_notify (G_OBJECT (stream), "form-factor");
475
gvc_mixer_stream_set_sysfs_path (GvcMixerStream *stream,
476
const char *sysfs_path)
478
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
480
g_free (stream->priv->sysfs_path);
481
stream->priv->sysfs_path = g_strdup (sysfs_path);
482
g_object_notify (G_OBJECT (stream), "sysfs-path");
488
* gvc_mixer_stream_get_base_volume:
491
* Returns: (type guint32) (transfer none):
494
gvc_mixer_stream_get_base_volume (GvcMixerStream *stream)
496
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
498
return stream->priv->base_volume;
502
* gvc_mixer_stream_set_base_volume:
504
* @base_volume: (type guint32):
509
gvc_mixer_stream_set_base_volume (GvcMixerStream *stream,
510
pa_volume_t base_volume)
512
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
514
stream->priv->base_volume = base_volume;
519
const GvcMixerStreamPort *
520
gvc_mixer_stream_get_port (GvcMixerStream *stream)
524
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
525
g_return_val_if_fail (stream->priv->ports != NULL, NULL);
527
for (l = stream->priv->ports; l != NULL; l = l->next) {
528
GvcMixerStreamPort *p = l->data;
529
if (g_strcmp0 (stream->priv->port, p->port) == 0) {
534
g_assert_not_reached ();
540
gvc_mixer_stream_set_port (GvcMixerStream *stream,
545
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
546
g_return_val_if_fail (stream->priv->ports != NULL, FALSE);
548
g_free (stream->priv->port);
549
stream->priv->port = g_strdup (port);
551
g_free (stream->priv->human_port);
552
stream->priv->human_port = NULL;
554
for (l = stream->priv->ports; l != NULL; l = l->next) {
555
GvcMixerStreamPort *p = l->data;
556
if (g_str_equal (stream->priv->port, p->port)) {
557
stream->priv->human_port = g_strdup (p->human_port);
562
g_object_notify (G_OBJECT (stream), "port");
568
gvc_mixer_stream_change_port (GvcMixerStream *stream,
571
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
572
return GVC_MIXER_STREAM_GET_CLASS (stream)->change_port (stream, port);
576
* gvc_mixer_stream_get_ports:
578
* Return value: (transfer none) (element-type GvcMixerStreamPort):
581
gvc_mixer_stream_get_ports (GvcMixerStream *stream)
583
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
584
return stream->priv->ports;
588
sort_ports (GvcMixerStreamPort *a,
589
GvcMixerStreamPort *b)
591
if (a->priority == b->priority)
593
if (a->priority > b->priority)
599
* gvc_mixer_stream_set_ports:
600
* @ports: (transfer full) (element-type GvcMixerStreamPort):
603
gvc_mixer_stream_set_ports (GvcMixerStream *stream,
606
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
607
g_return_val_if_fail (stream->priv->ports == NULL, FALSE);
609
stream->priv->ports = g_list_sort (ports, (GCompareFunc) sort_ports);
615
gvc_mixer_stream_get_card_index (GvcMixerStream *stream)
617
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), PA_INVALID_INDEX);
618
return stream->priv->card_index;
622
gvc_mixer_stream_set_card_index (GvcMixerStream *stream,
625
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
627
stream->priv->card_index = card_index;
628
g_object_notify (G_OBJECT (stream), "card-index");
634
gvc_mixer_stream_set_property (GObject *object,
639
GvcMixerStream *self = GVC_MIXER_STREAM (object);
642
case PROP_PA_CONTEXT:
643
self->priv->pa_context = g_value_get_pointer (value);
646
self->priv->index = g_value_get_ulong (value);
649
self->priv->id = g_value_get_ulong (value);
651
case PROP_CHANNEL_MAP:
652
gvc_mixer_stream_set_channel_map (self, g_value_get_object (value));
655
gvc_mixer_stream_set_name (self, g_value_get_string (value));
657
case PROP_DESCRIPTION:
658
gvc_mixer_stream_set_description (self, g_value_get_string (value));
660
case PROP_APPLICATION_ID:
661
gvc_mixer_stream_set_application_id (self, g_value_get_string (value));
664
gvc_mixer_stream_set_icon_name (self, g_value_get_string (value));
666
case PROP_FORM_FACTOR:
667
gvc_mixer_stream_set_form_factor (self, g_value_get_string (value));
669
case PROP_SYSFS_PATH:
670
gvc_mixer_stream_set_sysfs_path (self, g_value_get_string (value));
673
gvc_mixer_stream_set_volume (self, g_value_get_ulong (value));
676
gvc_mixer_stream_set_decibel (self, g_value_get_double (value));
679
gvc_mixer_stream_set_is_muted (self, g_value_get_boolean (value));
681
case PROP_IS_EVENT_STREAM:
682
gvc_mixer_stream_set_is_event_stream (self, g_value_get_boolean (value));
684
case PROP_IS_VIRTUAL:
685
gvc_mixer_stream_set_is_virtual (self, g_value_get_boolean (value));
687
case PROP_CAN_DECIBEL:
688
gvc_mixer_stream_set_can_decibel (self, g_value_get_boolean (value));
691
gvc_mixer_stream_set_port (self, g_value_get_string (value));
693
case PROP_CARD_INDEX:
694
self->priv->card_index = g_value_get_long (value);
697
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
703
gvc_mixer_stream_get_property (GObject *object,
708
GvcMixerStream *self = GVC_MIXER_STREAM (object);
711
case PROP_PA_CONTEXT:
712
g_value_set_pointer (value, self->priv->pa_context);
715
g_value_set_ulong (value, self->priv->index);
718
g_value_set_ulong (value, self->priv->id);
720
case PROP_CHANNEL_MAP:
721
g_value_set_object (value, self->priv->channel_map);
724
g_value_set_string (value, self->priv->name);
726
case PROP_DESCRIPTION:
727
g_value_set_string (value, self->priv->description);
729
case PROP_APPLICATION_ID:
730
g_value_set_string (value, self->priv->application_id);
733
g_value_set_string (value, self->priv->icon_name);
735
case PROP_FORM_FACTOR:
736
g_value_set_string (value, self->priv->form_factor);
738
case PROP_SYSFS_PATH:
739
g_value_set_string (value, self->priv->sysfs_path);
742
g_value_set_ulong (value,
743
pa_cvolume_max(gvc_channel_map_get_cvolume(self->priv->channel_map)));
746
g_value_set_double (value,
747
pa_sw_volume_to_dB(pa_cvolume_max(gvc_channel_map_get_cvolume(self->priv->channel_map))));
750
g_value_set_boolean (value, self->priv->is_muted);
752
case PROP_IS_EVENT_STREAM:
753
g_value_set_boolean (value, self->priv->is_event_stream);
755
case PROP_IS_VIRTUAL:
756
g_value_set_boolean (value, self->priv->is_virtual);
758
case PROP_CAN_DECIBEL:
759
g_value_set_boolean (value, self->priv->can_decibel);
762
g_value_set_string (value, self->priv->port);
764
case PROP_CARD_INDEX:
765
g_value_set_long (value, self->priv->card_index);
768
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
774
gvc_mixer_stream_constructor (GType type,
775
guint n_construct_properties,
776
GObjectConstructParam *construct_params)
779
GvcMixerStream *self;
781
object = G_OBJECT_CLASS (gvc_mixer_stream_parent_class)->constructor (type, n_construct_properties, construct_params);
783
self = GVC_MIXER_STREAM (object);
785
self->priv->id = get_next_stream_serial ();
791
gvc_mixer_stream_real_change_port (GvcMixerStream *stream,
798
gvc_mixer_stream_real_push_volume (GvcMixerStream *stream, gpointer *op)
804
gvc_mixer_stream_real_change_is_muted (GvcMixerStream *stream,
811
gvc_mixer_stream_push_volume (GvcMixerStream *stream)
816
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
818
if (stream->priv->is_event_stream != FALSE)
821
g_debug ("Pushing new volume to stream '%s' (%s)",
822
stream->priv->description, stream->priv->name);
824
ret = GVC_MIXER_STREAM_GET_CLASS (stream)->push_volume (stream, (gpointer *) &op);
826
if (stream->priv->change_volume_op != NULL)
827
pa_operation_unref (stream->priv->change_volume_op);
828
stream->priv->change_volume_op = op;
834
gvc_mixer_stream_change_is_muted (GvcMixerStream *stream,
838
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
839
ret = GVC_MIXER_STREAM_GET_CLASS (stream)->change_is_muted (stream, is_muted);
844
gvc_mixer_stream_is_running (GvcMixerStream *stream)
846
if (stream->priv->change_volume_op == NULL)
849
if ((pa_operation_get_state(stream->priv->change_volume_op) == PA_OPERATION_RUNNING))
852
pa_operation_unref(stream->priv->change_volume_op);
853
stream->priv->change_volume_op = NULL;
859
gvc_mixer_stream_class_init (GvcMixerStreamClass *klass)
861
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
863
gobject_class->constructor = gvc_mixer_stream_constructor;
864
gobject_class->finalize = gvc_mixer_stream_finalize;
865
gobject_class->set_property = gvc_mixer_stream_set_property;
866
gobject_class->get_property = gvc_mixer_stream_get_property;
868
klass->push_volume = gvc_mixer_stream_real_push_volume;
869
klass->change_port = gvc_mixer_stream_real_change_port;
870
klass->change_is_muted = gvc_mixer_stream_real_change_is_muted;
872
g_object_class_install_property (gobject_class,
874
g_param_spec_ulong ("index",
876
"The index for this stream",
878
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
879
g_object_class_install_property (gobject_class,
881
g_param_spec_ulong ("id",
883
"The id for this stream",
885
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
886
g_object_class_install_property (gobject_class,
888
g_param_spec_object ("channel-map",
890
"The channel map for this stream",
891
GVC_TYPE_CHANNEL_MAP,
892
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
893
g_object_class_install_property (gobject_class,
895
g_param_spec_pointer ("pa-context",
896
"PulseAudio context",
897
"The PulseAudio context for this stream",
898
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
899
g_object_class_install_property (gobject_class,
901
g_param_spec_ulong ("volume",
903
"The volume for this stream",
906
g_object_class_install_property (gobject_class,
908
g_param_spec_double ("decibel",
910
"The decibel level for this stream",
911
-G_MAXDOUBLE, G_MAXDOUBLE, 0,
912
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
914
g_object_class_install_property (gobject_class,
916
g_param_spec_string ("name",
918
"Name to display for this stream",
920
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
921
g_object_class_install_property (gobject_class,
923
g_param_spec_string ("description",
925
"Description to display for this stream",
927
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
928
g_object_class_install_property (gobject_class,
930
g_param_spec_string ("application-id",
931
"Application identifier",
932
"Application identifier for this stream",
934
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
935
g_object_class_install_property (gobject_class,
937
g_param_spec_string ("icon-name",
939
"Name of icon to display for this stream",
941
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
942
g_object_class_install_property (gobject_class,
944
g_param_spec_string ("form-factor",
946
"Device form factor for this stream, as reported by PulseAudio",
948
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
949
g_object_class_install_property (gobject_class,
951
g_param_spec_string ("sysfs-path",
953
"Sysfs path for the device associated with this stream",
955
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
956
g_object_class_install_property (gobject_class,
958
g_param_spec_boolean ("is-muted",
960
"Whether stream is muted",
962
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
963
g_object_class_install_property (gobject_class,
965
g_param_spec_boolean ("can-decibel",
967
"Whether stream volume can be converted to decibel units",
969
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
970
g_object_class_install_property (gobject_class,
971
PROP_IS_EVENT_STREAM,
972
g_param_spec_boolean ("is-event-stream",
974
"Whether stream's role is to play an event",
976
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
977
g_object_class_install_property (gobject_class,
979
g_param_spec_boolean ("is-virtual",
981
"Whether the stream is virtual",
983
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
984
g_object_class_install_property (gobject_class,
986
g_param_spec_string ("port",
988
"The name of the current port for this stream",
991
g_object_class_install_property (gobject_class,
993
g_param_spec_long ("card-index",
995
"The index of the card for this stream",
996
PA_INVALID_INDEX, G_MAXLONG, PA_INVALID_INDEX,
997
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
998
g_type_class_add_private (klass, sizeof (GvcMixerStreamPrivate));
1002
gvc_mixer_stream_init (GvcMixerStream *stream)
1004
stream->priv = GVC_MIXER_STREAM_GET_PRIVATE (stream);
1008
gvc_mixer_stream_finalize (GObject *object)
1010
GvcMixerStream *mixer_stream;
1012
g_return_if_fail (object != NULL);
1013
g_return_if_fail (GVC_IS_MIXER_STREAM (object));
1015
mixer_stream = GVC_MIXER_STREAM (object);
1017
g_return_if_fail (mixer_stream->priv != NULL);
1019
g_object_unref (mixer_stream->priv->channel_map);
1020
mixer_stream->priv->channel_map = NULL;
1022
g_free (mixer_stream->priv->name);
1023
mixer_stream->priv->name = NULL;
1025
g_free (mixer_stream->priv->description);
1026
mixer_stream->priv->description = NULL;
1028
g_free (mixer_stream->priv->application_id);
1029
mixer_stream->priv->application_id = NULL;
1031
g_free (mixer_stream->priv->icon_name);
1032
mixer_stream->priv->icon_name = NULL;
1034
g_free (mixer_stream->priv->form_factor);
1035
mixer_stream->priv->form_factor = NULL;
1037
g_free (mixer_stream->priv->sysfs_path);
1038
mixer_stream->priv->sysfs_path = NULL;
1040
g_free (mixer_stream->priv->port);
1041
mixer_stream->priv->port = NULL;
1043
g_free (mixer_stream->priv->human_port);
1044
mixer_stream->priv->human_port = NULL;
1046
g_list_foreach (mixer_stream->priv->ports, (GFunc) free_port, NULL);
1047
g_list_free (mixer_stream->priv->ports);
1048
mixer_stream->priv->ports = NULL;
1050
if (mixer_stream->priv->change_volume_op) {
1051
pa_operation_unref(mixer_stream->priv->change_volume_op);
1052
mixer_stream->priv->change_volume_op = NULL;
1055
G_OBJECT_CLASS (gvc_mixer_stream_parent_class)->finalize (object);