~kroq-gar78/ubuntu/precise/gnome-control-center/fix-885947

« back to all changes in this revision

Viewing changes to panels/sound/gvc-mixer-stream.c

  • Committer: Bazaar Package Importer
  • Author(s): Rodrigo Moya
  • Date: 2011-05-17 10:47:27 UTC
  • mfrom: (0.1.11 experimental) (1.1.45 upstream)
  • Revision ID: james.westby@ubuntu.com-20110517104727-lqel6m8vhfw5jby1
Tags: 1:3.0.1.1-1ubuntu1
* Rebase on Debian, remaining Ubuntu changes:
* debian/control:
  - Build-Depend on hardening-wrapper, dpkg-dev and dh-autoreconf
  - Add dependency on ubuntu-system-service
  - Remove dependency on gnome-icon-theme-symbolic
  - Move dependency on apg, gnome-icon-theme-symbolic and accountsservice to
    be a Recommends: until we get them in main
* debian/rules:
  - Use autoreconf
  - Add binary-post-install rule for gnome-control-center-data
  - Run dh-autoreconf
* debian/gnome-control-center.dirs:
* debian/gnome-control-center.links:
  - Add a link to the control center shell for indicators
* debian/patches/00_disable-nm.patch:
  - Temporary patch to disable building with NetworkManager until we get
    the new one in the archive
* debian/patches/01_git_remove_gettext_calls.patch:
  - Remove calls to AM_GNU_GETTEXT, IT_PROG_INTLTOOL should be enough
* debian/patches/01_git_kill_warning.patch:
  - Kill warning
* debian/patches/50_ubuntu_systemwide_prefs.patch:
  - Ubuntu specific proxy preferences
* debian/patches/51_ubuntu_system_keyboard.patch:
  - Implement the global keyboard spec at https://wiki.ubuntu.com/DefaultKeyboardSettings

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 *
 
134
 * @stream:
 
135
 *
 
136
 * Returns: (type guint32) (transfer none):
 
137
 */
 
138
pa_volume_t
 
139
gvc_mixer_stream_get_volume (GvcMixerStream *stream)
 
140
{
 
141
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
 
142
 
 
143
        return (pa_volume_t) gvc_channel_map_get_volume(stream->priv->channel_map)[VOLUME];
 
144
}
 
145
 
 
146
gdouble
 
147
gvc_mixer_stream_get_decibel (GvcMixerStream *stream)
 
148
{
 
149
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
 
150
 
 
151
        return pa_sw_volume_to_dB(
 
152
                        (pa_volume_t) gvc_channel_map_get_volume(stream->priv->channel_map)[VOLUME]);
 
153
}
 
154
 
 
155
/**
 
156
 * gvc_mixer_stream_set_volume:
 
157
 *
 
158
 * @stream:
 
159
 * @volume: (type guint32):
 
160
 *
 
161
 * Returns:
 
162
 */
 
163
gboolean
 
164
gvc_mixer_stream_set_volume (GvcMixerStream *stream,
 
165
                              pa_volume_t     volume)
 
166
{
 
167
        pa_cvolume cv;
 
168
 
 
169
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
170
 
 
171
        cv = *gvc_channel_map_get_cvolume(stream->priv->channel_map);
 
172
        pa_cvolume_scale(&cv, volume);
 
173
 
 
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");
 
177
                return TRUE;
 
178
        }
 
179
 
 
180
        return FALSE;
 
181
}
 
182
 
 
183
gboolean
 
184
gvc_mixer_stream_set_decibel (GvcMixerStream *stream,
 
185
                              gdouble         db)
 
186
{
 
187
        pa_cvolume cv;
 
188
 
 
189
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
190
 
 
191
        cv = *gvc_channel_map_get_cvolume(stream->priv->channel_map);
 
192
        pa_cvolume_scale(&cv, pa_sw_volume_from_dB(db));
 
193
 
 
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");
 
197
        }
 
198
 
 
199
        return TRUE;
 
200
}
 
201
 
 
202
gboolean
 
203
gvc_mixer_stream_get_is_muted  (GvcMixerStream *stream)
 
204
{
 
205
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
206
        return stream->priv->is_muted;
 
207
}
 
208
 
 
209
gboolean
 
210
gvc_mixer_stream_get_can_decibel (GvcMixerStream *stream)
 
211
{
 
212
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
213
        return stream->priv->can_decibel;
 
214
}
 
215
 
 
216
gboolean
 
217
gvc_mixer_stream_set_is_muted  (GvcMixerStream *stream,
 
218
                                gboolean        is_muted)
 
219
{
 
220
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
221
 
 
222
        if (is_muted != stream->priv->is_muted) {
 
223
                stream->priv->is_muted = is_muted;
 
224
                g_object_notify (G_OBJECT (stream), "is-muted");
 
225
        }
 
226
 
 
227
        return TRUE;
 
228
}
 
229
 
 
230
gboolean
 
231
gvc_mixer_stream_set_can_decibel  (GvcMixerStream *stream,
 
232
                                   gboolean        can_decibel)
 
233
{
 
234
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
235
 
 
236
        if (can_decibel != stream->priv->can_decibel) {
 
237
                stream->priv->can_decibel = can_decibel;
 
238
                g_object_notify (G_OBJECT (stream), "can-decibel");
 
239
        }
 
240
 
 
241
        return TRUE;
 
242
}
 
243
 
 
244
const char *
 
245
gvc_mixer_stream_get_name (GvcMixerStream *stream)
 
246
{
 
247
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
 
248
        return stream->priv->name;
 
249
}
 
250
 
 
251
const char *
 
252
gvc_mixer_stream_get_description (GvcMixerStream *stream)
 
253
{
 
254
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
 
255
        return stream->priv->description;
 
256
}
 
257
 
 
258
gboolean
 
259
gvc_mixer_stream_set_name (GvcMixerStream *stream,
 
260
                           const char     *name)
 
261
{
 
262
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
263
 
 
264
        g_free (stream->priv->name);
 
265
        stream->priv->name = g_strdup (name);
 
266
        g_object_notify (G_OBJECT (stream), "name");
 
267
 
 
268
        return TRUE;
 
269
}
 
270
 
 
271
gboolean
 
272
gvc_mixer_stream_set_description (GvcMixerStream *stream,
 
273
                                  const char     *description)
 
274
{
 
275
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
276
 
 
277
        g_free (stream->priv->description);
 
278
        stream->priv->description = g_strdup (description);
 
279
        g_object_notify (G_OBJECT (stream), "description");
 
280
 
 
281
        return TRUE;
 
282
}
 
283
 
 
284
gboolean
 
285
gvc_mixer_stream_is_event_stream (GvcMixerStream *stream)
 
286
{
 
287
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
288
 
 
289
        return stream->priv->is_event_stream;
 
290
}
 
291
 
 
292
gboolean
 
293
gvc_mixer_stream_set_is_event_stream (GvcMixerStream *stream,
 
294
                                      gboolean is_event_stream)
 
295
{
 
296
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
297
 
 
298
        stream->priv->is_event_stream = is_event_stream;
 
299
        g_object_notify (G_OBJECT (stream), "is-event-stream");
 
300
 
 
301
        return TRUE;
 
302
}
 
303
 
 
304
gboolean
 
305
gvc_mixer_stream_is_virtual (GvcMixerStream *stream)
 
306
{
 
307
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
308
 
 
309
        return stream->priv->is_virtual;
 
310
}
 
311
 
 
312
gboolean
 
313
gvc_mixer_stream_set_is_virtual (GvcMixerStream *stream,
 
314
                                 gboolean is_virtual)
 
315
{
 
316
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
317
 
 
318
        stream->priv->is_virtual = is_virtual;
 
319
        g_object_notify (G_OBJECT (stream), "is-virtual");
 
320
 
 
321
        return TRUE;
 
322
}
 
323
 
 
324
const char *
 
325
gvc_mixer_stream_get_application_id (GvcMixerStream *stream)
 
326
{
 
327
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
 
328
        return stream->priv->application_id;
 
329
}
 
330
 
 
331
gboolean
 
332
gvc_mixer_stream_set_application_id (GvcMixerStream *stream,
 
333
                                     const char *application_id)
 
334
{
 
335
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
336
 
 
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");
 
340
 
 
341
        return TRUE;
 
342
}
 
343
 
 
344
static void
 
345
on_channel_map_volume_changed (GvcChannelMap  *channel_map,
 
346
                               gboolean        set,
 
347
                               GvcMixerStream *stream)
 
348
{
 
349
        if (set == TRUE)
 
350
                gvc_mixer_stream_push_volume (stream);
 
351
 
 
352
        g_object_notify (G_OBJECT (stream), "volume");
 
353
}
 
354
 
 
355
static gboolean
 
356
gvc_mixer_stream_set_channel_map (GvcMixerStream *stream,
 
357
                                  GvcChannelMap  *channel_map)
 
358
{
 
359
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
360
 
 
361
        if (channel_map != NULL) {
 
362
                g_object_ref (channel_map);
 
363
        }
 
364
 
 
365
        if (stream->priv->channel_map != NULL) {
 
366
                g_signal_handlers_disconnect_by_func (stream->priv->channel_map,
 
367
                                                      on_channel_map_volume_changed,
 
368
                                                      stream);
 
369
                g_object_unref (stream->priv->channel_map);
 
370
        }
 
371
 
 
372
        stream->priv->channel_map = channel_map;
 
373
 
 
374
        if (stream->priv->channel_map != NULL) {
 
375
                g_signal_connect (stream->priv->channel_map,
 
376
                                  "volume-changed",
 
377
                                  G_CALLBACK (on_channel_map_volume_changed),
 
378
                                  stream);
 
379
 
 
380
                g_object_notify (G_OBJECT (stream), "channel-map");
 
381
        }
 
382
 
 
383
        return TRUE;
 
384
}
 
385
 
 
386
const char *
 
387
gvc_mixer_stream_get_icon_name (GvcMixerStream *stream)
 
388
{
 
389
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
 
390
        return stream->priv->icon_name;
 
391
}
 
392
 
 
393
/**
 
394
 * gvc_mixer_stream_get_gicon:
 
395
 * @stream: a #GvcMixerStream
 
396
 *
 
397
 * Returns: (transfer full): a new #GIcon
 
398
 */
 
399
GIcon *
 
400
gvc_mixer_stream_get_gicon (GvcMixerStream *stream)
 
401
{
 
402
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
 
403
        if (stream->priv->icon_name == NULL)
 
404
                return NULL;
 
405
        return g_themed_icon_new_with_default_fallbacks (stream->priv->icon_name);
 
406
}
 
407
 
 
408
gboolean
 
409
gvc_mixer_stream_set_icon_name (GvcMixerStream *stream,
 
410
                                const char     *icon_name)
 
411
{
 
412
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
413
 
 
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");
 
417
 
 
418
        return TRUE;
 
419
}
 
420
 
 
421
/**
 
422
 * gvc_mixer_stream_get_base_volume:
 
423
 *
 
424
 * @stream:
 
425
 *
 
426
 * Returns: (type guint32) (transfer none):
 
427
 */
 
428
pa_volume_t
 
429
gvc_mixer_stream_get_base_volume (GvcMixerStream *stream)
 
430
{
 
431
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
 
432
 
 
433
        return stream->priv->base_volume;
 
434
}
 
435
 
 
436
/**
 
437
 * gvc_mixer_stream_set_base_volume:
 
438
 *
 
439
 * @stream:
 
440
 * @base_volume: (type guint32):
 
441
 *
 
442
 * Returns:
 
443
 */
 
444
gboolean
 
445
gvc_mixer_stream_set_base_volume (GvcMixerStream *stream,
 
446
                                  pa_volume_t base_volume)
 
447
{
 
448
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
449
 
 
450
        stream->priv->base_volume = base_volume;
 
451
 
 
452
        return TRUE;
 
453
}
 
454
 
 
455
const GvcMixerStreamPort *
 
456
gvc_mixer_stream_get_port (GvcMixerStream *stream)
 
457
{
 
458
        GList *l;
 
459
 
 
460
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
 
461
        g_return_val_if_fail (stream->priv->ports != NULL, NULL);
 
462
 
 
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) {
 
466
                        return p;
 
467
                }
 
468
        }
 
469
 
 
470
        g_assert_not_reached ();
 
471
 
 
472
        return NULL;
 
473
}
 
474
 
 
475
gboolean
 
476
gvc_mixer_stream_set_port (GvcMixerStream *stream,
 
477
                           const char     *port)
 
478
{
 
479
        GList *l;
 
480
 
 
481
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
482
        g_return_val_if_fail (stream->priv->ports != NULL, FALSE);
 
483
 
 
484
        g_free (stream->priv->port);
 
485
        stream->priv->port = g_strdup (port);
 
486
 
 
487
        g_free (stream->priv->human_port);
 
488
        stream->priv->human_port = NULL;
 
489
 
 
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);
 
494
                        break;
 
495
                }
 
496
        }
 
497
 
 
498
        g_object_notify (G_OBJECT (stream), "port");
 
499
 
 
500
        return TRUE;
 
501
}
 
502
 
 
503
gboolean
 
504
gvc_mixer_stream_change_port (GvcMixerStream *stream,
 
505
                              const char     *port)
 
506
{
 
507
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
508
        return GVC_MIXER_STREAM_GET_CLASS (stream)->change_port (stream, port);
 
509
}
 
510
 
 
511
const GList *
 
512
gvc_mixer_stream_get_ports (GvcMixerStream *stream)
 
513
{
 
514
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
 
515
        return stream->priv->ports;
 
516
}
 
517
 
 
518
static int
 
519
sort_ports (GvcMixerStreamPort *a,
 
520
            GvcMixerStreamPort *b)
 
521
{
 
522
        if (a->priority == b->priority)
 
523
                return 0;
 
524
        if (a->priority > b->priority)
 
525
                return 1;
 
526
        return -1;
 
527
}
 
528
 
 
529
gboolean
 
530
gvc_mixer_stream_set_ports (GvcMixerStream *stream,
 
531
                            GList          *ports)
 
532
{
 
533
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
534
        g_return_val_if_fail (stream->priv->ports == NULL, FALSE);
 
535
 
 
536
        stream->priv->ports = g_list_sort (ports, (GCompareFunc) sort_ports);
 
537
 
 
538
        return TRUE;
 
539
}
 
540
 
 
541
gint
 
542
gvc_mixer_stream_get_card_index (GvcMixerStream *stream)
 
543
{
 
544
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), PA_INVALID_INDEX);
 
545
        return stream->priv->card_index;
 
546
}
 
547
 
 
548
gboolean
 
549
gvc_mixer_stream_set_card_index (GvcMixerStream *stream,
 
550
                                 gint            card_index)
 
551
{
 
552
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
553
 
 
554
        stream->priv->card_index = card_index;
 
555
        g_object_notify (G_OBJECT (stream), "card-index");
 
556
 
 
557
        return TRUE;
 
558
}
 
559
 
 
560
static void
 
561
gvc_mixer_stream_set_property (GObject       *object,
 
562
                               guint          prop_id,
 
563
                               const GValue  *value,
 
564
                               GParamSpec    *pspec)
 
565
{
 
566
        GvcMixerStream *self = GVC_MIXER_STREAM (object);
 
567
 
 
568
        switch (prop_id) {
 
569
        case PROP_PA_CONTEXT:
 
570
                self->priv->pa_context = g_value_get_pointer (value);
 
571
                break;
 
572
        case PROP_INDEX:
 
573
                self->priv->index = g_value_get_ulong (value);
 
574
                break;
 
575
        case PROP_ID:
 
576
                self->priv->id = g_value_get_ulong (value);
 
577
                break;
 
578
        case PROP_CHANNEL_MAP:
 
579
                gvc_mixer_stream_set_channel_map (self, g_value_get_object (value));
 
580
                break;
 
581
        case PROP_NAME:
 
582
                gvc_mixer_stream_set_name (self, g_value_get_string (value));
 
583
                break;
 
584
        case PROP_DESCRIPTION:
 
585
                gvc_mixer_stream_set_description (self, g_value_get_string (value));
 
586
                break;
 
587
        case PROP_APPLICATION_ID:
 
588
                gvc_mixer_stream_set_application_id (self, g_value_get_string (value));
 
589
                break;
 
590
        case PROP_ICON_NAME:
 
591
                gvc_mixer_stream_set_icon_name (self, g_value_get_string (value));
 
592
                break;
 
593
        case PROP_VOLUME:
 
594
                gvc_mixer_stream_set_volume (self, g_value_get_ulong (value));
 
595
                break;
 
596
        case PROP_DECIBEL:
 
597
                gvc_mixer_stream_set_decibel (self, g_value_get_double (value));
 
598
                break;
 
599
        case PROP_IS_MUTED:
 
600
                gvc_mixer_stream_set_is_muted (self, g_value_get_boolean (value));
 
601
                break;
 
602
        case PROP_IS_EVENT_STREAM:
 
603
                gvc_mixer_stream_set_is_event_stream (self, g_value_get_boolean (value));
 
604
                break;
 
605
        case PROP_IS_VIRTUAL:
 
606
                gvc_mixer_stream_set_is_virtual (self, g_value_get_boolean (value));
 
607
                break;
 
608
        case PROP_CAN_DECIBEL:
 
609
                gvc_mixer_stream_set_can_decibel (self, g_value_get_boolean (value));
 
610
                break;
 
611
        case PROP_PORT:
 
612
                gvc_mixer_stream_set_port (self, g_value_get_string (value));
 
613
                break;
 
614
        case PROP_CARD_INDEX:
 
615
                self->priv->card_index = g_value_get_long (value);
 
616
                break;
 
617
        default:
 
618
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
619
                break;
 
620
        }
 
621
}
 
622
 
 
623
static void
 
624
gvc_mixer_stream_get_property (GObject     *object,
 
625
                               guint        prop_id,
 
626
                               GValue      *value,
 
627
                               GParamSpec  *pspec)
 
628
{
 
629
        GvcMixerStream *self = GVC_MIXER_STREAM (object);
 
630
 
 
631
        switch (prop_id) {
 
632
        case PROP_PA_CONTEXT:
 
633
                g_value_set_pointer (value, self->priv->pa_context);
 
634
                break;
 
635
        case PROP_INDEX:
 
636
                g_value_set_ulong (value, self->priv->index);
 
637
                break;
 
638
        case PROP_ID:
 
639
                g_value_set_ulong (value, self->priv->id);
 
640
                break;
 
641
        case PROP_CHANNEL_MAP:
 
642
                g_value_set_object (value, self->priv->channel_map);
 
643
                break;
 
644
        case PROP_NAME:
 
645
                g_value_set_string (value, self->priv->name);
 
646
                break;
 
647
        case PROP_DESCRIPTION:
 
648
                g_value_set_string (value, self->priv->description);
 
649
                break;
 
650
        case PROP_APPLICATION_ID:
 
651
                g_value_set_string (value, self->priv->application_id);
 
652
                break;
 
653
        case PROP_ICON_NAME:
 
654
                g_value_set_string (value, self->priv->icon_name);
 
655
                break;
 
656
        case PROP_VOLUME:
 
657
                g_value_set_ulong (value,
 
658
                                   pa_cvolume_max(gvc_channel_map_get_cvolume(self->priv->channel_map)));
 
659
                break;
 
660
        case PROP_DECIBEL:
 
661
                g_value_set_double (value,
 
662
                                    pa_sw_volume_to_dB(pa_cvolume_max(gvc_channel_map_get_cvolume(self->priv->channel_map))));
 
663
                break;
 
664
        case PROP_IS_MUTED:
 
665
                g_value_set_boolean (value, self->priv->is_muted);
 
666
                break;
 
667
        case PROP_IS_EVENT_STREAM:
 
668
                g_value_set_boolean (value, self->priv->is_event_stream);
 
669
                break;
 
670
        case PROP_IS_VIRTUAL:
 
671
                g_value_set_boolean (value, self->priv->is_virtual);
 
672
                break;
 
673
        case PROP_CAN_DECIBEL:
 
674
                g_value_set_boolean (value, self->priv->can_decibel);
 
675
                break;
 
676
        case PROP_PORT:
 
677
                g_value_set_string (value, self->priv->port);
 
678
                break;
 
679
        case PROP_CARD_INDEX:
 
680
                g_value_set_long (value, self->priv->card_index);
 
681
                break;
 
682
        default:
 
683
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
684
                break;
 
685
        }
 
686
}
 
687
 
 
688
static GObject *
 
689
gvc_mixer_stream_constructor (GType                  type,
 
690
                              guint                  n_construct_properties,
 
691
                              GObjectConstructParam *construct_params)
 
692
{
 
693
        GObject       *object;
 
694
        GvcMixerStream *self;
 
695
 
 
696
        object = G_OBJECT_CLASS (gvc_mixer_stream_parent_class)->constructor (type, n_construct_properties, construct_params);
 
697
 
 
698
        self = GVC_MIXER_STREAM (object);
 
699
 
 
700
        self->priv->id = get_next_stream_serial ();
 
701
 
 
702
        return object;
 
703
}
 
704
 
 
705
static gboolean
 
706
gvc_mixer_stream_real_change_port (GvcMixerStream *stream,
 
707
                                   const char     *port)
 
708
{
 
709
        return FALSE;
 
710
}
 
711
 
 
712
static gboolean
 
713
gvc_mixer_stream_real_push_volume (GvcMixerStream *stream, gpointer *op)
 
714
{
 
715
        return FALSE;
 
716
}
 
717
 
 
718
static gboolean
 
719
gvc_mixer_stream_real_change_is_muted (GvcMixerStream *stream,
 
720
                                       gboolean        is_muted)
 
721
{
 
722
        return FALSE;
 
723
}
 
724
 
 
725
gboolean
 
726
gvc_mixer_stream_push_volume (GvcMixerStream *stream)
 
727
{
 
728
        pa_operation *op;
 
729
        gboolean ret;
 
730
 
 
731
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
732
 
 
733
        if (stream->priv->is_event_stream != FALSE)
 
734
                return TRUE;
 
735
 
 
736
        g_debug ("Pushing new volume to stream '%s' (%s)",
 
737
                 stream->priv->description, stream->priv->name);
 
738
 
 
739
        ret = GVC_MIXER_STREAM_GET_CLASS (stream)->push_volume (stream, (gpointer *) &op);
 
740
        if (ret) {
 
741
                if (stream->priv->change_volume_op != NULL)
 
742
                        pa_operation_unref (stream->priv->change_volume_op);
 
743
                stream->priv->change_volume_op = op;
 
744
        }
 
745
        return ret;
 
746
}
 
747
 
 
748
gboolean
 
749
gvc_mixer_stream_change_is_muted (GvcMixerStream *stream,
 
750
                                  gboolean        is_muted)
 
751
{
 
752
        gboolean ret;
 
753
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
754
        ret = GVC_MIXER_STREAM_GET_CLASS (stream)->change_is_muted (stream, is_muted);
 
755
        return ret;
 
756
}
 
757
 
 
758
gboolean
 
759
gvc_mixer_stream_is_running (GvcMixerStream *stream)
 
760
{
 
761
        if (stream->priv->change_volume_op == NULL)
 
762
                return FALSE;
 
763
 
 
764
        if ((pa_operation_get_state(stream->priv->change_volume_op) == PA_OPERATION_RUNNING))
 
765
                return TRUE;
 
766
 
 
767
        pa_operation_unref(stream->priv->change_volume_op);
 
768
        stream->priv->change_volume_op = NULL;
 
769
 
 
770
        return FALSE;
 
771
}
 
772
 
 
773
static void
 
774
gvc_mixer_stream_class_init (GvcMixerStreamClass *klass)
 
775
{
 
776
        GObjectClass   *gobject_class = G_OBJECT_CLASS (klass);
 
777
 
 
778
        gobject_class->constructor = gvc_mixer_stream_constructor;
 
779
        gobject_class->finalize = gvc_mixer_stream_finalize;
 
780
        gobject_class->set_property = gvc_mixer_stream_set_property;
 
781
        gobject_class->get_property = gvc_mixer_stream_get_property;
 
782
 
 
783
        klass->push_volume = gvc_mixer_stream_real_push_volume;
 
784
        klass->change_port = gvc_mixer_stream_real_change_port;
 
785
        klass->change_is_muted = gvc_mixer_stream_real_change_is_muted;
 
786
 
 
787
        g_object_class_install_property (gobject_class,
 
788
                                         PROP_INDEX,
 
789
                                         g_param_spec_ulong ("index",
 
790
                                                             "Index",
 
791
                                                             "The index for this stream",
 
792
                                                             0, G_MAXULONG, 0,
 
793
                                                             G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
 
794
        g_object_class_install_property (gobject_class,
 
795
                                         PROP_ID,
 
796
                                         g_param_spec_ulong ("id",
 
797
                                                             "id",
 
798
                                                             "The id for this stream",
 
799
                                                             0, G_MAXULONG, 0,
 
800
                                                             G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
 
801
        g_object_class_install_property (gobject_class,
 
802
                                         PROP_CHANNEL_MAP,
 
803
                                         g_param_spec_object ("channel-map",
 
804
                                                              "channel map",
 
805
                                                              "The channel map for this stream",
 
806
                                                              GVC_TYPE_CHANNEL_MAP,
 
807
                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
808
        g_object_class_install_property (gobject_class,
 
809
                                         PROP_PA_CONTEXT,
 
810
                                         g_param_spec_pointer ("pa-context",
 
811
                                                               "PulseAudio context",
 
812
                                                               "The PulseAudio context for this stream",
 
813
                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
 
814
        g_object_class_install_property (gobject_class,
 
815
                                         PROP_VOLUME,
 
816
                                         g_param_spec_ulong ("volume",
 
817
                                                             "Volume",
 
818
                                                             "The volume for this stream",
 
819
                                                             0, G_MAXULONG, 0,
 
820
                                                             G_PARAM_READWRITE));
 
821
        g_object_class_install_property (gobject_class,
 
822
                                         PROP_DECIBEL,
 
823
                                         g_param_spec_double ("decibel",
 
824
                                                              "Decibel",
 
825
                                                              "The decibel level for this stream",
 
826
                                                              -G_MAXDOUBLE, G_MAXDOUBLE, 0,
 
827
                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
828
 
 
829
        g_object_class_install_property (gobject_class,
 
830
                                         PROP_NAME,
 
831
                                         g_param_spec_string ("name",
 
832
                                                              "Name",
 
833
                                                              "Name to display for this stream",
 
834
                                                              NULL,
 
835
                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
836
        g_object_class_install_property (gobject_class,
 
837
                                         PROP_DESCRIPTION,
 
838
                                         g_param_spec_string ("description",
 
839
                                                              "Description",
 
840
                                                              "Description to display for this stream",
 
841
                                                              NULL,
 
842
                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
843
        g_object_class_install_property (gobject_class,
 
844
                                         PROP_APPLICATION_ID,
 
845
                                         g_param_spec_string ("application-id",
 
846
                                                              "Application identifier",
 
847
                                                              "Application identifier for this stream",
 
848
                                                              NULL,
 
849
                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
850
        g_object_class_install_property (gobject_class,
 
851
                                         PROP_ICON_NAME,
 
852
                                         g_param_spec_string ("icon-name",
 
853
                                                              "Icon Name",
 
854
                                                              "Name of icon to display for this stream",
 
855
                                                              NULL,
 
856
                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
857
        g_object_class_install_property (gobject_class,
 
858
                                         PROP_IS_MUTED,
 
859
                                         g_param_spec_boolean ("is-muted",
 
860
                                                               "is muted",
 
861
                                                               "Whether stream is muted",
 
862
                                                               FALSE,
 
863
                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
864
        g_object_class_install_property (gobject_class,
 
865
                                         PROP_CAN_DECIBEL,
 
866
                                         g_param_spec_boolean ("can-decibel",
 
867
                                                               "can decibel",
 
868
                                                               "Whether stream volume can be converted to decibel units",
 
869
                                                               FALSE,
 
870
                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
871
        g_object_class_install_property (gobject_class,
 
872
                                         PROP_IS_EVENT_STREAM,
 
873
                                         g_param_spec_boolean ("is-event-stream",
 
874
                                                               "is event stream",
 
875
                                                               "Whether stream's role is to play an event",
 
876
                                                               FALSE,
 
877
                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
878
        g_object_class_install_property (gobject_class,
 
879
                                         PROP_IS_VIRTUAL,
 
880
                                         g_param_spec_boolean ("is-virtual",
 
881
                                                               "is virtual stream",
 
882
                                                               "Whether the stream is virtual",
 
883
                                                               FALSE,
 
884
                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
885
        g_object_class_install_property (gobject_class,
 
886
                                         PROP_PORT,
 
887
                                         g_param_spec_string ("port",
 
888
                                                              "Port",
 
889
                                                              "The name of the current port for this stream",
 
890
                                                              NULL,
 
891
                                                              G_PARAM_READWRITE));
 
892
        g_object_class_install_property (gobject_class,
 
893
                                         PROP_CARD_INDEX,
 
894
                                         g_param_spec_long ("card-index",
 
895
                                                             "Card index",
 
896
                                                             "The index of the card for this stream",
 
897
                                                             PA_INVALID_INDEX, G_MAXLONG, PA_INVALID_INDEX,
 
898
                                                             G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
899
        g_type_class_add_private (klass, sizeof (GvcMixerStreamPrivate));
 
900
}
 
901
 
 
902
static void
 
903
gvc_mixer_stream_init (GvcMixerStream *stream)
 
904
{
 
905
        stream->priv = GVC_MIXER_STREAM_GET_PRIVATE (stream);
 
906
}
 
907
 
 
908
static void
 
909
free_port (GvcMixerStreamPort *p)
 
910
{
 
911
        g_free (p->port);
 
912
        g_free (p->human_port);
 
913
        g_free (p);
 
914
}
 
915
 
 
916
static void
 
917
gvc_mixer_stream_finalize (GObject *object)
 
918
{
 
919
        GvcMixerStream *mixer_stream;
 
920
 
 
921
        g_return_if_fail (object != NULL);
 
922
        g_return_if_fail (GVC_IS_MIXER_STREAM (object));
 
923
 
 
924
        mixer_stream = GVC_MIXER_STREAM (object);
 
925
 
 
926
        g_return_if_fail (mixer_stream->priv != NULL);
 
927
 
 
928
        g_object_unref (mixer_stream->priv->channel_map);
 
929
        mixer_stream->priv->channel_map = NULL;
 
930
 
 
931
        g_free (mixer_stream->priv->name);
 
932
        mixer_stream->priv->name = NULL;
 
933
 
 
934
        g_free (mixer_stream->priv->description);
 
935
        mixer_stream->priv->description = NULL;
 
936
 
 
937
        g_free (mixer_stream->priv->application_id);
 
938
        mixer_stream->priv->application_id = NULL;
 
939
 
 
940
        g_free (mixer_stream->priv->icon_name);
 
941
        mixer_stream->priv->icon_name = NULL;
 
942
 
 
943
        g_free (mixer_stream->priv->port);
 
944
        mixer_stream->priv->port = NULL;
 
945
 
 
946
        g_free (mixer_stream->priv->human_port);
 
947
        mixer_stream->priv->human_port = NULL;
 
948
 
 
949
        g_list_foreach (mixer_stream->priv->ports, (GFunc) free_port, NULL);
 
950
        g_list_free (mixer_stream->priv->ports);
 
951
        mixer_stream->priv->ports = NULL;
 
952
 
 
953
       if (mixer_stream->priv->change_volume_op) {
 
954
               pa_operation_unref(mixer_stream->priv->change_volume_op);
 
955
               mixer_stream->priv->change_volume_op = NULL;
 
956
       }
 
957
 
 
958
        G_OBJECT_CLASS (gvc_mixer_stream_parent_class)->finalize (object);
 
959
}