~ctf/unity-settings-daemon/bug1389099_mic_volume_icons

« back to all changes in this revision

Viewing changes to plugins/media-keys/gvc/gvc-mixer-stream.c

  • Committer: Package Import Robot
  • Author(s): Robert Ancell
  • Date: 2014-02-07 11:44:36 UTC
  • Revision ID: package-import@ubuntu.com-20140207114436-7t5u3yvwc4ul7w3e
Tags: upstream-14.04.0
ImportĀ upstreamĀ versionĀ 14.04.0

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