~nathwill-deactivatedaccount-deactivatedaccount/ubuntu/precise/gnome-control-center/fix-lp-978118

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Ken VanDine, Didier Roche, Ken VanDine
  • Date: 2012-02-09 16:44:44 UTC
  • Revision ID: package-import@ubuntu.com-20120209164444-nvlkg36obi95y6n0
Tags: 1:3.2.2-2ubuntu7
[ Didier Roche ]
* debian/patches/04_new_appearance_settings.patch:
  - fix a typo (LP: #929070)
  - new reveal sensitivity default is now 2.0

[ Ken VanDine ]
* debian/patches/96_sound_nua_panel.patch
  - Adding the new sound-nua panel for sound settings, only displayed 
    in Unity, the old sound panel will load in GNOME

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
/**
 
512
 * gvc_mixer_stream_get_ports:
 
513
 *
 
514
 * Return value: (transfer none) (element-type GvcMixerStreamPort):
 
515
 */
 
516
const GList *
 
517
gvc_mixer_stream_get_ports (GvcMixerStream *stream)
 
518
{
 
519
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL);
 
520
        return stream->priv->ports;
 
521
}
 
522
 
 
523
static int
 
524
sort_ports (GvcMixerStreamPort *a,
 
525
            GvcMixerStreamPort *b)
 
526
{
 
527
        if (a->priority == b->priority)
 
528
                return 0;
 
529
        if (a->priority > b->priority)
 
530
                return 1;
 
531
        return -1;
 
532
}
 
533
 
 
534
/**
 
535
 * gvc_mixer_stream_set_ports:
 
536
 * @ports: (transfer full) (element-type GvcMixerStreamPort):
 
537
 */
 
538
gboolean
 
539
gvc_mixer_stream_set_ports (GvcMixerStream *stream,
 
540
                            GList          *ports)
 
541
{
 
542
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
543
        g_return_val_if_fail (stream->priv->ports == NULL, FALSE);
 
544
 
 
545
        stream->priv->ports = g_list_sort (ports, (GCompareFunc) sort_ports);
 
546
 
 
547
        return TRUE;
 
548
}
 
549
 
 
550
gint
 
551
gvc_mixer_stream_get_card_index (GvcMixerStream *stream)
 
552
{
 
553
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), PA_INVALID_INDEX);
 
554
        return stream->priv->card_index;
 
555
}
 
556
 
 
557
gboolean
 
558
gvc_mixer_stream_set_card_index (GvcMixerStream *stream,
 
559
                                 gint            card_index)
 
560
{
 
561
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
562
 
 
563
        stream->priv->card_index = card_index;
 
564
        g_object_notify (G_OBJECT (stream), "card-index");
 
565
 
 
566
        return TRUE;
 
567
}
 
568
 
 
569
static void
 
570
gvc_mixer_stream_set_property (GObject       *object,
 
571
                               guint          prop_id,
 
572
                               const GValue  *value,
 
573
                               GParamSpec    *pspec)
 
574
{
 
575
        GvcMixerStream *self = GVC_MIXER_STREAM (object);
 
576
 
 
577
        switch (prop_id) {
 
578
        case PROP_PA_CONTEXT:
 
579
                self->priv->pa_context = g_value_get_pointer (value);
 
580
                break;
 
581
        case PROP_INDEX:
 
582
                self->priv->index = g_value_get_ulong (value);
 
583
                break;
 
584
        case PROP_ID:
 
585
                self->priv->id = g_value_get_ulong (value);
 
586
                break;
 
587
        case PROP_CHANNEL_MAP:
 
588
                gvc_mixer_stream_set_channel_map (self, g_value_get_object (value));
 
589
                break;
 
590
        case PROP_NAME:
 
591
                gvc_mixer_stream_set_name (self, g_value_get_string (value));
 
592
                break;
 
593
        case PROP_DESCRIPTION:
 
594
                gvc_mixer_stream_set_description (self, g_value_get_string (value));
 
595
                break;
 
596
        case PROP_APPLICATION_ID:
 
597
                gvc_mixer_stream_set_application_id (self, g_value_get_string (value));
 
598
                break;
 
599
        case PROP_ICON_NAME:
 
600
                gvc_mixer_stream_set_icon_name (self, g_value_get_string (value));
 
601
                break;
 
602
        case PROP_VOLUME:
 
603
                gvc_mixer_stream_set_volume (self, g_value_get_ulong (value));
 
604
                break;
 
605
        case PROP_DECIBEL:
 
606
                gvc_mixer_stream_set_decibel (self, g_value_get_double (value));
 
607
                break;
 
608
        case PROP_IS_MUTED:
 
609
                gvc_mixer_stream_set_is_muted (self, g_value_get_boolean (value));
 
610
                break;
 
611
        case PROP_IS_EVENT_STREAM:
 
612
                gvc_mixer_stream_set_is_event_stream (self, g_value_get_boolean (value));
 
613
                break;
 
614
        case PROP_IS_VIRTUAL:
 
615
                gvc_mixer_stream_set_is_virtual (self, g_value_get_boolean (value));
 
616
                break;
 
617
        case PROP_CAN_DECIBEL:
 
618
                gvc_mixer_stream_set_can_decibel (self, g_value_get_boolean (value));
 
619
                break;
 
620
        case PROP_PORT:
 
621
                gvc_mixer_stream_set_port (self, g_value_get_string (value));
 
622
                break;
 
623
        case PROP_CARD_INDEX:
 
624
                self->priv->card_index = g_value_get_long (value);
 
625
                break;
 
626
        default:
 
627
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
628
                break;
 
629
        }
 
630
}
 
631
 
 
632
static void
 
633
gvc_mixer_stream_get_property (GObject     *object,
 
634
                               guint        prop_id,
 
635
                               GValue      *value,
 
636
                               GParamSpec  *pspec)
 
637
{
 
638
        GvcMixerStream *self = GVC_MIXER_STREAM (object);
 
639
 
 
640
        switch (prop_id) {
 
641
        case PROP_PA_CONTEXT:
 
642
                g_value_set_pointer (value, self->priv->pa_context);
 
643
                break;
 
644
        case PROP_INDEX:
 
645
                g_value_set_ulong (value, self->priv->index);
 
646
                break;
 
647
        case PROP_ID:
 
648
                g_value_set_ulong (value, self->priv->id);
 
649
                break;
 
650
        case PROP_CHANNEL_MAP:
 
651
                g_value_set_object (value, self->priv->channel_map);
 
652
                break;
 
653
        case PROP_NAME:
 
654
                g_value_set_string (value, self->priv->name);
 
655
                break;
 
656
        case PROP_DESCRIPTION:
 
657
                g_value_set_string (value, self->priv->description);
 
658
                break;
 
659
        case PROP_APPLICATION_ID:
 
660
                g_value_set_string (value, self->priv->application_id);
 
661
                break;
 
662
        case PROP_ICON_NAME:
 
663
                g_value_set_string (value, self->priv->icon_name);
 
664
                break;
 
665
        case PROP_VOLUME:
 
666
                g_value_set_ulong (value,
 
667
                                   pa_cvolume_max(gvc_channel_map_get_cvolume(self->priv->channel_map)));
 
668
                break;
 
669
        case PROP_DECIBEL:
 
670
                g_value_set_double (value,
 
671
                                    pa_sw_volume_to_dB(pa_cvolume_max(gvc_channel_map_get_cvolume(self->priv->channel_map))));
 
672
                break;
 
673
        case PROP_IS_MUTED:
 
674
                g_value_set_boolean (value, self->priv->is_muted);
 
675
                break;
 
676
        case PROP_IS_EVENT_STREAM:
 
677
                g_value_set_boolean (value, self->priv->is_event_stream);
 
678
                break;
 
679
        case PROP_IS_VIRTUAL:
 
680
                g_value_set_boolean (value, self->priv->is_virtual);
 
681
                break;
 
682
        case PROP_CAN_DECIBEL:
 
683
                g_value_set_boolean (value, self->priv->can_decibel);
 
684
                break;
 
685
        case PROP_PORT:
 
686
                g_value_set_string (value, self->priv->port);
 
687
                break;
 
688
        case PROP_CARD_INDEX:
 
689
                g_value_set_long (value, self->priv->card_index);
 
690
                break;
 
691
        default:
 
692
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
693
                break;
 
694
        }
 
695
}
 
696
 
 
697
static GObject *
 
698
gvc_mixer_stream_constructor (GType                  type,
 
699
                              guint                  n_construct_properties,
 
700
                              GObjectConstructParam *construct_params)
 
701
{
 
702
        GObject       *object;
 
703
        GvcMixerStream *self;
 
704
 
 
705
        object = G_OBJECT_CLASS (gvc_mixer_stream_parent_class)->constructor (type, n_construct_properties, construct_params);
 
706
 
 
707
        self = GVC_MIXER_STREAM (object);
 
708
 
 
709
        self->priv->id = get_next_stream_serial ();
 
710
 
 
711
        return object;
 
712
}
 
713
 
 
714
static gboolean
 
715
gvc_mixer_stream_real_change_port (GvcMixerStream *stream,
 
716
                                   const char     *port)
 
717
{
 
718
        return FALSE;
 
719
}
 
720
 
 
721
static gboolean
 
722
gvc_mixer_stream_real_push_volume (GvcMixerStream *stream, gpointer *op)
 
723
{
 
724
        return FALSE;
 
725
}
 
726
 
 
727
static gboolean
 
728
gvc_mixer_stream_real_change_is_muted (GvcMixerStream *stream,
 
729
                                       gboolean        is_muted)
 
730
{
 
731
        return FALSE;
 
732
}
 
733
 
 
734
gboolean
 
735
gvc_mixer_stream_push_volume (GvcMixerStream *stream)
 
736
{
 
737
        pa_operation *op;
 
738
        gboolean ret;
 
739
 
 
740
        g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
 
741
 
 
742
        if (stream->priv->is_event_stream != FALSE)
 
743
                return TRUE;
 
744
 
 
745
        g_debug ("Pushing new volume to stream '%s' (%s)",
 
746
                 stream->priv->description, stream->priv->name);
 
747
 
 
748
        ret = GVC_MIXER_STREAM_GET_CLASS (stream)->push_volume (stream, (gpointer *) &op);
 
749
        if (ret) {
 
750
                if (stream->priv->change_volume_op != NULL)
 
751
                        pa_operation_unref (stream->priv->change_volume_op);
 
752
                stream->priv->change_volume_op = op;
 
753
        }
 
754
        return ret;
 
755
}
 
756
 
 
757
gboolean
 
758
gvc_mixer_stream_change_is_muted (GvcMixerStream *stream,
 
759
                                  gboolean        is_muted)
 
760
{
 
761
        gboolean ret;
 
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);
 
764
        return ret;
 
765
}
 
766
 
 
767
gboolean
 
768
gvc_mixer_stream_is_running (GvcMixerStream *stream)
 
769
{
 
770
        if (stream->priv->change_volume_op == NULL)
 
771
                return FALSE;
 
772
 
 
773
        if ((pa_operation_get_state(stream->priv->change_volume_op) == PA_OPERATION_RUNNING))
 
774
                return TRUE;
 
775
 
 
776
        pa_operation_unref(stream->priv->change_volume_op);
 
777
        stream->priv->change_volume_op = NULL;
 
778
 
 
779
        return FALSE;
 
780
}
 
781
 
 
782
static void
 
783
gvc_mixer_stream_class_init (GvcMixerStreamClass *klass)
 
784
{
 
785
        GObjectClass   *gobject_class = G_OBJECT_CLASS (klass);
 
786
 
 
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;
 
791
 
 
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;
 
795
 
 
796
        g_object_class_install_property (gobject_class,
 
797
                                         PROP_INDEX,
 
798
                                         g_param_spec_ulong ("index",
 
799
                                                             "Index",
 
800
                                                             "The index for this stream",
 
801
                                                             0, G_MAXULONG, 0,
 
802
                                                             G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
 
803
        g_object_class_install_property (gobject_class,
 
804
                                         PROP_ID,
 
805
                                         g_param_spec_ulong ("id",
 
806
                                                             "id",
 
807
                                                             "The id for this stream",
 
808
                                                             0, G_MAXULONG, 0,
 
809
                                                             G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
 
810
        g_object_class_install_property (gobject_class,
 
811
                                         PROP_CHANNEL_MAP,
 
812
                                         g_param_spec_object ("channel-map",
 
813
                                                              "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,
 
818
                                         PROP_PA_CONTEXT,
 
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,
 
824
                                         PROP_VOLUME,
 
825
                                         g_param_spec_ulong ("volume",
 
826
                                                             "Volume",
 
827
                                                             "The volume for this stream",
 
828
                                                             0, G_MAXULONG, 0,
 
829
                                                             G_PARAM_READWRITE));
 
830
        g_object_class_install_property (gobject_class,
 
831
                                         PROP_DECIBEL,
 
832
                                         g_param_spec_double ("decibel",
 
833
                                                              "Decibel",
 
834
                                                              "The decibel level for this stream",
 
835
                                                              -G_MAXDOUBLE, G_MAXDOUBLE, 0,
 
836
                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
837
 
 
838
        g_object_class_install_property (gobject_class,
 
839
                                         PROP_NAME,
 
840
                                         g_param_spec_string ("name",
 
841
                                                              "Name",
 
842
                                                              "Name to display for this stream",
 
843
                                                              NULL,
 
844
                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
845
        g_object_class_install_property (gobject_class,
 
846
                                         PROP_DESCRIPTION,
 
847
                                         g_param_spec_string ("description",
 
848
                                                              "Description",
 
849
                                                              "Description to display for this stream",
 
850
                                                              NULL,
 
851
                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
852
        g_object_class_install_property (gobject_class,
 
853
                                         PROP_APPLICATION_ID,
 
854
                                         g_param_spec_string ("application-id",
 
855
                                                              "Application identifier",
 
856
                                                              "Application identifier for this stream",
 
857
                                                              NULL,
 
858
                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
859
        g_object_class_install_property (gobject_class,
 
860
                                         PROP_ICON_NAME,
 
861
                                         g_param_spec_string ("icon-name",
 
862
                                                              "Icon Name",
 
863
                                                              "Name of icon to display for this stream",
 
864
                                                              NULL,
 
865
                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
866
        g_object_class_install_property (gobject_class,
 
867
                                         PROP_IS_MUTED,
 
868
                                         g_param_spec_boolean ("is-muted",
 
869
                                                               "is muted",
 
870
                                                               "Whether stream is muted",
 
871
                                                               FALSE,
 
872
                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
873
        g_object_class_install_property (gobject_class,
 
874
                                         PROP_CAN_DECIBEL,
 
875
                                         g_param_spec_boolean ("can-decibel",
 
876
                                                               "can decibel",
 
877
                                                               "Whether stream volume can be converted to decibel units",
 
878
                                                               FALSE,
 
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",
 
883
                                                               "is event stream",
 
884
                                                               "Whether stream's role is to play an event",
 
885
                                                               FALSE,
 
886
                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
887
        g_object_class_install_property (gobject_class,
 
888
                                         PROP_IS_VIRTUAL,
 
889
                                         g_param_spec_boolean ("is-virtual",
 
890
                                                               "is virtual stream",
 
891
                                                               "Whether the stream is virtual",
 
892
                                                               FALSE,
 
893
                                                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
894
        g_object_class_install_property (gobject_class,
 
895
                                         PROP_PORT,
 
896
                                         g_param_spec_string ("port",
 
897
                                                              "Port",
 
898
                                                              "The name of the current port for this stream",
 
899
                                                              NULL,
 
900
                                                              G_PARAM_READWRITE));
 
901
        g_object_class_install_property (gobject_class,
 
902
                                         PROP_CARD_INDEX,
 
903
                                         g_param_spec_long ("card-index",
 
904
                                                             "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));
 
909
}
 
910
 
 
911
static void
 
912
gvc_mixer_stream_init (GvcMixerStream *stream)
 
913
{
 
914
        stream->priv = GVC_MIXER_STREAM_GET_PRIVATE (stream);
 
915
}
 
916
 
 
917
static void
 
918
free_port (GvcMixerStreamPort *p)
 
919
{
 
920
        g_free (p->port);
 
921
        g_free (p->human_port);
 
922
        g_free (p);
 
923
}
 
924
 
 
925
static void
 
926
gvc_mixer_stream_finalize (GObject *object)
 
927
{
 
928
        GvcMixerStream *mixer_stream;
 
929
 
 
930
        g_return_if_fail (object != NULL);
 
931
        g_return_if_fail (GVC_IS_MIXER_STREAM (object));
 
932
 
 
933
        mixer_stream = GVC_MIXER_STREAM (object);
 
934
 
 
935
        g_return_if_fail (mixer_stream->priv != NULL);
 
936
 
 
937
        g_object_unref (mixer_stream->priv->channel_map);
 
938
        mixer_stream->priv->channel_map = NULL;
 
939
 
 
940
        g_free (mixer_stream->priv->name);
 
941
        mixer_stream->priv->name = NULL;
 
942
 
 
943
        g_free (mixer_stream->priv->description);
 
944
        mixer_stream->priv->description = NULL;
 
945
 
 
946
        g_free (mixer_stream->priv->application_id);
 
947
        mixer_stream->priv->application_id = NULL;
 
948
 
 
949
        g_free (mixer_stream->priv->icon_name);
 
950
        mixer_stream->priv->icon_name = NULL;
 
951
 
 
952
        g_free (mixer_stream->priv->port);
 
953
        mixer_stream->priv->port = NULL;
 
954
 
 
955
        g_free (mixer_stream->priv->human_port);
 
956
        mixer_stream->priv->human_port = NULL;
 
957
 
 
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;
 
961
 
 
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;
 
965
       }
 
966
 
 
967
        G_OBJECT_CLASS (gvc_mixer_stream_parent_class)->finalize (object);
 
968
}