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;
53
gboolean is_event_stream;
55
pa_volume_t base_volume;
56
pa_operation *change_volume_op;
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);
87
G_DEFINE_ABSTRACT_TYPE (GvcMixerStream, gvc_mixer_stream, G_TYPE_OBJECT)
90
get_next_stream_serial (void)
94
serial = stream_serial++;
96
if ((gint32)stream_serial < 0) {
104
gvc_mixer_stream_get_pa_context (GvcMixerStream *stream)
106
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
107
return stream->priv->pa_context;
111
gvc_mixer_stream_get_index (GvcMixerStream *stream)
113
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
114
return stream->priv->index;
118
gvc_mixer_stream_get_id (GvcMixerStream *stream)
120
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
121
return stream->priv->id;
124
const GvcChannelMap *
125
gvc_mixer_stream_get_channel_map (GvcMixerStream *stream)
127
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
128
return stream->priv->channel_map;
132
* gvc_mixer_stream_get_volume:
136
* Returns: (type guint32) (transfer none):
139
gvc_mixer_stream_get_volume (GvcMixerStream *stream)
141
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
143
return (pa_volume_t) gvc_channel_map_get_volume(stream->priv->channel_map)[VOLUME];
147
gvc_mixer_stream_get_decibel (GvcMixerStream *stream)
149
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
151
return pa_sw_volume_to_dB(
152
(pa_volume_t) gvc_channel_map_get_volume(stream->priv->channel_map)[VOLUME]);
156
* gvc_mixer_stream_set_volume:
159
* @volume: (type guint32):
164
gvc_mixer_stream_set_volume (GvcMixerStream *stream,
169
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
171
cv = *gvc_channel_map_get_cvolume(stream->priv->channel_map);
172
pa_cvolume_scale(&cv, volume);
174
if (!pa_cvolume_equal(gvc_channel_map_get_cvolume(stream->priv->channel_map), &cv)) {
175
gvc_channel_map_volume_changed(stream->priv->channel_map, &cv, FALSE);
176
g_object_notify (G_OBJECT (stream), "volume");
184
gvc_mixer_stream_set_decibel (GvcMixerStream *stream,
189
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
191
cv = *gvc_channel_map_get_cvolume(stream->priv->channel_map);
192
pa_cvolume_scale(&cv, pa_sw_volume_from_dB(db));
194
if (!pa_cvolume_equal(gvc_channel_map_get_cvolume(stream->priv->channel_map), &cv)) {
195
gvc_channel_map_volume_changed(stream->priv->channel_map, &cv, FALSE);
196
g_object_notify (G_OBJECT (stream), "volume");
203
gvc_mixer_stream_get_is_muted (GvcMixerStream *stream)
205
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
206
return stream->priv->is_muted;
210
gvc_mixer_stream_get_can_decibel (GvcMixerStream *stream)
212
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
213
return stream->priv->can_decibel;
217
gvc_mixer_stream_set_is_muted (GvcMixerStream *stream,
220
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
222
if (is_muted != stream->priv->is_muted) {
223
stream->priv->is_muted = is_muted;
224
g_object_notify (G_OBJECT (stream), "is-muted");
231
gvc_mixer_stream_set_can_decibel (GvcMixerStream *stream,
232
gboolean can_decibel)
234
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
236
if (can_decibel != stream->priv->can_decibel) {
237
stream->priv->can_decibel = can_decibel;
238
g_object_notify (G_OBJECT (stream), "can-decibel");
245
gvc_mixer_stream_get_name (GvcMixerStream *stream)
247
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
248
return stream->priv->name;
252
gvc_mixer_stream_get_description (GvcMixerStream *stream)
254
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
255
return stream->priv->description;
259
gvc_mixer_stream_set_name (GvcMixerStream *stream,
262
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
264
g_free (stream->priv->name);
265
stream->priv->name = g_strdup (name);
266
g_object_notify (G_OBJECT (stream), "name");
272
gvc_mixer_stream_set_description (GvcMixerStream *stream,
273
const char *description)
275
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
277
g_free (stream->priv->description);
278
stream->priv->description = g_strdup (description);
279
g_object_notify (G_OBJECT (stream), "description");
285
gvc_mixer_stream_is_event_stream (GvcMixerStream *stream)
287
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
289
return stream->priv->is_event_stream;
293
gvc_mixer_stream_set_is_event_stream (GvcMixerStream *stream,
294
gboolean is_event_stream)
296
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
298
stream->priv->is_event_stream = is_event_stream;
299
g_object_notify (G_OBJECT (stream), "is-event-stream");
305
gvc_mixer_stream_is_virtual (GvcMixerStream *stream)
307
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
309
return stream->priv->is_virtual;
313
gvc_mixer_stream_set_is_virtual (GvcMixerStream *stream,
316
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
318
stream->priv->is_virtual = is_virtual;
319
g_object_notify (G_OBJECT (stream), "is-virtual");
325
gvc_mixer_stream_get_application_id (GvcMixerStream *stream)
327
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
328
return stream->priv->application_id;
332
gvc_mixer_stream_set_application_id (GvcMixerStream *stream,
333
const char *application_id)
335
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
337
g_free (stream->priv->application_id);
338
stream->priv->application_id = g_strdup (application_id);
339
g_object_notify (G_OBJECT (stream), "application-id");
345
on_channel_map_volume_changed (GvcChannelMap *channel_map,
347
GvcMixerStream *stream)
350
gvc_mixer_stream_push_volume (stream);
352
g_object_notify (G_OBJECT (stream), "volume");
356
gvc_mixer_stream_set_channel_map (GvcMixerStream *stream,
357
GvcChannelMap *channel_map)
359
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
361
if (channel_map != NULL) {
362
g_object_ref (channel_map);
365
if (stream->priv->channel_map != NULL) {
366
g_signal_handlers_disconnect_by_func (stream->priv->channel_map,
367
on_channel_map_volume_changed,
369
g_object_unref (stream->priv->channel_map);
372
stream->priv->channel_map = channel_map;
374
if (stream->priv->channel_map != NULL) {
375
g_signal_connect (stream->priv->channel_map,
377
G_CALLBACK (on_channel_map_volume_changed),
380
g_object_notify (G_OBJECT (stream), "channel-map");
387
gvc_mixer_stream_get_icon_name (GvcMixerStream *stream)
389
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
390
return stream->priv->icon_name;
394
* gvc_mixer_stream_get_gicon:
395
* @stream: a #GvcMixerStream
397
* Returns: (transfer full): a new #GIcon
400
gvc_mixer_stream_get_gicon (GvcMixerStream *stream)
402
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
403
if (stream->priv->icon_name == NULL)
405
return g_themed_icon_new_with_default_fallbacks (stream->priv->icon_name);
409
gvc_mixer_stream_set_icon_name (GvcMixerStream *stream,
410
const char *icon_name)
412
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
414
g_free (stream->priv->icon_name);
415
stream->priv->icon_name = g_strdup (icon_name);
416
g_object_notify (G_OBJECT (stream), "icon-name");
422
* gvc_mixer_stream_get_base_volume:
426
* Returns: (type guint32) (transfer none):
429
gvc_mixer_stream_get_base_volume (GvcMixerStream *stream)
431
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
433
return stream->priv->base_volume;
437
* gvc_mixer_stream_set_base_volume:
440
* @base_volume: (type guint32):
445
gvc_mixer_stream_set_base_volume (GvcMixerStream *stream,
446
pa_volume_t base_volume)
448
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
450
stream->priv->base_volume = base_volume;
455
const GvcMixerStreamPort *
456
gvc_mixer_stream_get_port (GvcMixerStream *stream)
460
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
461
g_return_val_if_fail (stream->priv->ports != NULL, NULL);
463
for (l = stream->priv->ports; l != NULL; l = l->next) {
464
GvcMixerStreamPort *p = l->data;
465
if (g_strcmp0 (stream->priv->port, p->port) == 0) {
470
g_assert_not_reached ();
476
gvc_mixer_stream_set_port (GvcMixerStream *stream,
481
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
482
g_return_val_if_fail (stream->priv->ports != NULL, FALSE);
484
g_free (stream->priv->port);
485
stream->priv->port = g_strdup (port);
487
g_free (stream->priv->human_port);
488
stream->priv->human_port = NULL;
490
for (l = stream->priv->ports; l != NULL; l = l->next) {
491
GvcMixerStreamPort *p = l->data;
492
if (g_str_equal (stream->priv->port, p->port)) {
493
stream->priv->human_port = g_strdup (p->human_port);
498
g_object_notify (G_OBJECT (stream), "port");
504
gvc_mixer_stream_change_port (GvcMixerStream *stream,
507
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
508
return GVC_MIXER_STREAM_GET_CLASS (stream)->change_port (stream, port);
512
* gvc_mixer_stream_get_ports:
514
* Return value: (transfer none) (element-type GvcMixerStreamPort):
517
gvc_mixer_stream_get_ports (GvcMixerStream *stream)
519
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
520
return stream->priv->ports;
524
sort_ports (GvcMixerStreamPort *a,
525
GvcMixerStreamPort *b)
527
if (a->priority == b->priority)
529
if (a->priority > b->priority)
535
* gvc_mixer_stream_set_ports:
536
* @ports: (transfer full) (element-type GvcMixerStreamPort):
539
gvc_mixer_stream_set_ports (GvcMixerStream *stream,
542
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
543
g_return_val_if_fail (stream->priv->ports == NULL, FALSE);
545
stream->priv->ports = g_list_sort (ports, (GCompareFunc) sort_ports);
551
gvc_mixer_stream_get_card_index (GvcMixerStream *stream)
553
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), PA_INVALID_INDEX);
554
return stream->priv->card_index;
558
gvc_mixer_stream_set_card_index (GvcMixerStream *stream,
561
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
563
stream->priv->card_index = card_index;
564
g_object_notify (G_OBJECT (stream), "card-index");
570
gvc_mixer_stream_set_property (GObject *object,
575
GvcMixerStream *self = GVC_MIXER_STREAM (object);
578
case PROP_PA_CONTEXT:
579
self->priv->pa_context = g_value_get_pointer (value);
582
self->priv->index = g_value_get_ulong (value);
585
self->priv->id = g_value_get_ulong (value);
587
case PROP_CHANNEL_MAP:
588
gvc_mixer_stream_set_channel_map (self, g_value_get_object (value));
591
gvc_mixer_stream_set_name (self, g_value_get_string (value));
593
case PROP_DESCRIPTION:
594
gvc_mixer_stream_set_description (self, g_value_get_string (value));
596
case PROP_APPLICATION_ID:
597
gvc_mixer_stream_set_application_id (self, g_value_get_string (value));
600
gvc_mixer_stream_set_icon_name (self, g_value_get_string (value));
603
gvc_mixer_stream_set_volume (self, g_value_get_ulong (value));
606
gvc_mixer_stream_set_decibel (self, g_value_get_double (value));
609
gvc_mixer_stream_set_is_muted (self, g_value_get_boolean (value));
611
case PROP_IS_EVENT_STREAM:
612
gvc_mixer_stream_set_is_event_stream (self, g_value_get_boolean (value));
614
case PROP_IS_VIRTUAL:
615
gvc_mixer_stream_set_is_virtual (self, g_value_get_boolean (value));
617
case PROP_CAN_DECIBEL:
618
gvc_mixer_stream_set_can_decibel (self, g_value_get_boolean (value));
621
gvc_mixer_stream_set_port (self, g_value_get_string (value));
623
case PROP_CARD_INDEX:
624
self->priv->card_index = g_value_get_long (value);
627
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
633
gvc_mixer_stream_get_property (GObject *object,
638
GvcMixerStream *self = GVC_MIXER_STREAM (object);
641
case PROP_PA_CONTEXT:
642
g_value_set_pointer (value, self->priv->pa_context);
645
g_value_set_ulong (value, self->priv->index);
648
g_value_set_ulong (value, self->priv->id);
650
case PROP_CHANNEL_MAP:
651
g_value_set_object (value, self->priv->channel_map);
654
g_value_set_string (value, self->priv->name);
656
case PROP_DESCRIPTION:
657
g_value_set_string (value, self->priv->description);
659
case PROP_APPLICATION_ID:
660
g_value_set_string (value, self->priv->application_id);
663
g_value_set_string (value, self->priv->icon_name);
666
g_value_set_ulong (value,
667
pa_cvolume_max(gvc_channel_map_get_cvolume(self->priv->channel_map)));
670
g_value_set_double (value,
671
pa_sw_volume_to_dB(pa_cvolume_max(gvc_channel_map_get_cvolume(self->priv->channel_map))));
674
g_value_set_boolean (value, self->priv->is_muted);
676
case PROP_IS_EVENT_STREAM:
677
g_value_set_boolean (value, self->priv->is_event_stream);
679
case PROP_IS_VIRTUAL:
680
g_value_set_boolean (value, self->priv->is_virtual);
682
case PROP_CAN_DECIBEL:
683
g_value_set_boolean (value, self->priv->can_decibel);
686
g_value_set_string (value, self->priv->port);
688
case PROP_CARD_INDEX:
689
g_value_set_long (value, self->priv->card_index);
692
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
698
gvc_mixer_stream_constructor (GType type,
699
guint n_construct_properties,
700
GObjectConstructParam *construct_params)
703
GvcMixerStream *self;
705
object = G_OBJECT_CLASS (gvc_mixer_stream_parent_class)->constructor (type, n_construct_properties, construct_params);
707
self = GVC_MIXER_STREAM (object);
709
self->priv->id = get_next_stream_serial ();
715
gvc_mixer_stream_real_change_port (GvcMixerStream *stream,
722
gvc_mixer_stream_real_push_volume (GvcMixerStream *stream, gpointer *op)
728
gvc_mixer_stream_real_change_is_muted (GvcMixerStream *stream,
735
gvc_mixer_stream_push_volume (GvcMixerStream *stream)
740
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
742
if (stream->priv->is_event_stream != FALSE)
745
g_debug ("Pushing new volume to stream '%s' (%s)",
746
stream->priv->description, stream->priv->name);
748
ret = GVC_MIXER_STREAM_GET_CLASS (stream)->push_volume (stream, (gpointer *) &op);
750
if (stream->priv->change_volume_op != NULL)
751
pa_operation_unref (stream->priv->change_volume_op);
752
stream->priv->change_volume_op = op;
758
gvc_mixer_stream_change_is_muted (GvcMixerStream *stream,
762
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
763
ret = GVC_MIXER_STREAM_GET_CLASS (stream)->change_is_muted (stream, is_muted);
768
gvc_mixer_stream_is_running (GvcMixerStream *stream)
770
if (stream->priv->change_volume_op == NULL)
773
if ((pa_operation_get_state(stream->priv->change_volume_op) == PA_OPERATION_RUNNING))
776
pa_operation_unref(stream->priv->change_volume_op);
777
stream->priv->change_volume_op = NULL;
783
gvc_mixer_stream_class_init (GvcMixerStreamClass *klass)
785
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
787
gobject_class->constructor = gvc_mixer_stream_constructor;
788
gobject_class->finalize = gvc_mixer_stream_finalize;
789
gobject_class->set_property = gvc_mixer_stream_set_property;
790
gobject_class->get_property = gvc_mixer_stream_get_property;
792
klass->push_volume = gvc_mixer_stream_real_push_volume;
793
klass->change_port = gvc_mixer_stream_real_change_port;
794
klass->change_is_muted = gvc_mixer_stream_real_change_is_muted;
796
g_object_class_install_property (gobject_class,
798
g_param_spec_ulong ("index",
800
"The index for this stream",
802
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
803
g_object_class_install_property (gobject_class,
805
g_param_spec_ulong ("id",
807
"The id for this stream",
809
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
810
g_object_class_install_property (gobject_class,
812
g_param_spec_object ("channel-map",
814
"The channel map for this stream",
815
GVC_TYPE_CHANNEL_MAP,
816
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
817
g_object_class_install_property (gobject_class,
819
g_param_spec_pointer ("pa-context",
820
"PulseAudio context",
821
"The PulseAudio context for this stream",
822
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
823
g_object_class_install_property (gobject_class,
825
g_param_spec_ulong ("volume",
827
"The volume for this stream",
830
g_object_class_install_property (gobject_class,
832
g_param_spec_double ("decibel",
834
"The decibel level for this stream",
835
-G_MAXDOUBLE, G_MAXDOUBLE, 0,
836
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
838
g_object_class_install_property (gobject_class,
840
g_param_spec_string ("name",
842
"Name to display for this stream",
844
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
845
g_object_class_install_property (gobject_class,
847
g_param_spec_string ("description",
849
"Description to display for this stream",
851
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
852
g_object_class_install_property (gobject_class,
854
g_param_spec_string ("application-id",
855
"Application identifier",
856
"Application identifier for this stream",
858
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
859
g_object_class_install_property (gobject_class,
861
g_param_spec_string ("icon-name",
863
"Name of icon to display for this stream",
865
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
866
g_object_class_install_property (gobject_class,
868
g_param_spec_boolean ("is-muted",
870
"Whether stream is muted",
872
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
873
g_object_class_install_property (gobject_class,
875
g_param_spec_boolean ("can-decibel",
877
"Whether stream volume can be converted to decibel units",
879
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
880
g_object_class_install_property (gobject_class,
881
PROP_IS_EVENT_STREAM,
882
g_param_spec_boolean ("is-event-stream",
884
"Whether stream's role is to play an event",
886
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
887
g_object_class_install_property (gobject_class,
889
g_param_spec_boolean ("is-virtual",
891
"Whether the stream is virtual",
893
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
894
g_object_class_install_property (gobject_class,
896
g_param_spec_string ("port",
898
"The name of the current port for this stream",
901
g_object_class_install_property (gobject_class,
903
g_param_spec_long ("card-index",
905
"The index of the card for this stream",
906
PA_INVALID_INDEX, G_MAXLONG, PA_INVALID_INDEX,
907
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
908
g_type_class_add_private (klass, sizeof (GvcMixerStreamPrivate));
912
gvc_mixer_stream_init (GvcMixerStream *stream)
914
stream->priv = GVC_MIXER_STREAM_GET_PRIVATE (stream);
918
free_port (GvcMixerStreamPort *p)
921
g_free (p->human_port);
926
gvc_mixer_stream_finalize (GObject *object)
928
GvcMixerStream *mixer_stream;
930
g_return_if_fail (object != NULL);
931
g_return_if_fail (GVC_IS_MIXER_STREAM (object));
933
mixer_stream = GVC_MIXER_STREAM (object);
935
g_return_if_fail (mixer_stream->priv != NULL);
937
g_object_unref (mixer_stream->priv->channel_map);
938
mixer_stream->priv->channel_map = NULL;
940
g_free (mixer_stream->priv->name);
941
mixer_stream->priv->name = NULL;
943
g_free (mixer_stream->priv->description);
944
mixer_stream->priv->description = NULL;
946
g_free (mixer_stream->priv->application_id);
947
mixer_stream->priv->application_id = NULL;
949
g_free (mixer_stream->priv->icon_name);
950
mixer_stream->priv->icon_name = NULL;
952
g_free (mixer_stream->priv->port);
953
mixer_stream->priv->port = NULL;
955
g_free (mixer_stream->priv->human_port);
956
mixer_stream->priv->human_port = NULL;
958
g_list_foreach (mixer_stream->priv->ports, (GFunc) free_port, NULL);
959
g_list_free (mixer_stream->priv->ports);
960
mixer_stream->priv->ports = NULL;
962
if (mixer_stream->priv->change_volume_op) {
963
pa_operation_unref(mixer_stream->priv->change_volume_op);
964
mixer_stream->priv->change_volume_op = NULL;
967
G_OBJECT_CLASS (gvc_mixer_stream_parent_class)->finalize (object);