~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-dialog.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
 * Copyright (C) 2012 Conor Curran
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
19
 *
 
20
 */
 
21
 
 
22
#include "config.h"
 
23
 
 
24
#include <stdlib.h>
 
25
#include <stdio.h>
 
26
#include <unistd.h>
 
27
#include <math.h>
 
28
 
 
29
#include <glib.h>
 
30
#include <glib/gi18n-lib.h>
 
31
#include <gdk/gdkkeysyms.h>
 
32
#include <gtk/gtk.h>
 
33
#include <pulse/pulseaudio.h>
 
34
 
 
35
 
 
36
#include "gvc-channel-bar.h"
 
37
#include "gvc-balance-bar.h"
 
38
#include "gvc-combo-box.h"
 
39
#include "gvc-mixer-control.h"
 
40
#include "gvc-mixer-card.h"
 
41
#include "gvc-mixer-ui-device.h"
 
42
#include "gvc-mixer-sink.h"
 
43
#include "gvc-mixer-source.h"
 
44
#include "gvc-mixer-source-output.h"
 
45
#include "gvc-mixer-dialog.h"
 
46
#include "gvc-sound-theme-chooser.h"
 
47
#include "gvc-level-bar.h"
 
48
#include "gvc-speaker-test.h"
 
49
#include "gvc-mixer-control-private.h"
 
50
 
 
51
#define SCALE_SIZE 128
 
52
 
 
53
#define GVC_MIXER_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_DIALOG, GvcMixerDialogPrivate))
 
54
 
 
55
struct GvcMixerDialogPrivate
 
56
{
 
57
        GvcMixerControl *mixer_control;
 
58
        GHashTable      *bars;        
 
59
        GtkWidget       *notebook;
 
60
        GtkWidget       *output_bar;
 
61
        GtkWidget       *input_bar;
 
62
        GtkWidget       *input_level_bar;
 
63
        GtkWidget       *effects_bar;
 
64
        GtkWidget       *output_stream_box;
 
65
        GtkWidget       *sound_effects_box;
 
66
        GtkWidget       *hw_box;
 
67
        GtkWidget       *hw_treeview;
 
68
        GtkWidget       *hw_settings_box;
 
69
        GtkWidget       *hw_profile_combo;
 
70
        GtkWidget       *input_box;
 
71
        GtkWidget       *output_box;
 
72
        GtkWidget       *applications_box;
 
73
        GtkWidget       *no_apps_label;
 
74
        GtkWidget       *output_treeview;
 
75
        GtkWidget       *output_settings_box;
 
76
        GtkWidget       *output_balance_bar;
 
77
        GtkWidget       *output_fade_bar;
 
78
        GtkWidget       *output_lfe_bar;
 
79
        GtkWidget       *output_port_combo;
 
80
        GtkWidget       *input_treeview;
 
81
        GtkWidget       *input_settings_box;
 
82
        GtkWidget       *sound_theme_chooser;
 
83
        GtkWidget       *click_feedback_button;
 
84
        GtkWidget       *audible_bell_button;
 
85
        GtkSizeGroup    *size_group;
 
86
        GtkWidget       *selected_output_label;
 
87
        GtkWidget       *selected_input_label;
 
88
        GtkWidget       *test_output_button;
 
89
 
 
90
        gdouble          last_input_peak;
 
91
        guint            num_apps;
 
92
};
 
93
 
 
94
enum {
 
95
        NAME_COLUMN,
 
96
        DEVICE_COLUMN,
 
97
        ACTIVE_COLUMN,
 
98
        ID_COLUMN,
 
99
        SPEAKERS_COLUMN,
 
100
        ICON_COLUMN,
 
101
        NUM_COLUMNS
 
102
};
 
103
 
 
104
enum {
 
105
        HW_ID_COLUMN,
 
106
        HW_ICON_COLUMN,
 
107
        HW_NAME_COLUMN,
 
108
        HW_STATUS_COLUMN,
 
109
        HW_PROFILE_COLUMN,
 
110
        HW_PROFILE_HUMAN_COLUMN,
 
111
        HW_SENSITIVE_COLUMN,
 
112
        HW_NUM_COLUMNS
 
113
};
 
114
 
 
115
enum
 
116
{
 
117
        PROP_0,
 
118
        PROP_MIXER_CONTROL
 
119
};
 
120
 
 
121
static void     gvc_mixer_dialog_class_init (GvcMixerDialogClass *klass);
 
122
static void     gvc_mixer_dialog_init       (GvcMixerDialog      *mixer_dialog);
 
123
static void     gvc_mixer_dialog_finalize   (GObject             *object);
 
124
 
 
125
static void     bar_set_stream              (GvcMixerDialog      *dialog,
 
126
                                             GtkWidget           *bar,
 
127
                                             GvcMixerStream      *stream);
 
128
 
 
129
static void     on_adjustment_value_changed (GtkAdjustment  *adjustment,
 
130
                                             GvcMixerDialog *dialog);
 
131
static void     on_control_output_added (GvcMixerControl *control,
 
132
                                       guint            id,
 
133
                                       GvcMixerDialog  *dialog);
 
134
static void   on_control_active_output_update (GvcMixerControl *control,
 
135
                                               guint            id,
 
136
                                               GvcMixerDialog  *dialog);
 
137
                                       
 
138
static void   on_control_active_input_update (GvcMixerControl *control,
 
139
                                              guint            id,
 
140
                                              GvcMixerDialog  *dialog);
 
141
 
 
142
G_DEFINE_TYPE (GvcMixerDialog, gvc_mixer_dialog, GTK_TYPE_VBOX)
 
143
 
 
144
 
 
145
static void
 
146
update_description (GvcMixerDialog *dialog,
 
147
                    guint column,
 
148
                    const char *value,
 
149
                    GvcMixerStream *stream)
 
150
{
 
151
        GtkTreeModel *model;
 
152
        GtkTreeIter   iter;
 
153
        guint         id;
 
154
 
 
155
        if (GVC_IS_MIXER_SOURCE (stream))
 
156
                model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
 
157
        else if (GVC_IS_MIXER_SINK (stream))
 
158
                model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
 
159
        else
 
160
                g_assert_not_reached ();
 
161
        gtk_tree_model_get_iter_first (model, &iter);
 
162
 
 
163
        id = gvc_mixer_stream_get_id (stream);
 
164
        do {
 
165
                guint       current_id;
 
166
 
 
167
                gtk_tree_model_get (model, &iter,
 
168
                                    ID_COLUMN, &current_id,
 
169
                                    -1);
 
170
                if (id != current_id)
 
171
                        continue;
 
172
 
 
173
                gtk_list_store_set (GTK_LIST_STORE (model),
 
174
                                    &iter,
 
175
                                    column, value,
 
176
                                    -1);
 
177
                break;
 
178
        } while (gtk_tree_model_iter_next (model, &iter));
 
179
}
 
180
 
 
181
static void
 
182
profile_selection_changed (GvcComboBox *combo_box,
 
183
                           const char  *profile,
 
184
                           GvcMixerDialog *dialog)
 
185
{       
 
186
        g_print ("profile_selection_changed - %s", profile);
 
187
        GvcMixerUIDevice *out;
 
188
        out = g_object_get_data (G_OBJECT (combo_box), "uidevice");
 
189
        
 
190
        if (out == NULL) {
 
191
                g_warning ("Could not find Output for profile combo box");
 
192
                return;
 
193
        }
 
194
 
 
195
        if (gvc_mixer_control_change_profile_on_selected_device (dialog->priv->mixer_control, out, profile) == FALSE) {
 
196
                g_warning ("Could not change profile on device %s",
 
197
                           gvc_mixer_ui_device_get_description (out));
 
198
        }
 
199
}
 
200
 
 
201
#define DECAY_STEP .15
 
202
 
 
203
static void
 
204
update_input_peak (GvcMixerDialog *dialog,
 
205
                   gdouble         v)
 
206
{
 
207
        GtkAdjustment *adj;
 
208
 
 
209
        if (dialog->priv->last_input_peak >= DECAY_STEP) {
 
210
                if (v < dialog->priv->last_input_peak - DECAY_STEP) {
 
211
                        v = dialog->priv->last_input_peak - DECAY_STEP;
 
212
                }
 
213
        }
 
214
 
 
215
        dialog->priv->last_input_peak = v;
 
216
 
 
217
        adj = gvc_level_bar_get_peak_adjustment (GVC_LEVEL_BAR (dialog->priv->input_level_bar));
 
218
        if (v >= 0) {
 
219
                gtk_adjustment_set_value (adj, v);
 
220
        } else {
 
221
                gtk_adjustment_set_value (adj, 0.0);
 
222
        }
 
223
}
 
224
 
 
225
static void
 
226
update_input_meter (GvcMixerDialog *dialog,
 
227
                    uint32_t        source_index,
 
228
                    uint32_t        sink_input_idx,
 
229
                    double          v)
 
230
{
 
231
        update_input_peak (dialog, v);
 
232
}
 
233
 
 
234
static void
 
235
on_monitor_suspended_callback (pa_stream *s,
 
236
                               void      *userdata)
 
237
{
 
238
        GvcMixerDialog *dialog;
 
239
 
 
240
        dialog = userdata;
 
241
 
 
242
        if (pa_stream_is_suspended (s)) {
 
243
                g_debug ("Stream suspended");
 
244
                update_input_meter (dialog,
 
245
                                    pa_stream_get_device_index (s),
 
246
                                    PA_INVALID_INDEX,
 
247
                                    -1);
 
248
        }
 
249
}
 
250
 
 
251
static void
 
252
on_monitor_read_callback (pa_stream *s,
 
253
                          size_t     length,
 
254
                          void      *userdata)
 
255
{
 
256
        GvcMixerDialog *dialog;
 
257
        const void     *data;
 
258
        double          v;
 
259
 
 
260
        dialog = userdata;
 
261
 
 
262
        if (pa_stream_peek (s, &data, &length) < 0) {
 
263
                g_warning ("Failed to read data from stream");
 
264
                return;
 
265
        }
 
266
 
 
267
        assert (length > 0);
 
268
        assert (length % sizeof (float) == 0);
 
269
 
 
270
        v = ((const float *) data)[length / sizeof (float) -1];
 
271
 
 
272
        pa_stream_drop (s);
 
273
 
 
274
        if (v < 0) {
 
275
                v = 0;
 
276
        }
 
277
        if (v > 1) {
 
278
                v = 1;
 
279
        }
 
280
 
 
281
        update_input_meter (dialog,
 
282
                            pa_stream_get_device_index (s),
 
283
                            pa_stream_get_monitor_stream (s),
 
284
                            v);
 
285
}
 
286
 
 
287
static void
 
288
create_monitor_stream_for_source (GvcMixerDialog *dialog,
 
289
                                  GvcMixerStream *stream)
 
290
{
 
291
        pa_stream     *s;
 
292
        char           t[16];
 
293
        pa_buffer_attr attr;
 
294
        pa_sample_spec ss;
 
295
        pa_context    *context;
 
296
        int            res;
 
297
        pa_proplist   *proplist;
 
298
        gboolean       has_monitor;
 
299
 
 
300
        if (stream == NULL) {
 
301
                return;
 
302
        }
 
303
        has_monitor = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (stream), "has-monitor"));
 
304
        if (has_monitor != FALSE) {
 
305
                return;
 
306
        }
 
307
 
 
308
        g_debug ("Create monitor for %u",
 
309
                 gvc_mixer_stream_get_index (stream));
 
310
 
 
311
        context = gvc_mixer_control_get_pa_context (dialog->priv->mixer_control);
 
312
 
 
313
        if (pa_context_get_server_protocol_version (context) < 13) {
 
314
                return;
 
315
        }
 
316
 
 
317
        ss.channels = 1;
 
318
        ss.format = PA_SAMPLE_FLOAT32;
 
319
        ss.rate = 25;
 
320
 
 
321
        memset (&attr, 0, sizeof (attr));
 
322
        attr.fragsize = sizeof (float);
 
323
        attr.maxlength = (uint32_t) -1;
 
324
 
 
325
        snprintf (t, sizeof (t), "%u", gvc_mixer_stream_get_index (stream));
 
326
 
 
327
        proplist = pa_proplist_new ();
 
328
        pa_proplist_sets (proplist, PA_PROP_APPLICATION_ID, "org.gnome.VolumeControl");
 
329
        s = pa_stream_new_with_proplist (context, _("Peak detect"), &ss, NULL, proplist);
 
330
        pa_proplist_free (proplist);
 
331
        if (s == NULL) {
 
332
                g_warning ("Failed to create monitoring stream");
 
333
                return;
 
334
        }
 
335
 
 
336
        pa_stream_set_read_callback (s, on_monitor_read_callback, dialog);
 
337
        pa_stream_set_suspended_callback (s, on_monitor_suspended_callback, dialog);
 
338
 
 
339
        res = pa_stream_connect_record (s,
 
340
                                        t,
 
341
                                        &attr,
 
342
                                        (pa_stream_flags_t) (PA_STREAM_DONT_MOVE
 
343
                                                             |PA_STREAM_PEAK_DETECT
 
344
                                                             |PA_STREAM_ADJUST_LATENCY));
 
345
        if (res < 0) {
 
346
                g_warning ("Failed to connect monitoring stream");
 
347
                pa_stream_unref (s);
 
348
        } else {
 
349
                g_object_set_data (G_OBJECT (stream), "has-monitor", GINT_TO_POINTER (TRUE));
 
350
                g_object_set_data (G_OBJECT (dialog->priv->input_level_bar), "pa_stream", s);
 
351
                g_object_set_data (G_OBJECT (dialog->priv->input_level_bar), "stream", stream);
 
352
        }
 
353
}
 
354
 
 
355
static void
 
356
stop_monitor_stream_for_source (GvcMixerDialog *dialog)
 
357
{
 
358
        pa_stream      *s;
 
359
        pa_context     *context;
 
360
        int             res;
 
361
        GvcMixerStream *stream;
 
362
 
 
363
        s = g_object_get_data (G_OBJECT (dialog->priv->input_level_bar), "pa_stream");
 
364
        if (s == NULL)
 
365
                return;
 
366
        stream = g_object_get_data (G_OBJECT (dialog->priv->input_level_bar), "stream");
 
367
        g_assert (stream != NULL);
 
368
 
 
369
        g_debug ("Stopping monitor for %u", pa_stream_get_index (s));
 
370
 
 
371
        context = gvc_mixer_control_get_pa_context (dialog->priv->mixer_control);
 
372
 
 
373
        if (pa_context_get_server_protocol_version (context) < 13) {
 
374
                return;
 
375
        }
 
376
 
 
377
        res = pa_stream_disconnect (s);
 
378
        if (res == 0)
 
379
                g_object_set_data (G_OBJECT (stream), "has-monitor", GINT_TO_POINTER (FALSE));
 
380
        g_object_set_data (G_OBJECT (dialog->priv->input_level_bar), "pa_stream", NULL);
 
381
        g_object_set_data (G_OBJECT (dialog->priv->input_level_bar), "stream", NULL);
 
382
}
 
383
 
 
384
static void
 
385
gvc_mixer_dialog_set_mixer_control (GvcMixerDialog  *dialog,
 
386
                                    GvcMixerControl *control)
 
387
{
 
388
        g_return_if_fail (GVC_MIXER_DIALOG (dialog));
 
389
        g_return_if_fail (GVC_IS_MIXER_CONTROL (control));
 
390
 
 
391
        g_object_ref (control);
 
392
 
 
393
        if (dialog->priv->mixer_control != NULL) {
 
394
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
 
395
                                                      G_CALLBACK (on_control_active_output_update),
 
396
                                                      dialog);
 
397
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
 
398
                                                      G_CALLBACK (on_control_active_input_update),
 
399
                                                      dialog);
 
400
                g_object_unref (dialog->priv->mixer_control);
 
401
        }
 
402
 
 
403
        dialog->priv->mixer_control = control;
 
404
 
 
405
        g_signal_connect (dialog->priv->mixer_control,
 
406
                          "active-output-update",
 
407
                          G_CALLBACK (on_control_active_output_update),
 
408
                          dialog);
 
409
        g_signal_connect (dialog->priv->mixer_control,
 
410
                          "active-input-update",
 
411
                          G_CALLBACK (on_control_active_input_update),
 
412
                          dialog);
 
413
 
 
414
        g_object_notify (G_OBJECT (dialog), "mixer-control");
 
415
}
 
416
 
 
417
static GvcMixerControl *
 
418
gvc_mixer_dialog_get_mixer_control (GvcMixerDialog *dialog)
 
419
{
 
420
        g_return_val_if_fail (GVC_IS_MIXER_DIALOG (dialog), NULL);
 
421
 
 
422
        return dialog->priv->mixer_control;
 
423
}
 
424
 
 
425
static void
 
426
gvc_mixer_dialog_set_property (GObject       *object,
 
427
                               guint          prop_id,
 
428
                               const GValue  *value,
 
429
                               GParamSpec    *pspec)
 
430
{
 
431
        GvcMixerDialog *self = GVC_MIXER_DIALOG (object);
 
432
 
 
433
        switch (prop_id) {
 
434
        case PROP_MIXER_CONTROL:
 
435
                gvc_mixer_dialog_set_mixer_control (self, g_value_get_object (value));
 
436
                break;
 
437
        default:
 
438
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
439
                break;
 
440
        }
 
441
}
 
442
 
 
443
static void
 
444
gvc_mixer_dialog_get_property (GObject     *object,
 
445
                               guint        prop_id,
 
446
                               GValue      *value,
 
447
                               GParamSpec  *pspec)
 
448
{
 
449
        GvcMixerDialog *self = GVC_MIXER_DIALOG (object);
 
450
 
 
451
        switch (prop_id) {
 
452
        case PROP_MIXER_CONTROL:
 
453
                g_value_set_object (value, gvc_mixer_dialog_get_mixer_control (self));
 
454
                break;
 
455
        default:
 
456
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
457
                break;
 
458
        }
 
459
}
 
460
 
 
461
static void
 
462
on_adjustment_value_changed (GtkAdjustment  *adjustment,
 
463
                             GvcMixerDialog *dialog)
 
464
{
 
465
        GvcMixerStream *stream;
 
466
 
 
467
        stream = g_object_get_data (G_OBJECT (adjustment), "gvc-mixer-dialog-stream");
 
468
        if (stream != NULL) {
 
469
                GObject *bar;
 
470
                gdouble volume, rounded;
 
471
                char *name;
 
472
 
 
473
                volume = gtk_adjustment_get_value (adjustment);
 
474
                rounded = round (volume);
 
475
 
 
476
                bar = g_object_get_data (G_OBJECT (adjustment), "gvc-mixer-dialog-bar");
 
477
                g_object_get (bar, "name", &name, NULL);
 
478
                g_debug ("Setting stream volume %lf (rounded: %lf) for bar '%s'", volume, rounded, name);
 
479
                g_free (name);
 
480
 
 
481
                /* FIXME would need to do that in the balance bar really... */
 
482
                /* Make sure we do not unmute muted streams, there's a button for that */
 
483
                if (volume == 0.0)
 
484
                        gvc_mixer_stream_set_is_muted (stream, TRUE);
 
485
                /* Only push the volume if it's actually changed */
 
486
                if (gvc_mixer_stream_set_volume(stream, (pa_volume_t) rounded) != FALSE)
 
487
                        gvc_mixer_stream_push_volume (stream);
 
488
        }
 
489
}
 
490
 
 
491
static void
 
492
on_bar_is_muted_notify (GObject        *object,
 
493
                        GParamSpec     *pspec,
 
494
                        GvcMixerDialog *dialog)
 
495
{
 
496
        gboolean        is_muted;
 
497
        GvcMixerStream *stream;
 
498
 
 
499
        is_muted = gvc_channel_bar_get_is_muted (GVC_CHANNEL_BAR (object));
 
500
 
 
501
        stream = g_object_get_data (object, "gvc-mixer-dialog-stream");
 
502
        if (stream != NULL) {
 
503
                gvc_mixer_stream_change_is_muted (stream, is_muted);
 
504
        } else {
 
505
                char *name;
 
506
                g_object_get (object, "name", &name, NULL);
 
507
                g_warning ("Unable to find stream for bar '%s'", name);
 
508
                g_free (name);
 
509
        }
 
510
}
 
511
 
 
512
static GtkWidget *
 
513
lookup_bar_for_stream (GvcMixerDialog *dialog,
 
514
                       GvcMixerStream *stream)
 
515
{
 
516
        GtkWidget *bar;
 
517
 
 
518
        bar = g_hash_table_lookup (dialog->priv->bars, GUINT_TO_POINTER (gvc_mixer_stream_get_id (stream)));
 
519
 
 
520
        return bar;
 
521
}
 
522
 
 
523
// TODO
 
524
// Do we need this ?
 
525
// UI devices now pull description material mainly for the card ports.
 
526
// Therefore the need for stream description dynamic changes more than ever seems unneccessary. 
 
527
static void
 
528
on_stream_description_notify (GvcMixerStream *stream,
 
529
                              GParamSpec     *pspec,
 
530
                              GvcMixerDialog *dialog)
 
531
{
 
532
        update_description (dialog, NAME_COLUMN,
 
533
                            gvc_mixer_stream_get_description (stream),
 
534
                            stream);
 
535
}
 
536
 
 
537
static void
 
538
on_stream_volume_notify (GObject        *object,
 
539
                         GParamSpec     *pspec,
 
540
                         GvcMixerDialog *dialog)
 
541
{
 
542
        GvcMixerStream *stream;
 
543
        GtkWidget      *bar;
 
544
        GtkAdjustment  *adj;
 
545
        stream = GVC_MIXER_STREAM (object);
 
546
 
 
547
        bar = lookup_bar_for_stream (dialog, stream);
 
548
 
 
549
        if (bar == NULL) {
 
550
                if (stream == gvc_mixer_control_get_default_sink(dialog->priv->mixer_control)) {
 
551
                        bar = dialog->priv->output_bar;
 
552
                }
 
553
                else if(stream == gvc_mixer_control_get_default_source(dialog->priv->mixer_control)) {
 
554
                        bar = dialog->priv->input_bar;
 
555
                }
 
556
                else{
 
557
                        g_warning ("Unable to find bar for stream %s in on_stream_volume_notify()",
 
558
                                   gvc_mixer_stream_get_name (stream));
 
559
                        return;
 
560
                }
 
561
        }
 
562
 
 
563
        adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (bar)));
 
564
 
 
565
        g_signal_handlers_block_by_func (adj,
 
566
                                         on_adjustment_value_changed,
 
567
                                         dialog);
 
568
 
 
569
        gtk_adjustment_set_value (adj,
 
570
                                  gvc_mixer_stream_get_volume (stream));
 
571
 
 
572
        g_signal_handlers_unblock_by_func (adj,
 
573
                                           on_adjustment_value_changed,
 
574
                                           dialog);
 
575
}
 
576
 
 
577
static void
 
578
on_stream_is_muted_notify (GObject        *object,
 
579
                           GParamSpec     *pspec,
 
580
                           GvcMixerDialog *dialog)
 
581
{
 
582
        GvcMixerStream *stream;
 
583
        GtkWidget      *bar;
 
584
        gboolean        is_muted;
 
585
 
 
586
        stream = GVC_MIXER_STREAM (object);
 
587
 
 
588
        bar = lookup_bar_for_stream (dialog, stream);
 
589
 
 
590
        if (bar == NULL) {
 
591
                if (stream == gvc_mixer_control_get_default_sink(dialog->priv->mixer_control)) {
 
592
                        bar = dialog->priv->output_bar;
 
593
                }
 
594
                else if(stream == gvc_mixer_control_get_default_source(dialog->priv->mixer_control)) {
 
595
                        bar = dialog->priv->input_bar;
 
596
                }                
 
597
                else{
 
598
                        g_warning ("Unable to find bar for stream %s in on_stream_muted_notify()",
 
599
                                   gvc_mixer_stream_get_name (stream));
 
600
                        return;
 
601
                }
 
602
        }
 
603
 
 
604
 
 
605
        is_muted = gvc_mixer_stream_get_is_muted (stream);
 
606
        gvc_channel_bar_set_is_muted (GVC_CHANNEL_BAR (bar),
 
607
                                      is_muted);
 
608
 
 
609
        if (stream == gvc_mixer_control_get_default_sink (dialog->priv->mixer_control)) {
 
610
                gtk_widget_set_sensitive (dialog->priv->applications_box,
 
611
                                          !is_muted);
 
612
        }
 
613
 
 
614
}
 
615
 
 
616
static void
 
617
save_bar_for_stream (GvcMixerDialog *dialog,
 
618
                     GvcMixerStream *stream,
 
619
                     GtkWidget      *bar)
 
620
{
 
621
        g_print ("\n saving bar for stream %s",
 
622
                 gvc_mixer_stream_get_name (stream));
 
623
        g_hash_table_insert (dialog->priv->bars,
 
624
                             GUINT_TO_POINTER (gvc_mixer_stream_get_id (stream)),
 
625
                             bar);
 
626
}
 
627
 
 
628
static GtkWidget *
 
629
create_bar (GvcMixerDialog *dialog,
 
630
            gboolean        add_to_size_group,
 
631
            gboolean        symmetric)
 
632
{
 
633
        GtkWidget *bar;
 
634
 
 
635
        bar = gvc_channel_bar_new ();
 
636
        gtk_widget_set_sensitive (bar, FALSE);
 
637
        if (add_to_size_group && dialog->priv->size_group != NULL) {
 
638
                gvc_channel_bar_set_size_group (GVC_CHANNEL_BAR (bar),
 
639
                                                dialog->priv->size_group,
 
640
                                                symmetric);
 
641
        }
 
642
        gvc_channel_bar_set_orientation (GVC_CHANNEL_BAR (bar),
 
643
                                         GTK_ORIENTATION_HORIZONTAL);
 
644
        gvc_channel_bar_set_show_mute (GVC_CHANNEL_BAR (bar),
 
645
                                       TRUE);
 
646
        g_signal_connect (bar,
 
647
                          "notify::is-muted",
 
648
                          G_CALLBACK (on_bar_is_muted_notify),
 
649
                          dialog);
 
650
        return bar;
 
651
}
 
652
 
 
653
static GtkWidget *
 
654
create_app_bar (GvcMixerDialog *dialog,
 
655
                const char     *name,
 
656
                const char     *icon_name)
 
657
{
 
658
        GtkWidget *bar;
 
659
 
 
660
        bar = create_bar (dialog, FALSE, FALSE);
 
661
        gvc_channel_bar_set_ellipsize (GVC_CHANNEL_BAR (bar), TRUE);
 
662
        gvc_channel_bar_set_icon_name (GVC_CHANNEL_BAR (bar), icon_name);
 
663
        if (name == NULL || strchr (name, '_') == NULL) {
 
664
                gvc_channel_bar_set_name (GVC_CHANNEL_BAR (bar), name);
 
665
        } else {
 
666
                char **tokens, *escaped;
 
667
 
 
668
                tokens = g_strsplit (name, "_", -1);
 
669
                escaped = g_strjoinv ("__", tokens);
 
670
                g_strfreev (tokens);
 
671
                gvc_channel_bar_set_name (GVC_CHANNEL_BAR (bar), escaped);
 
672
                g_free (escaped);
 
673
        }
 
674
 
 
675
        return bar;
 
676
}
 
677
 
 
678
/* active_input_update
 
679
 * Handle input update change from the backend (control). 
 
680
 * Trust the backend whole-heartedly to deliver the correct input
 
681
 * i.e. keep it MVC.
 
682
 */
 
683
static void
 
684
active_input_update (GvcMixerDialog *dialog,
 
685
                     GvcMixerUIDevice *active_input)
 
686
{         
 
687
        g_print ("\n active_input_update %s \n", gvc_mixer_ui_device_get_description (active_input));
 
688
        // First make sure the correct UI device is selected.
 
689
        GtkTreeModel *model;
 
690
        GtkTreeIter   iter;
 
691
 
 
692
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
 
693
        gtk_tree_model_get_iter_first (model, &iter);
 
694
        
 
695
        do {
 
696
                gboolean         is_selected = FALSE;
 
697
                gint             id;
 
698
                        
 
699
                gtk_tree_model_get (model, &iter,
 
700
                                    ID_COLUMN, &id,
 
701
                                    -1);
 
702
 
 
703
                is_selected = id == gvc_mixer_ui_device_get_id (active_input);
 
704
                
 
705
                gtk_list_store_set (GTK_LIST_STORE (model),
 
706
                                    &iter,
 
707
                                    ACTIVE_COLUMN, is_selected,
 
708
                                    -1);
 
709
 
 
710
                if (is_selected) {
 
711
                        GtkTreeSelection *selection;
 
712
                        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->input_treeview));
 
713
                        gtk_tree_selection_select_iter (selection, &iter);
 
714
                }
 
715
                
 
716
        }while (gtk_tree_model_iter_next (model, &iter));
 
717
 
 
718
        stop_monitor_stream_for_source (dialog);
 
719
 
 
720
 
 
721
        GvcMixerStream       *stream;  
 
722
        const GvcChannelMap  *map;
 
723
        GtkAdjustment        *adj;
 
724
  
 
725
        stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control, 
 
726
                                                           active_input); 
 
727
 
 
728
        if (stream == NULL) {
 
729
                g_warning ("active_input_update - couldn't find a stream from the supposed active input");
 
730
                gtk_widget_set_sensitive (dialog->priv->input_bar, 
 
731
                                          FALSE);                
 
732
                return;
 
733
        }
 
734
        // Set the label accordingly
 
735
        gtk_label_set_label (GTK_LABEL(dialog->priv->selected_input_label),
 
736
                             g_strdup_printf("Settings for %s",
 
737
                                             gvc_mixer_ui_device_get_description (active_input)));  
 
738
 
 
739
        gvc_channel_bar_set_base_volume (GVC_CHANNEL_BAR (dialog->priv->input_bar),
 
740
                                         gvc_mixer_stream_get_base_volume (stream));
 
741
        gvc_channel_bar_set_is_amplified (GVC_CHANNEL_BAR (dialog->priv->input_bar),
 
742
                                          gvc_mixer_stream_get_can_decibel (stream));
 
743
        /* Update the adjustment in case the previous bar wasn't decibel
 
744
         * capable, and we clipped it */
 
745
        adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (dialog->priv->input_bar)));
 
746
        gtk_adjustment_set_value (adj,
 
747
                                  gvc_mixer_stream_get_volume (stream));        
 
748
        
 
749
        create_monitor_stream_for_source (dialog, stream);
 
750
        // remove any previous stream that might have been pointed at 
 
751
        // the static input bar and connect new signals from new stream.
 
752
        bar_set_stream (dialog, dialog->priv->input_bar, stream);        
 
753
}
 
754
 
 
755
/* active_output_update
 
756
 * Handle output update change from the backend (control). 
 
757
 * Trust the backend whole heartedly to deliver the correct output
 
758
 * i.e. keep it MVC.
 
759
 */
 
760
static void
 
761
active_output_update (GvcMixerDialog *dialog,
 
762
                      GvcMixerUIDevice *active_output)
 
763
{                 
 
764
        // First make sure the correct UI device is selected.
 
765
        GtkTreeModel *model;
 
766
        GtkTreeIter   iter;
 
767
        g_print ("\n\n active output update - device id = %i \n\n",
 
768
                 gvc_mixer_ui_device_get_id (active_output));
 
769
 
 
770
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
 
771
        gtk_tree_model_get_iter_first (model, &iter);
 
772
        
 
773
        do {
 
774
                gboolean         is_selected;
 
775
                gint             id;
 
776
                        
 
777
                gtk_tree_model_get (model, &iter,
 
778
                                    ID_COLUMN, &id,
 
779
                                    ACTIVE_COLUMN, &is_selected,                  
 
780
                                    -1);
 
781
 
 
782
                if (is_selected && id == gvc_mixer_ui_device_get_id (active_output)) {
 
783
                        g_print ("\n\n unneccessary active output update unless it was a profile change on the same device ? \n\n");
 
784
                        //return;        
 
785
                }
 
786
 
 
787
                is_selected = id == gvc_mixer_ui_device_get_id (active_output);
 
788
                
 
789
                gtk_list_store_set (GTK_LIST_STORE (model),
 
790
                                    &iter,
 
791
                                    ACTIVE_COLUMN, is_selected,
 
792
                                    -1);
 
793
 
 
794
                if (is_selected) {
 
795
                        GtkTreeSelection *selection;
 
796
                        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->output_treeview));
 
797
                        gtk_tree_selection_select_iter (selection, &iter);
 
798
                }
 
799
                
 
800
        }while (gtk_tree_model_iter_next (model, &iter));
 
801
        
 
802
          // Not ideal but for now destroy the combo and recreate below.
 
803
        if (dialog->priv->output_port_combo != NULL) {
 
804
                gtk_container_remove (GTK_CONTAINER (dialog->priv->output_settings_box),
 
805
                                      dialog->priv->output_port_combo);
 
806
                dialog->priv->output_port_combo = NULL;
 
807
        }
 
808
 
 
809
        GvcMixerStream       *stream;  
 
810
        const GvcChannelMap *map;
 
811
        GtkAdjustment        *adj;
 
812
  
 
813
        stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control, 
 
814
                                                           active_output); 
 
815
 
 
816
        if (stream == NULL) {
 
817
                g_warning ("active_output_update - couldn't find a stream from the supposed active output");
 
818
                return;
 
819
        }
 
820
 
 
821
        gboolean is_muted = gvc_mixer_stream_get_is_muted (stream);
 
822
        gtk_widget_set_sensitive (dialog->priv->applications_box,
 
823
                                  !is_muted);
 
824
        adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (dialog->priv->output_bar)));
 
825
        g_signal_handlers_disconnect_by_func(adj, on_adjustment_value_changed, dialog);
 
826
 
 
827
        bar_set_stream (dialog, dialog->priv->output_bar, stream);
 
828
        gvc_channel_bar_set_base_volume (GVC_CHANNEL_BAR (dialog->priv->output_bar),
 
829
                                         gvc_mixer_stream_get_base_volume (stream));
 
830
        gvc_channel_bar_set_is_amplified (GVC_CHANNEL_BAR (dialog->priv->output_bar),
 
831
                                          gvc_mixer_stream_get_can_decibel (stream));
 
832
        /* Update the adjustment in case the previous bar wasn't decibel
 
833
         * capable, and we clipped it */
 
834
        adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (dialog->priv->output_bar)));
 
835
        gtk_adjustment_set_value (adj,
 
836
                                  gvc_mixer_stream_get_volume (stream));
 
837
 
 
838
        map = gvc_mixer_stream_get_channel_map (stream);
 
839
 
 
840
        if (map == NULL) {
 
841
                g_warning ("Active output stream has no channel map");
 
842
                gtk_widget_set_sensitive (dialog->priv->output_bar, FALSE);
 
843
                gtk_widget_set_sensitive (dialog->priv->output_balance_bar, FALSE);
 
844
                gtk_widget_set_sensitive (dialog->priv->output_lfe_bar, FALSE);
 
845
                gtk_widget_set_sensitive (dialog->priv->output_fade_bar, FALSE);                
 
846
                return;
 
847
        }
 
848
 
 
849
 
 
850
        // Swap bars to the active map
 
851
        gvc_balance_bar_set_map (GVC_BALANCE_BAR (dialog->priv->output_balance_bar), 
 
852
                                 map);  
 
853
        gvc_balance_bar_set_map (GVC_BALANCE_BAR (dialog->priv->output_fade_bar), 
 
854
                                 map);
 
855
        gvc_balance_bar_set_map (GVC_BALANCE_BAR (dialog->priv->output_lfe_bar), 
 
856
                                 map);
 
857
                           
 
858
        // Set sensitivities accordingly.
 
859
        gtk_widget_set_sensitive (dialog->priv->output_balance_bar,
 
860
                                  gvc_channel_map_can_balance (map));                                    
 
861
        gtk_widget_set_sensitive (dialog->priv->output_fade_bar, 
 
862
                                  gvc_channel_map_can_fade (map));
 
863
        gtk_widget_set_sensitive (dialog->priv->output_lfe_bar, 
 
864
                                  gvc_channel_map_has_lfe (map));
 
865
        gtk_widget_set_sensitive (dialog->priv->output_bar, 
 
866
                                  TRUE);
 
867
        // Set the label accordingly
 
868
        gtk_label_set_label (GTK_LABEL(dialog->priv->selected_output_label),
 
869
                             g_strdup_printf("Settings for %s",
 
870
                                             gvc_mixer_ui_device_get_description (active_output)));  
 
871
        g_print ("\n active_output_update %s \n", gvc_mixer_ui_device_get_description (active_output));
 
872
 
 
873
        GList* profiles;
 
874
        profiles = gvc_mixer_ui_device_get_profiles (active_output);
 
875
 
 
876
        if (profiles != NULL) {
 
877
                dialog->priv->output_port_combo = gvc_combo_box_new (_("Mode:"));                
 
878
                gvc_combo_box_set_profiles (GVC_COMBO_BOX (dialog->priv->output_port_combo),
 
879
                                            profiles);
 
880
                                
 
881
                gboolean disabled;
 
882
                disabled = gvc_mixer_ui_device_determine_profile_sensitivity (active_output);
 
883
 
 
884
                if (disabled){
 
885
                        GList *profs;
 
886
                        GvcMixerCardProfile *p;
 
887
                        profs = gvc_mixer_ui_device_get_profiles (active_output);
 
888
                        // We can be sure that its just one profile in the list when it's disabled
 
889
                        p = g_list_last (profs)->data;
 
890
                        gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->output_port_combo), 
 
891
                                                                 p->profile);                        
 
892
                }
 
893
                else{
 
894
                        gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->output_port_combo), 
 
895
                                                  gvc_mixer_control_get_active_profile_from_ui_device (dialog->priv->mixer_control,
 
896
                                                                                               active_output));
 
897
                }
 
898
                g_object_set_data (G_OBJECT (dialog->priv->output_port_combo),
 
899
                                   "uidevice",
 
900
                                   active_output);
 
901
                g_signal_connect (G_OBJECT (dialog->priv->output_port_combo), "changed",
 
902
                                  G_CALLBACK (profile_selection_changed), dialog);
 
903
 
 
904
                gtk_box_pack_start (GTK_BOX (dialog->priv->output_settings_box),
 
905
                                    dialog->priv->output_port_combo,
 
906
                                    TRUE, FALSE, 6);
 
907
 
 
908
                if (dialog->priv->size_group != NULL) {
 
909
                        gvc_combo_box_set_size_group (GVC_COMBO_BOX (dialog->priv->output_port_combo),
 
910
                                                      dialog->priv->size_group, FALSE);
 
911
                }
 
912
                gtk_widget_show (dialog->priv->output_port_combo);                
 
913
                gtk_widget_set_sensitive (dialog->priv->output_port_combo, 
 
914
                                           !disabled);
 
915
        }
 
916
 
 
917
}
 
918
 
 
919
static void
 
920
bar_set_stream (GvcMixerDialog *dialog,
 
921
                GtkWidget      *bar,
 
922
                GvcMixerStream *stream)
 
923
{
 
924
        GtkAdjustment  *adj;
 
925
        GvcMixerStream *old_stream;
 
926
 
 
927
        g_assert (bar != NULL);
 
928
 
 
929
        /*
 
930
        old_stream = g_object_get_data (G_OBJECT (bar), "gvc-mixer-dialog-stream");
 
931
 
 
932
        if (old_stream != NULL) {
 
933
                char *name;
 
934
 
 
935
                /*g_object_get (bar, "name", &name, NULL);
 
936
                g_print ("Disconnecting old stream '%s' from bar '%s'",
 
937
                         gvc_mixer_stream_get_name (old_stream), name);
 
938
                g_free (name);
 
939
 
 
940
                g_signal_handlers_disconnect_by_func (old_stream, on_stream_is_muted_notify, dialog);
 
941
                g_signal_handlers_disconnect_by_func (old_stream, on_stream_volume_notify, dialog);
 
942
                
 
943
        }
 
944
        */
 
945
 
 
946
        gtk_widget_set_sensitive (bar, (stream != NULL));
 
947
 
 
948
        adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (bar)));
 
949
 
 
950
        g_signal_handlers_disconnect_by_func (adj, on_adjustment_value_changed, dialog);
 
951
 
 
952
        g_object_set_data (G_OBJECT (bar), "gvc-mixer-dialog-stream", stream);
 
953
        g_object_set_data (G_OBJECT (adj), "gvc-mixer-dialog-stream", stream);
 
954
        g_object_set_data (G_OBJECT (adj), "gvc-mixer-dialog-bar", bar);
 
955
 
 
956
        if (stream != NULL) {
 
957
                gboolean is_muted;
 
958
 
 
959
                is_muted = gvc_mixer_stream_get_is_muted (stream);
 
960
                gvc_channel_bar_set_is_muted (GVC_CHANNEL_BAR (bar), is_muted);
 
961
 
 
962
                gtk_adjustment_set_value (adj,
 
963
                                          gvc_mixer_stream_get_volume (stream));
 
964
                g_signal_connect (stream,
 
965
                                  "notify::is-muted",
 
966
                                  G_CALLBACK (on_stream_is_muted_notify),
 
967
                                  dialog);
 
968
                g_signal_connect (stream,
 
969
                                  "notify::volume",
 
970
                                  G_CALLBACK (on_stream_volume_notify),
 
971
                                  dialog);
 
972
                g_signal_connect (adj,
 
973
                                  "value-changed",
 
974
                                  G_CALLBACK (on_adjustment_value_changed),
 
975
                                  dialog);
 
976
        }
 
977
}
 
978
 
 
979
/**
 
980
* This method handles all streams that are not an input or output
 
981
* i.e. effects streams and application streams
 
982
* TODO rename to truly reflect its usage. 
 
983
**/
 
984
static void
 
985
add_stream (GvcMixerDialog *dialog,
 
986
            GvcMixerStream *stream)
 
987
{
 
988
  
 
989
        GtkWidget     *bar;
 
990
        bar = NULL;
 
991
 
 
992
        if (stream == gvc_mixer_control_get_event_sink_input (dialog->priv->mixer_control)) {
 
993
                bar = dialog->priv->effects_bar;
 
994
                g_debug ("Adding effects stream");
 
995
        } else {
 
996
                // Must be a sink/source input/output
 
997
                const char *name;
 
998
                name = gvc_mixer_stream_get_name (stream);
 
999
                g_print ("\n Add bar for application stream : %s",
 
1000
                             name);
 
1001
 
 
1002
                bar = create_app_bar (dialog, name,
 
1003
                                      gvc_mixer_stream_get_icon_name (stream));
 
1004
 
 
1005
                gtk_box_pack_start (GTK_BOX (dialog->priv->applications_box), bar, FALSE, FALSE, 12);
 
1006
                dialog->priv->num_apps++;
 
1007
                gtk_widget_hide (dialog->priv->no_apps_label);
 
1008
        }
 
1009
        // We should have a bar by now.
 
1010
        g_assert (bar != NULL);
 
1011
        GvcMixerStream *old_stream;
 
1012
 
 
1013
        if (bar != NULL) {
 
1014
                old_stream = g_object_get_data (G_OBJECT (bar), "gvc-mixer-dialog-stream");
 
1015
                if (old_stream != NULL) {
 
1016
                        char *name;
 
1017
                        g_object_get (bar, "name", &name, NULL);
 
1018
                        g_debug ("Disconnecting old stream '%s' from bar '%s'",
 
1019
                                 gvc_mixer_stream_get_name (old_stream), name);
 
1020
                        g_free (name);
 
1021
 
 
1022
                        g_signal_handlers_disconnect_by_func (old_stream, on_stream_is_muted_notify, dialog);
 
1023
                        g_signal_handlers_disconnect_by_func (old_stream, on_stream_volume_notify, dialog);
 
1024
                        g_hash_table_remove (dialog->priv->bars, GUINT_TO_POINTER (gvc_mixer_stream_get_id (old_stream)));
 
1025
                }
 
1026
                save_bar_for_stream (dialog, stream, bar);
 
1027
                bar_set_stream (dialog, bar, stream);
 
1028
                gtk_widget_show (bar);
 
1029
        }
 
1030
}
 
1031
 
 
1032
static void
 
1033
remove_stream (GvcMixerDialog  *dialog,
 
1034
               guint            id)
 
1035
{        
 
1036
        GtkWidget *bar;
 
1037
        bar = g_hash_table_lookup (dialog->priv->bars, GUINT_TO_POINTER (id));
 
1038
        if (bar != NULL) {
 
1039
                g_hash_table_remove (dialog->priv->bars, GUINT_TO_POINTER (id));
 
1040
                gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (bar)),
 
1041
                                      bar);
 
1042
                dialog->priv->num_apps--;
 
1043
                if (dialog->priv->num_apps == 0) {
 
1044
                        gtk_widget_show (dialog->priv->no_apps_label);
 
1045
                }
 
1046
        }
 
1047
 
 
1048
}
 
1049
 
 
1050
static void
 
1051
on_control_stream_added (GvcMixerControl *control,
 
1052
                         guint            id,
 
1053
                         GvcMixerDialog  *dialog)
 
1054
{
 
1055
        GvcMixerStream *stream;
 
1056
        stream = gvc_mixer_control_lookup_stream_id (control, id);
 
1057
        
 
1058
        if (stream == NULL) 
 
1059
                return;
 
1060
        
 
1061
        const char    *app_id;
 
1062
        app_id = gvc_mixer_stream_get_application_id (stream);
 
1063
 
 
1064
        if (stream == gvc_mixer_control_get_event_sink_input (dialog->priv->mixer_control) || (!GVC_IS_MIXER_SOURCE (stream) &&
 
1065
                !GVC_IS_MIXER_SINK (stream)
 
1066
                && !gvc_mixer_stream_is_virtual (stream)
 
1067
                && g_strcmp0 (app_id, "org.gnome.VolumeControl") != 0
 
1068
                && g_strcmp0 (app_id, "org.PulseAudio.pavucontrol") != 0)) {
 
1069
 
 
1070
                GtkWidget      *bar;
 
1071
 
 
1072
                bar = g_hash_table_lookup (dialog->priv->bars, GUINT_TO_POINTER (id));
 
1073
                if (bar != NULL) {
 
1074
                        g_debug ("GvcMixerDialog: Stream %u already added", id);
 
1075
                        return;
 
1076
                }
 
1077
                add_stream (dialog, stream);
 
1078
        } 
 
1079
}
 
1080
 
 
1081
static void
 
1082
on_control_stream_removed (GvcMixerControl *control,
 
1083
                           guint            id,
 
1084
                           GvcMixerDialog  *dialog)
 
1085
{
 
1086
        remove_stream (dialog, id);
 
1087
}
 
1088
 
 
1089
static gboolean
 
1090
find_item_by_id (GtkTreeModel *model,
 
1091
                 guint         id,
 
1092
                 guint         column,
 
1093
                 GtkTreeIter  *iter)
 
1094
{
 
1095
        gboolean found_item;
 
1096
 
 
1097
        found_item = FALSE;
 
1098
 
 
1099
        if (!gtk_tree_model_get_iter_first (model, iter)) {
 
1100
                return FALSE;
 
1101
        }
 
1102
 
 
1103
        do {
 
1104
                guint t_id;
 
1105
 
 
1106
                gtk_tree_model_get (model, iter,
 
1107
                                    column, &t_id, -1);
 
1108
 
 
1109
                if (id == t_id) {
 
1110
                        found_item = TRUE;
 
1111
                }
 
1112
        } while (!found_item && gtk_tree_model_iter_next (model, iter));
 
1113
 
 
1114
        return found_item;
 
1115
}
 
1116
 
 
1117
static void
 
1118
add_input_ui_entry (GvcMixerDialog *dialog,
 
1119
                    GvcMixerUIDevice *input)
 
1120
{
 
1121
        g_print ("\n Add input ui entry with id : %u \n",
 
1122
                  gvc_mixer_ui_device_get_id (input));
 
1123
 
 
1124
        gchar    *port_name;
 
1125
        gchar    *origin;
 
1126
        gchar    *description;
 
1127
        gboolean active;
 
1128
        gboolean available;
 
1129
        gint     card_id;
 
1130
        gint     stream_id;
 
1131
 
 
1132
        g_object_get (G_OBJECT (input),
 
1133
                     "stream-id", &stream_id,
 
1134
                     "card-id", &card_id,
 
1135
                     "origin", &origin,
 
1136
                     "description", &description,
 
1137
                     "port-name", &port_name,
 
1138
                     "port-available", &available,
 
1139
                      NULL);
 
1140
        
 
1141
        GtkTreeModel        *model;
 
1142
        GtkTreeIter          iter;
 
1143
        const GvcChannelMap *map;
 
1144
        GIcon               *icon;
 
1145
 
 
1146
        if (card_id == GVC_MIXER_UI_DEVICE_INVALID) {
 
1147
                GvcMixerStream *stream;
 
1148
                g_print ("just detected a network source");
 
1149
                stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control, input);
 
1150
                if (stream == NULL) {
 
1151
                        g_warning ("tried to add the network source but the stream was null - fail ?!");
 
1152
                        g_free (port_name);                                     
 
1153
                        g_free (origin);                                                        
 
1154
                        g_free (description);                                           
 
1155
                        return;
 
1156
                }
 
1157
                icon = gvc_mixer_stream_get_gicon (stream);                     
 
1158
        }
 
1159
        else{
 
1160
                GvcMixerCard        *card;
 
1161
                card = gvc_mixer_control_lookup_card_id (dialog->priv->mixer_control, card_id);
 
1162
                icon = gvc_mixer_card_get_gicon (card);                 
 
1163
        }
 
1164
 
 
1165
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
 
1166
        gtk_list_store_append (GTK_LIST_STORE (model), &iter);
 
1167
 
 
1168
        gtk_list_store_set (GTK_LIST_STORE (model),
 
1169
                            &iter,
 
1170
                            NAME_COLUMN, description,
 
1171
                            DEVICE_COLUMN, origin,
 
1172
                            ACTIVE_COLUMN, FALSE,
 
1173
                            ICON_COLUMN, icon,
 
1174
                            ID_COLUMN, gvc_mixer_ui_device_get_id (input),
 
1175
                            SPEAKERS_COLUMN,origin,
 
1176
                            -1);
 
1177
 
 
1178
        if (icon != NULL)
 
1179
                g_object_unref (icon);
 
1180
 
 
1181
        // TODO check this.
 
1182
        /*g_signal_connect (output,
 
1183
                          "notify::description",
 
1184
                          G_CALLBACK (on_output_description_notify),
 
1185
                          dialog);*/
 
1186
              
 
1187
        g_free (port_name);                                        
 
1188
        g_free (origin);                                                        
 
1189
        g_free (description);                   
 
1190
}                                   
 
1191
 
 
1192
static void
 
1193
add_output_ui_entry (GvcMixerDialog *dialog,
 
1194
                     GvcMixerUIDevice *output)
 
1195
{
 
1196
        g_print ("\n Add output ui entry with id : %u \n",
 
1197
                  gvc_mixer_ui_device_get_id (output));
 
1198
 
 
1199
        gchar    *sink_port_name;
 
1200
        gchar    *origin;
 
1201
        gchar    *description;
 
1202
        gboolean active;
 
1203
        gboolean available;
 
1204
        gint     card_id;
 
1205
        gint     sink_stream_id;
 
1206
 
 
1207
        g_object_get (G_OBJECT (output),
 
1208
                     "stream-id", &sink_stream_id,
 
1209
                     "card-id", &card_id,
 
1210
                     "origin", &origin,
 
1211
                     "description", &description,
 
1212
                     "port-name", &sink_port_name,
 
1213
                     "port-available", &available,
 
1214
                      NULL);
 
1215
        
 
1216
        GtkTreeModel        *model;
 
1217
        GtkTreeIter          iter;
 
1218
        const GvcChannelMap *map;
 
1219
        GIcon               *icon;
 
1220
 
 
1221
        if (card_id == GVC_MIXER_UI_DEVICE_INVALID) {
 
1222
                g_print ("just detected a network sink");
 
1223
                
 
1224
                GvcMixerStream *stream;
 
1225
                stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control, output);
 
1226
                if (stream == NULL) {
 
1227
                        g_warning ("tried to add the network sink but the stream was null - fail ?!");
 
1228
                        g_free (sink_port_name);                                        
 
1229
                        g_free (origin);                                                        
 
1230
                        g_free (description);                                           
 
1231
                        return;
 
1232
                }
 
1233
                icon = gvc_mixer_stream_get_gicon (stream);                     
 
1234
        }
 
1235
        else{
 
1236
                GvcMixerCard        *card;
 
1237
                card = gvc_mixer_control_lookup_card_id (dialog->priv->mixer_control, card_id);
 
1238
                icon = gvc_mixer_card_get_gicon (card);                 
 
1239
        }
 
1240
 
 
1241
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
 
1242
        gtk_list_store_append (GTK_LIST_STORE (model), &iter);
 
1243
 
 
1244
        gtk_list_store_set (GTK_LIST_STORE (model),
 
1245
                            &iter,
 
1246
                            NAME_COLUMN, description,
 
1247
                            DEVICE_COLUMN, origin,
 
1248
                            ACTIVE_COLUMN, FALSE,
 
1249
                            ICON_COLUMN, icon,
 
1250
                            ID_COLUMN, gvc_mixer_ui_device_get_id (output),
 
1251
                            SPEAKERS_COLUMN,origin,
 
1252
                            -1);
 
1253
 
 
1254
        if (icon != NULL)
 
1255
                g_object_unref (icon);
 
1256
 
 
1257
        // TODO check this.
 
1258
        /*g_signal_connect (output,
 
1259
                          "notify::description",
 
1260
                          G_CALLBACK (on_output_description_notify),
 
1261
                          dialog);*/
 
1262
              
 
1263
        g_free (sink_port_name);                                        
 
1264
        g_free (origin);                                                        
 
1265
        g_free (description);                   
 
1266
}                                   
 
1267
 
 
1268
static void
 
1269
on_control_output_added (GvcMixerControl *control,
 
1270
                         guint            id,
 
1271
                         GvcMixerDialog  *dialog)
 
1272
{
 
1273
        GvcMixerUIDevice* out = NULL;
 
1274
        out = gvc_mixer_control_lookup_output_id (control, id);
 
1275
 
 
1276
        if (out == NULL) {
 
1277
                g_warning ("on_control_output_added - tried to fetch an output of id %u but got nothing", id);
 
1278
                return;
 
1279
        }
 
1280
 
 
1281
        add_output_ui_entry (dialog, out);
 
1282
}
 
1283
 
 
1284
static void
 
1285
on_control_active_output_update (GvcMixerControl *control,
 
1286
                                 guint            id,
 
1287
                                 GvcMixerDialog  *dialog)
 
1288
{
 
1289
        GvcMixerUIDevice* out = NULL;
 
1290
        out = gvc_mixer_control_lookup_output_id (control, id);
 
1291
 
 
1292
        if (out == NULL) {
 
1293
                g_warning ("\n on_control_active_output_update - tried to fetch an output of id %u but got nothing", id);
 
1294
                return;
 
1295
        }
 
1296
        active_output_update (dialog, out);
 
1297
}
 
1298
 
 
1299
static void
 
1300
on_control_active_input_update (GvcMixerControl *control,
 
1301
                                 guint            id,
 
1302
                                 GvcMixerDialog  *dialog)
 
1303
{
 
1304
        GvcMixerUIDevice* in = NULL;
 
1305
        in = gvc_mixer_control_lookup_input_id (control, id);
 
1306
 
 
1307
        if (in == NULL) {
 
1308
                g_warning ("on_control_active_input_update - tried to fetch an input of id %u but got nothing", id);
 
1309
                return;
 
1310
        }
 
1311
        active_input_update (dialog, in);
 
1312
}
 
1313
 
 
1314
static void
 
1315
on_control_input_added (GvcMixerControl *control,
 
1316
                        guint            id,
 
1317
                        GvcMixerDialog  *dialog)
 
1318
{
 
1319
        GvcMixerUIDevice* in = NULL;
 
1320
        in = gvc_mixer_control_lookup_input_id (control, id);
 
1321
 
 
1322
        if (in == NULL) {
 
1323
                g_warning ("on_control_input_added - tried to fetch an input of id %u but got nothing", id);
 
1324
                return;
 
1325
        }
 
1326
        add_input_ui_entry (dialog, in);
 
1327
}
 
1328
 
 
1329
static void
 
1330
on_control_output_removed (GvcMixerControl *control,
 
1331
                           guint            id,
 
1332
                           GvcMixerDialog  *dialog)
 
1333
{
 
1334
        GtkWidget    *bar;
 
1335
        gboolean      found;
 
1336
        GtkTreeIter   iter;
 
1337
        GtkTreeModel *model;
 
1338
 
 
1339
        GvcMixerUIDevice* out = NULL;
 
1340
        out = gvc_mixer_control_lookup_output_id (control, id);
 
1341
        
 
1342
        gint sink_stream_id;
 
1343
        
 
1344
        g_object_get (G_OBJECT (out),
 
1345
                     "stream-id", &sink_stream_id,
 
1346
                      NULL);
 
1347
                      
 
1348
        g_print ("Remove output from dialog \n id : %u \n sink stream id : %i \n",
 
1349
                  id,
 
1350
                  sink_stream_id);
 
1351
 
 
1352
        /* remove from any models */
 
1353
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
 
1354
        found = find_item_by_id (GTK_TREE_MODEL (model), id, ID_COLUMN, &iter);
 
1355
        if (found) {
 
1356
                gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
 
1357
        }
 
1358
}     
 
1359
 
 
1360
 
 
1361
                 
 
1362
static void
 
1363
on_control_input_removed (GvcMixerControl *control,
 
1364
                           guint            id,
 
1365
                           GvcMixerDialog  *dialog)
 
1366
{
 
1367
        GtkWidget    *bar;
 
1368
        gboolean      found;
 
1369
        GtkTreeIter   iter;
 
1370
        GtkTreeModel *model;
 
1371
 
 
1372
        GvcMixerUIDevice* in = NULL;
 
1373
        in = gvc_mixer_control_lookup_input_id (control, id);
 
1374
        
 
1375
        gint stream_id;
 
1376
        
 
1377
        g_object_get (G_OBJECT (in),
 
1378
                     "stream-id", &stream_id,
 
1379
                      NULL);
 
1380
                      
 
1381
        g_print ("Remove input from dialog \n id : %u \n stream id : %i \n",
 
1382
                  id,
 
1383
                  stream_id);
 
1384
 
 
1385
        /* remove from any models */
 
1386
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
 
1387
        found = find_item_by_id (GTK_TREE_MODEL (model), id, ID_COLUMN, &iter);
 
1388
        if (found) {
 
1389
                gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
 
1390
        }        
 
1391
}
 
1392
 
 
1393
static void
 
1394
_gtk_label_make_bold (GtkLabel *label)
 
1395
{
 
1396
        PangoFontDescription *font_desc;
 
1397
 
 
1398
        font_desc = pango_font_description_new ();
 
1399
 
 
1400
        pango_font_description_set_weight (font_desc,
 
1401
                                           PANGO_WEIGHT_BOLD);
 
1402
 
 
1403
        /* This will only affect the weight of the font, the rest is
 
1404
         * from the current state of the widget, which comes from the
 
1405
         * theme or user prefs, since the font desc only has the
 
1406
         * weight flag turned on.
 
1407
         */
 
1408
        gtk_widget_modify_font (GTK_WIDGET (label), font_desc);
 
1409
 
 
1410
        pango_font_description_free (font_desc);
 
1411
}
 
1412
 
 
1413
 
 
1414
static void
 
1415
on_input_selection_changed (GtkTreeSelection *selection,
 
1416
                             GvcMixerDialog   *dialog)
 
1417
{
 
1418
        GtkTreeModel *model;
 
1419
        GtkTreeIter   iter;
 
1420
        gboolean      toggled;
 
1421
        guint         id;
 
1422
 
 
1423
        if (gtk_tree_selection_get_selected (selection, &model, &iter) == FALSE) {
 
1424
                g_debug ("Could not get default input from selection");
 
1425
                return;
 
1426
        }
 
1427
 
 
1428
        gtk_tree_model_get (model, &iter,
 
1429
                            ID_COLUMN, &id,
 
1430
                            ACTIVE_COLUMN, &toggled,
 
1431
                            -1);
 
1432
 
 
1433
        toggled ^= 1;
 
1434
        GvcMixerUIDevice *input;
 
1435
        //g_print ("on_input_selection_changed - try swap to input with id %u", id); 
 
1436
        input = gvc_mixer_control_lookup_input_id (dialog->priv->mixer_control, id);
 
1437
        
 
1438
        if (input == NULL) {
 
1439
                g_warning ("on_input_selection_changed - Unable to find input with id: %u", id);
 
1440
                return;
 
1441
        }
 
1442
 
 
1443
        gvc_mixer_control_change_input (dialog->priv->mixer_control, input);
 
1444
 
 
1445
        /*if (toggled) {
 
1446
                GvcMixerStream *stream;
 
1447
 
 
1448
                g_debug ("Default input selected: %u", id);
 
1449
                stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id);
 
1450
                if (stream == NULL) {
 
1451
                        g_warning ("Unable to find stream for id: %u", id);
 
1452
                        return;
 
1453
                }
 
1454
 
 
1455
                gvc_mixer_control_set_default_source (dialog->priv->mixer_control, stream);
 
1456
        }*/
 
1457
}
 
1458
 
 
1459
static void
 
1460
on_output_selection_changed (GtkTreeSelection *selection,
 
1461
                             GvcMixerDialog   *dialog)
 
1462
{
 
1463
        GtkTreeModel *model;
 
1464
        GtkTreeIter   iter;
 
1465
        gboolean      active;
 
1466
        guint         id;
 
1467
 
 
1468
        if (gtk_tree_selection_get_selected (selection, &model, &iter) == FALSE) {
 
1469
                g_debug ("Could not get default output from selection");
 
1470
                return;
 
1471
        }
 
1472
 
 
1473
        gtk_tree_model_get (model, &iter,
 
1474
                            ID_COLUMN, &id,
 
1475
                            ACTIVE_COLUMN, &active,
 
1476
                            -1);
 
1477
        
 
1478
        g_print ("\n\n on_output_selection_changed - active %i \n\n", active); 
 
1479
        if (active){
 
1480
                return;
 
1481
        }
 
1482
 
 
1483
        GvcMixerUIDevice *output;
 
1484
        g_print ("\n on_output_selection_changed - try swap to output with id %u", id); 
 
1485
        output = gvc_mixer_control_lookup_output_id (dialog->priv->mixer_control, id);
 
1486
        
 
1487
        if (output == NULL) {
 
1488
                g_warning ("on_output_selection_changed - Unable to find output with id: %u", id);
 
1489
                return;
 
1490
        }
 
1491
 
 
1492
        gvc_mixer_control_change_output (dialog->priv->mixer_control, output);
 
1493
}
 
1494
 
 
1495
static void
 
1496
name_to_text (GtkTreeViewColumn *column,
 
1497
              GtkCellRenderer *cell,
 
1498
              GtkTreeModel *model,
 
1499
              GtkTreeIter *iter,
 
1500
              gpointer user_data)
 
1501
{
 
1502
        char *name, *mapping;
 
1503
 
 
1504
        gtk_tree_model_get(model, iter,
 
1505
                           NAME_COLUMN, &name,
 
1506
                           SPEAKERS_COLUMN, &mapping,
 
1507
                           -1);
 
1508
 
 
1509
        if (mapping == NULL) {
 
1510
                g_object_set (cell, "text", name, NULL);
 
1511
        } else {
 
1512
                char *str;
 
1513
 
 
1514
                str = g_strdup_printf ("%s\n<i>%s</i>",
 
1515
                                       name, mapping);
 
1516
                g_object_set (cell, "markup", str, NULL);
 
1517
                g_free (str);
 
1518
        }
 
1519
 
 
1520
        g_free (name);
 
1521
        g_free (mapping);
 
1522
}
 
1523
 
 
1524
static GtkWidget *
 
1525
create_stream_treeview (GvcMixerDialog *dialog,
 
1526
                        GCallback       on_selection_changed)
 
1527
{
 
1528
        GtkWidget         *treeview;
 
1529
        GtkListStore      *store;
 
1530
        GtkCellRenderer   *renderer;
 
1531
        GtkTreeViewColumn *column;
 
1532
        GtkTreeSelection  *selection;
 
1533
 
 
1534
        treeview = gtk_tree_view_new ();
 
1535
        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
 
1536
 
 
1537
        store = gtk_list_store_new (NUM_COLUMNS,
 
1538
                                    G_TYPE_STRING,
 
1539
                                    G_TYPE_STRING,
 
1540
                                    G_TYPE_BOOLEAN,
 
1541
                                    G_TYPE_UINT,
 
1542
                                    G_TYPE_STRING,
 
1543
                                    G_TYPE_ICON);
 
1544
        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
 
1545
                                 GTK_TREE_MODEL (store));
 
1546
 
 
1547
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
 
1548
        gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
 
1549
 
 
1550
        column = gtk_tree_view_column_new ();
 
1551
        gtk_tree_view_column_set_title (column, _("Name"));
 
1552
        renderer = gtk_cell_renderer_pixbuf_new ();
 
1553
        gtk_tree_view_column_pack_start (column, renderer, FALSE);
 
1554
        g_object_set (G_OBJECT (renderer), "stock-size", GTK_ICON_SIZE_LARGE_TOOLBAR, NULL);
 
1555
        gtk_tree_view_column_set_attributes (column, renderer,
 
1556
                                             "gicon", ICON_COLUMN,
 
1557
                                             NULL);
 
1558
 
 
1559
        renderer = gtk_cell_renderer_text_new ();
 
1560
        gtk_tree_view_column_pack_start (column, renderer, TRUE);
 
1561
        gtk_tree_view_column_set_cell_data_func (column, renderer,
 
1562
                                                 name_to_text, NULL, NULL);
 
1563
        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
 
1564
 
 
1565
        g_signal_connect ( selection, "changed",
 
1566
                          on_selection_changed, dialog);
 
1567
#if 0
 
1568
        renderer = gtk_cell_renderer_text_new ();
 
1569
        column = gtk_tree_view_column_new_with_attributes (_("Device"),
 
1570
                                                           renderer,
 
1571
                                                           "text", DEVICE_COLUMN,
 
1572
                                                           NULL);
 
1573
        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
 
1574
#endif
 
1575
        return treeview;
 
1576
}
 
1577
 
 
1578
static void
 
1579
on_profile_changed (GvcComboBox *widget,
 
1580
                    const char  *profile,
 
1581
                    gpointer     user_data)
 
1582
{
 
1583
        GvcMixerCard        *card;
 
1584
 
 
1585
        card = g_object_get_data (G_OBJECT (widget), "card");
 
1586
        if (card == NULL) {
 
1587
                g_warning ("Could not find card for combobox");
 
1588
                return;
 
1589
        }
 
1590
 
 
1591
        g_debug ("Profile changed to %s for card %s", profile,
 
1592
                 gvc_mixer_card_get_name (card));
 
1593
 
 
1594
        gvc_mixer_card_change_profile (card, profile);
 
1595
}
 
1596
 
 
1597
static void
 
1598
on_test_speakers_clicked (GtkButton *widget,
 
1599
                          gpointer  user_data)
 
1600
{
 
1601
        GvcMixerDialog      *dialog = GVC_MIXER_DIALOG (user_data);
 
1602
        GtkTreeModel        *model;
 
1603
        GtkTreeIter         iter;
 
1604
        gint                active_output = GVC_MIXER_UI_DEVICE_INVALID;
 
1605
 
 
1606
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
 
1607
        gtk_tree_model_get_iter_first (model, &iter);
 
1608
        
 
1609
        // Fetch the active output from the treeview (hmmm...)         
 
1610
        
 
1611
        do {
 
1612
                gboolean         is_selected = FALSE ;
 
1613
                gint             id;
 
1614
                        
 
1615
                gtk_tree_model_get (model, &iter,
 
1616
                                    ID_COLUMN, &id,
 
1617
                                    ACTIVE_COLUMN, &is_selected,
 
1618
                                    -1);
 
1619
                
 
1620
                if (is_selected) {
 
1621
                        active_output = id;
 
1622
                        break;
 
1623
                }
 
1624
                
 
1625
        }while (gtk_tree_model_iter_next (model, &iter));
 
1626
        
 
1627
        if (active_output == GVC_MIXER_UI_DEVICE_INVALID) {
 
1628
                g_warning ("Cant find the active output from the UI");
 
1629
                return;
 
1630
        }        
 
1631
 
 
1632
        GvcMixerUIDevice *output;
 
1633
        output = gvc_mixer_control_lookup_output_id (dialog->priv->mixer_control, (guint)active_output);
 
1634
        gint stream_id = gvc_mixer_ui_device_get_stream_id(output);
 
1635
 
 
1636
        if (stream_id == GVC_MIXER_UI_DEVICE_INVALID)
 
1637
                return;
 
1638
 
 
1639
        g_print ("Test the speakers on the %s", gvc_mixer_ui_device_get_description (output));
 
1640
        
 
1641
        GvcMixerStream        *stream;
 
1642
        GvcMixerCardProfile *profile;
 
1643
        GtkWidget           *d, *speaker_test, *container;
 
1644
        char                *title;
 
1645
 
 
1646
        stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, stream_id);
 
1647
        if (stream == NULL) {
 
1648
                g_print ("Stream/sink not found");
 
1649
                return;
 
1650
        }
 
1651
/*        card = gvc_mixer_control_lookup_card_id (dialog->priv->mixer_control, card_id);
 
1652
 
 
1653
        profile = gvc_mixer_card_get_profile (card);
 
1654
 
 
1655
        g_debug ("XXX Start speaker testing for profile '%s', card %s XXX",
 
1656
                 profile->profile, gvc_mixer_card_get_name (card));
 
1657
*/
 
1658
        title = g_strdup_printf (_("Speaker Testing for %s"), gvc_mixer_ui_device_get_description (output));
 
1659
        d = gtk_dialog_new_with_buttons (title,
 
1660
                                         GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (widget))),
 
1661
                                         GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
 
1662
                                         GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
 
1663
                                         NULL);
 
1664
        gtk_window_set_has_resize_grip (GTK_WINDOW (d), FALSE);
 
1665
 
 
1666
        g_free (title);
 
1667
        speaker_test = gvc_speaker_test_new (dialog->priv->mixer_control,
 
1668
                                             stream);
 
1669
        gtk_widget_show (speaker_test);
 
1670
        container = gtk_dialog_get_content_area (GTK_DIALOG (d));
 
1671
        gtk_container_add (GTK_CONTAINER (container), speaker_test);
 
1672
 
 
1673
        gtk_dialog_run (GTK_DIALOG (d));
 
1674
        gtk_widget_destroy (d);
 
1675
}
 
1676
 
 
1677
static GObject *
 
1678
gvc_mixer_dialog_constructor (GType                  type,
 
1679
                              guint                  n_construct_properties,
 
1680
                              GObjectConstructParam *construct_params)
 
1681
{
 
1682
        GObject          *object;
 
1683
        GvcMixerDialog   *self;
 
1684
        GtkWidget        *main_vbox;
 
1685
        GtkWidget        *label;
 
1686
        GtkWidget        *alignment;
 
1687
        GtkWidget        *box;
 
1688
        GtkWidget        *sbox;
 
1689
        GtkWidget        *ebox;
 
1690
        GtkWidget        *test_sound_box;
 
1691
        GSList           *streams;
 
1692
        GSList           *cards;
 
1693
        GSList           *l;
 
1694
        GvcMixerStream   *stream;
 
1695
        GvcMixerCard     *card;
 
1696
        GtkTreeSelection *selection;
 
1697
 
 
1698
        object = G_OBJECT_CLASS (gvc_mixer_dialog_parent_class)->constructor (type, n_construct_properties, construct_params);
 
1699
 
 
1700
        self = GVC_MIXER_DIALOG (object);
 
1701
 
 
1702
        main_vbox = GTK_WIDGET (self);
 
1703
        gtk_box_set_spacing (GTK_BOX (main_vbox), 2);
 
1704
 
 
1705
        gtk_container_set_border_width (GTK_CONTAINER (self), 6);
 
1706
 
 
1707
        self->priv->output_stream_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
 
1708
        alignment = gtk_alignment_new (0, 0, 1, 1);
 
1709
        gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 12, 0, 0, 0);
 
1710
        gtk_container_add (GTK_CONTAINER (alignment), self->priv->output_stream_box);
 
1711
        gtk_box_pack_start (GTK_BOX (main_vbox),
 
1712
                            alignment,
 
1713
                            FALSE, FALSE, 0);
 
1714
 
 
1715
        self->priv->notebook = gtk_notebook_new ();
 
1716
        gtk_box_pack_start (GTK_BOX (main_vbox),
 
1717
                            self->priv->notebook,
 
1718
                            TRUE, TRUE, 0);
 
1719
        gtk_container_set_border_width (GTK_CONTAINER (self->priv->notebook), 5);
 
1720
 
 
1721
        /* Effects page */
 
1722
        self->priv->sound_effects_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
 
1723
        gtk_container_set_border_width (GTK_CONTAINER (self->priv->sound_effects_box), 12);
 
1724
        label = gtk_label_new (_("Sound Effects"));
 
1725
        gtk_notebook_append_page (GTK_NOTEBOOK (self->priv->notebook),
 
1726
                                  self->priv->sound_effects_box,
 
1727
                                  label);
 
1728
 
 
1729
        self->priv->effects_bar = create_bar (self, FALSE, TRUE);
 
1730
        gvc_channel_bar_set_name (GVC_CHANNEL_BAR (self->priv->effects_bar),
 
1731
                                  _("_Alert volume:"));
 
1732
        gtk_widget_set_sensitive (self->priv->effects_bar, FALSE);
 
1733
        gtk_box_pack_start (GTK_BOX (self->priv->sound_effects_box),
 
1734
                            self->priv->effects_bar, FALSE, FALSE, 0);
 
1735
 
 
1736
        self->priv->sound_theme_chooser = gvc_sound_theme_chooser_new ();
 
1737
        gtk_box_pack_start (GTK_BOX (self->priv->sound_effects_box),
 
1738
                            self->priv->sound_theme_chooser,
 
1739
                            TRUE, TRUE, 6);
 
1740
 
 
1741
        /* Input page */
 
1742
        self->priv->input_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
 
1743
        gtk_container_set_border_width (GTK_CONTAINER (self->priv->input_box), 12);
 
1744
        label = gtk_label_new (_("Input"));
 
1745
        gtk_notebook_append_page (GTK_NOTEBOOK (self->priv->notebook),
 
1746
                                  self->priv->input_box,
 
1747
                                  label);
 
1748
        box = gtk_frame_new (_("Record sound from:"));
 
1749
        gtk_widget_set_size_request (GTK_WIDGET (box), 325, -1);        
 
1750
        label = gtk_frame_get_label_widget (GTK_FRAME (box));
 
1751
        _gtk_label_make_bold (GTK_LABEL (label));
 
1752
        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
 
1753
        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
 
1754
        gtk_box_pack_start (GTK_BOX (self->priv->input_box), box, FALSE, TRUE, 0);
 
1755
 
 
1756
        alignment = gtk_alignment_new (0, 0, 1, 1);
 
1757
        gtk_container_add (GTK_CONTAINER (box), alignment);
 
1758
        gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 0, 0);
 
1759
 
 
1760
        self->priv->input_treeview = create_stream_treeview (self,
 
1761
                                                             G_CALLBACK (on_input_selection_changed));
 
1762
        gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->priv->input_treeview);
 
1763
 
 
1764
        box = gtk_scrolled_window_new (NULL, NULL);
 
1765
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (box),
 
1766
                                        GTK_POLICY_NEVER,
 
1767
                                        GTK_POLICY_AUTOMATIC);
 
1768
        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (box),
 
1769
                                             GTK_SHADOW_IN);
 
1770
        gtk_container_add (GTK_CONTAINER (box), self->priv->input_treeview);
 
1771
        gtk_container_add (GTK_CONTAINER (alignment), box);
 
1772
 
 
1773
        self->priv->selected_input_label = gtk_label_new (_("Settings for the selected device:"));
 
1774
        box = gtk_frame_new ("");
 
1775
        gtk_frame_set_label_widget (GTK_FRAME (box), self->priv->selected_input_label);
 
1776
 
 
1777
        label = gtk_frame_get_label_widget (GTK_FRAME (box));
 
1778
        _gtk_label_make_bold (GTK_LABEL (label));
 
1779
        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
 
1780
        gtk_box_pack_start (GTK_BOX (self->priv->input_box), box, FALSE, FALSE, 0);
 
1781
        self->priv->input_settings_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
 
1782
 
 
1783
        self->priv->input_bar = create_bar (self, FALSE, TRUE);
 
1784
        gvc_channel_bar_set_name (GVC_CHANNEL_BAR (self->priv->input_bar),
 
1785
                                  _("_Input volume:"));
 
1786
        gvc_channel_bar_set_low_icon_name (GVC_CHANNEL_BAR (self->priv->input_bar),
 
1787
                                           "audio-input-microphone-low-symbolic");
 
1788
        gvc_channel_bar_set_high_icon_name (GVC_CHANNEL_BAR (self->priv->input_bar),
 
1789
                                            "audio-input-microphone-high-symbolic");
 
1790
        gtk_widget_set_sensitive (self->priv->input_bar, FALSE);
 
1791
 
 
1792
        if (self->priv->size_group != NULL) {
 
1793
                gvc_channel_bar_set_size_group (GVC_CHANNEL_BAR (self->priv->input_bar),
 
1794
                                                self->priv->size_group,
 
1795
                                                FALSE);                
 
1796
        }
 
1797
 
 
1798
        gtk_box_pack_start (GTK_BOX (self->priv->input_settings_box),
 
1799
                            self->priv->input_bar,
 
1800
                            FALSE, FALSE, 3);
 
1801
        gtk_widget_show (self->priv->input_bar);
 
1802
        
 
1803
        gtk_container_add (GTK_CONTAINER (box), self->priv->input_settings_box);
 
1804
        
 
1805
        
 
1806
 
 
1807
        /* Creating a box and try to deal using the same size group. */
 
1808
        GtkWidget *input_level_box;
 
1809
        input_level_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
 
1810
        gtk_box_pack_start (GTK_BOX (self->priv->input_settings_box),
 
1811
                            input_level_box,
 
1812
                            FALSE,
 
1813
                            FALSE,
 
1814
                            5);
 
1815
 
 
1816
        sbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
 
1817
        gtk_box_pack_start (GTK_BOX (input_level_box),
 
1818
                            sbox,
 
1819
                            FALSE, FALSE, 0);
 
1820
        
 
1821
        label = gtk_label_new (_("Input level:"));
 
1822
        gtk_box_pack_start (GTK_BOX (sbox),
 
1823
                            label,
 
1824
                            FALSE, FALSE, 0);
 
1825
        if (self->priv->size_group != NULL)
 
1826
                gtk_size_group_add_widget (self->priv->size_group, sbox);
 
1827
 
 
1828
 
 
1829
        self->priv->input_level_bar = gvc_level_bar_new ();
 
1830
        gvc_level_bar_set_orientation (GVC_LEVEL_BAR (self->priv->input_level_bar),
 
1831
                                       GTK_ORIENTATION_HORIZONTAL);
 
1832
        gvc_level_bar_set_scale (GVC_LEVEL_BAR (self->priv->input_level_bar),
 
1833
                                 GVC_LEVEL_SCALE_LINEAR);
 
1834
 
 
1835
        gtk_box_pack_start (GTK_BOX (input_level_box),
 
1836
                            self->priv->input_level_bar,
 
1837
                            TRUE, TRUE, 10);
 
1838
 
 
1839
 
 
1840
        /* Output page */
 
1841
        self->priv->output_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);        
 
1842
        gtk_container_set_border_width (GTK_CONTAINER (self->priv->output_box), 12);
 
1843
        label = gtk_label_new (_("Output"));
 
1844
        gtk_notebook_append_page (GTK_NOTEBOOK (self->priv->notebook),
 
1845
                                  self->priv->output_box,
 
1846
                                  label);
 
1847
 
 
1848
        box = gtk_frame_new (_("Play sound through:"));
 
1849
        gtk_widget_set_size_request (GTK_WIDGET (box), 325, -1);        
 
1850
        label = gtk_frame_get_label_widget (GTK_FRAME (box));
 
1851
        _gtk_label_make_bold (GTK_LABEL (label));
 
1852
        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
 
1853
        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
 
1854
        gtk_box_pack_start (GTK_BOX (self->priv->output_box), box, FALSE, TRUE, 0);
 
1855
 
 
1856
        alignment = gtk_alignment_new (0, 0, 1, 1);
 
1857
        gtk_container_add (GTK_CONTAINER (box), alignment);
 
1858
        gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 0, 0);
 
1859
 
 
1860
        self->priv->output_treeview = create_stream_treeview (self,
 
1861
                                                              G_CALLBACK (on_output_selection_changed));
 
1862
        gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->priv->output_treeview);
 
1863
 
 
1864
        box = gtk_scrolled_window_new (NULL, NULL);
 
1865
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (box),
 
1866
                                        GTK_POLICY_NEVER,
 
1867
                                        GTK_POLICY_AUTOMATIC);
 
1868
        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (box),
 
1869
                                             GTK_SHADOW_IN);
 
1870
        gtk_container_add (GTK_CONTAINER (box), self->priv->output_treeview);
 
1871
        gtk_container_add (GTK_CONTAINER (alignment), box);
 
1872
 
 
1873
        self->priv->selected_output_label = gtk_label_new (_("Settings for the selected device:"));
 
1874
        box = gtk_frame_new ("");
 
1875
        gtk_frame_set_label_widget (GTK_FRAME (box), self->priv->selected_output_label);
 
1876
 
 
1877
        label = gtk_frame_get_label_widget (GTK_FRAME (box));
 
1878
        _gtk_label_make_bold (GTK_LABEL (label));
 
1879
        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
 
1880
        
 
1881
        gtk_box_pack_start (GTK_BOX (self->priv->output_box), box, FALSE, FALSE, 0);
 
1882
        self->priv->output_settings_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
 
1883
 
 
1884
        
 
1885
        self->priv->output_balance_bar = gvc_balance_bar_new (BALANCE_TYPE_RL);
 
1886
        if (self->priv->size_group != NULL) {
 
1887
                gvc_balance_bar_set_size_group (GVC_BALANCE_BAR (self->priv->output_balance_bar),
 
1888
                                                self->priv->size_group,
 
1889
                                                FALSE);
 
1890
        }
 
1891
        gtk_box_pack_start (GTK_BOX (self->priv->output_settings_box),
 
1892
                            self->priv->output_balance_bar,
 
1893
                            FALSE, FALSE, 3);
 
1894
        gtk_widget_show (self->priv->output_balance_bar);
 
1895
 
 
1896
        self->priv->output_fade_bar = gvc_balance_bar_new (BALANCE_TYPE_FR);
 
1897
        if (self->priv->size_group != NULL) {
 
1898
                gvc_balance_bar_set_size_group (GVC_BALANCE_BAR (self->priv->output_fade_bar),
 
1899
                                                self->priv->size_group,
 
1900
                                                FALSE);
 
1901
        }
 
1902
        gtk_box_pack_start (GTK_BOX (self->priv->output_settings_box),
 
1903
                            self->priv->output_fade_bar,
 
1904
                            FALSE, FALSE, 3);
 
1905
        gtk_widget_show (self->priv->output_fade_bar);
 
1906
 
 
1907
        self->priv->output_lfe_bar = gvc_balance_bar_new (BALANCE_TYPE_LFE);
 
1908
        if (self->priv->size_group != NULL) {
 
1909
                gvc_balance_bar_set_size_group (GVC_BALANCE_BAR (self->priv->output_lfe_bar),
 
1910
                                                self->priv->size_group,
 
1911
                                                FALSE);
 
1912
        }
 
1913
        gtk_box_pack_start (GTK_BOX (self->priv->output_settings_box),
 
1914
                            self->priv->output_lfe_bar,
 
1915
                            FALSE, FALSE, 3);
 
1916
        gtk_widget_show (self->priv->output_lfe_bar);
 
1917
                
 
1918
 
 
1919
        self->priv->output_port_combo = gvc_combo_box_new (_("Modes:"));
 
1920
        g_signal_connect (G_OBJECT (self->priv->output_port_combo), "changed",
 
1921
                          G_CALLBACK (profile_selection_changed), self);
 
1922
        gtk_box_pack_start (GTK_BOX (self->priv->output_settings_box),
 
1923
                            self->priv->output_port_combo,
 
1924
                            TRUE, FALSE, 3);
 
1925
 
 
1926
        if (self->priv->size_group != NULL) {
 
1927
                gvc_combo_box_set_size_group (GVC_COMBO_BOX (self->priv->output_port_combo),
 
1928
                                              self->priv->size_group, FALSE);
 
1929
        }
 
1930
        gtk_widget_show (self->priv->output_port_combo);
 
1931
 
 
1932
        /* Creating a box and try to deal using the same size group. */
 
1933
        test_sound_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
 
1934
        gtk_box_pack_end (GTK_BOX (self->priv->output_settings_box),
 
1935
                          test_sound_box,
 
1936
                          FALSE, 
 
1937
                          FALSE,
 
1938
                          5);
 
1939
 
 
1940
        sbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
 
1941
        gtk_box_pack_start (GTK_BOX (test_sound_box),
 
1942
                            sbox,
 
1943
                            FALSE, FALSE, 0);
 
1944
 
 
1945
        label = gtk_label_new (_("Test:"));
 
1946
        gtk_box_pack_start (GTK_BOX (sbox),
 
1947
                            label,
 
1948
                            FALSE, FALSE, 0);
 
1949
        if (self->priv->size_group != NULL)
 
1950
                gtk_size_group_add_widget (self->priv->size_group, sbox);
 
1951
 
 
1952
        self->priv->test_output_button = gtk_button_new_with_label ("Test Sound");
 
1953
        
 
1954
        /* FIXME: I am getting mental with all these hardcoded padding values,
 
1955
         * Here 8 works fine, not sure why. */
 
1956
        gtk_box_pack_start (GTK_BOX (test_sound_box),
 
1957
                            self->priv->test_output_button,
 
1958
                            TRUE, TRUE, 8);
 
1959
 
 
1960
        /* Is this needed */
 
1961
        if (self->priv->size_group != NULL)
 
1962
                gtk_size_group_add_widget (self->priv->size_group, self->priv->test_output_button);
 
1963
 
 
1964
        gtk_widget_show (test_sound_box);
 
1965
 
 
1966
        gtk_container_add (GTK_CONTAINER (box), self->priv->output_settings_box);
 
1967
        g_signal_connect (self->priv->test_output_button,
 
1968
                          "released",
 
1969
                           G_CALLBACK (on_test_speakers_clicked),
 
1970
                           self);
 
1971
        
 
1972
        /* Applications */
 
1973
        self->priv->applications_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
 
1974
        gtk_container_set_border_width (GTK_CONTAINER (self->priv->applications_box), 12);
 
1975
        label = gtk_label_new (_("Applications"));
 
1976
        gtk_notebook_append_page (GTK_NOTEBOOK (self->priv->notebook),
 
1977
                                  self->priv->applications_box,
 
1978
                                  label);
 
1979
        self->priv->no_apps_label = gtk_label_new (_("No application is currently playing or recording audio."));
 
1980
        gtk_box_pack_start (GTK_BOX (self->priv->applications_box),
 
1981
                            self->priv->no_apps_label,
 
1982
                            TRUE, TRUE, 0);
 
1983
 
 
1984
        self->priv->output_stream_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
 
1985
        alignment = gtk_alignment_new (0, 0, 1, 1);
 
1986
        gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 12, 0, 0, 0);
 
1987
        gtk_container_add (GTK_CONTAINER (alignment), self->priv->output_stream_box);
 
1988
        gtk_box_pack_start (GTK_BOX (main_vbox),
 
1989
                            alignment,
 
1990
                            FALSE, FALSE, 0);
 
1991
        // Output volume
 
1992
        self->priv->output_bar = create_bar (self, FALSE, TRUE);
 
1993
        gvc_channel_bar_set_name (GVC_CHANNEL_BAR (self->priv->output_bar),
 
1994
                                  _("_Output volume:"));
 
1995
        gtk_widget_set_sensitive (self->priv->output_bar, FALSE);
 
1996
        gtk_widget_set_size_request (self->priv->output_bar, 460, -1);        
 
1997
 
 
1998
        gtk_box_pack_start (GTK_BOX (self->priv->output_stream_box),
 
1999
                            self->priv->output_bar, TRUE, FALSE, 12);
 
2000
 
 
2001
        gtk_widget_show_all (main_vbox);
 
2002
 
 
2003
        g_signal_connect (self->priv->mixer_control,
 
2004
                          "stream-added",
 
2005
                          G_CALLBACK (on_control_stream_added),
 
2006
                          self);
 
2007
        g_signal_connect (self->priv->mixer_control,
 
2008
                          "stream-removed",
 
2009
                          G_CALLBACK (on_control_stream_removed),
 
2010
                          self);
 
2011
        g_signal_connect (self->priv->mixer_control,
 
2012
                          "output-added",
 
2013
                          G_CALLBACK (on_control_output_added),
 
2014
                          self);
 
2015
        g_signal_connect (self->priv->mixer_control,
 
2016
                          "output-removed",
 
2017
                          G_CALLBACK (on_control_output_removed),
 
2018
                          self);
 
2019
        /*g_signal_connect (self->priv->mixer_control,
 
2020
                          "active-output-update",
 
2021
                          G_CALLBACK (on_control_active_output_update),
 
2022
                          self);*/
 
2023
        g_signal_connect (self->priv->mixer_control,
 
2024
                          "input-added",
 
2025
                          G_CALLBACK (on_control_input_added),
 
2026
                          self);
 
2027
        g_signal_connect (self->priv->mixer_control,
 
2028
                          "input-removed",
 
2029
                          G_CALLBACK (on_control_input_removed),
 
2030
                          self);        
 
2031
        /*g_signal_connect (self->priv->mixer_control,
 
2032
                          "active-input-update",
 
2033
                          G_CALLBACK (on_control_active_input_update),
 
2034
                          self);*/
 
2035
 
 
2036
        //// The below code is redundant, for some reason no cards or sinks
 
2037
        //// are returned at this point. 
 
2038
        //GSList           *streams;
 
2039
        //GSList           *cards;
 
2040
        //GSList           *l;
 
2041
        
 
2042
        //streams = gvc_mixer_control_get_streams (self->priv->mixer_control);
 
2043
        //for (l = streams; l != NULL; l = l->next) {
 
2044
                //////stream = l->data;
 
2045
                ////add_stream (self, stream);
 
2046
        ////}
 
2047
        ////g_slist_free (streams);
 
2048
 
 
2049
        ////cards = gvc_mixer_control_get_cards (self->priv->mixer_control);
 
2050
 
 
2051
        ////for (l = cards; l != NULL; l = l->next) {
 
2052
                ////card = l->data;
 
2053
                ////add_card (self, card);
 
2054
                ////g_print ("about to add a card");
 
2055
        ////}
 
2056
        ////g_slist_free (cards);
 
2057
        
 
2058
        return object;
 
2059
}
 
2060
 
 
2061
static void
 
2062
gvc_mixer_dialog_dispose (GObject *object)
 
2063
{
 
2064
        GvcMixerDialog *dialog = GVC_MIXER_DIALOG (object);
 
2065
 
 
2066
        if (dialog->priv->mixer_control != NULL) {
 
2067
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
 
2068
                                                      on_control_output_added,
 
2069
                                                      dialog);
 
2070
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
 
2071
                                                      on_control_output_removed,
 
2072
                                                      dialog);
 
2073
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
 
2074
                                                      on_control_active_input_update,
 
2075
                                                      dialog);
 
2076
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
 
2077
                                                      on_control_active_output_update,
 
2078
                                                      dialog);                                            
 
2079
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
 
2080
                                                      on_control_input_added,
 
2081
                                                      dialog);
 
2082
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
 
2083
                                                      on_control_input_removed,
 
2084
                                                      dialog);
 
2085
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
 
2086
                                                      on_control_stream_added,
 
2087
                                                      dialog);
 
2088
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
 
2089
                                                      on_control_stream_removed,
 
2090
                                                      dialog);
 
2091
                g_object_unref (dialog->priv->mixer_control);
 
2092
                dialog->priv->mixer_control = NULL;
 
2093
        }
 
2094
 
 
2095
        if (dialog->priv->bars != NULL) {
 
2096
                g_hash_table_destroy (dialog->priv->bars);
 
2097
                dialog->priv->bars = NULL;
 
2098
        }
 
2099
 
 
2100
        G_OBJECT_CLASS (gvc_mixer_dialog_parent_class)->dispose (object);
 
2101
}
 
2102
 
 
2103
static void
 
2104
gvc_mixer_dialog_class_init (GvcMixerDialogClass *klass)
 
2105
{
 
2106
        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
 
2107
 
 
2108
        object_class->constructor = gvc_mixer_dialog_constructor;
 
2109
        object_class->dispose = gvc_mixer_dialog_dispose;
 
2110
        object_class->finalize = gvc_mixer_dialog_finalize;
 
2111
        object_class->set_property = gvc_mixer_dialog_set_property;
 
2112
        object_class->get_property = gvc_mixer_dialog_get_property;
 
2113
 
 
2114
        g_object_class_install_property (object_class,
 
2115
                                         PROP_MIXER_CONTROL,
 
2116
                                         g_param_spec_object ("mixer-control",
 
2117
                                                              "mixer control",
 
2118
                                                              "mixer control",
 
2119
                                                              GVC_TYPE_MIXER_CONTROL,
 
2120
                                                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
2121
 
 
2122
        g_type_class_add_private (klass, sizeof (GvcMixerDialogPrivate));
 
2123
}
 
2124
 
 
2125
 
 
2126
static void
 
2127
gvc_mixer_dialog_init (GvcMixerDialog *dialog)
 
2128
{
 
2129
        dialog->priv = GVC_MIXER_DIALOG_GET_PRIVATE (dialog);
 
2130
        dialog->priv->bars = g_hash_table_new (NULL, NULL);
 
2131
        dialog->priv->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
 
2132
}
 
2133
 
 
2134
static void
 
2135
gvc_mixer_dialog_finalize (GObject *object)
 
2136
{
 
2137
        GvcMixerDialog *mixer_dialog;
 
2138
 
 
2139
        g_return_if_fail (object != NULL);
 
2140
        g_return_if_fail (GVC_IS_MIXER_DIALOG (object));
 
2141
 
 
2142
        mixer_dialog = GVC_MIXER_DIALOG (object);
 
2143
 
 
2144
        g_return_if_fail (mixer_dialog->priv != NULL);
 
2145
        G_OBJECT_CLASS (gvc_mixer_dialog_parent_class)->finalize (object);
 
2146
}
 
2147
 
 
2148
GvcMixerDialog *
 
2149
gvc_mixer_dialog_new (GvcMixerControl *control)
 
2150
{
 
2151
        GObject *dialog;
 
2152
        dialog = g_object_new (GVC_TYPE_MIXER_DIALOG,
 
2153
                               "mixer-control", control,
 
2154
                               NULL);
 
2155
        return GVC_MIXER_DIALOG (dialog);
 
2156
}
 
2157
 
 
2158
enum {
 
2159
        PAGE_EVENTS,
 
2160
        PAGE_HARDWARE,
 
2161
        PAGE_INPUT,
 
2162
        PAGE_OUTPUT,
 
2163
        PAGE_APPLICATIONS
 
2164
};
 
2165
 
 
2166
gboolean
 
2167
gvc_mixer_dialog_set_page (GvcMixerDialog *self,
 
2168
                           const char     *page)
 
2169
{
 
2170
        guint num;
 
2171
 
 
2172
        g_return_val_if_fail (self != NULL, FALSE);
 
2173
 
 
2174
        if (page == NULL)
 
2175
                num = 0;
 
2176
        else if (g_str_equal (page, "effects"))
 
2177
                num = PAGE_EVENTS;
 
2178
        else if (g_str_equal (page, "input"))
 
2179
                num = PAGE_INPUT;
 
2180
        else if (g_str_equal (page, "output"))
 
2181
                num = PAGE_OUTPUT;
 
2182
        else if (g_str_equal (page, "applications"))
 
2183
                num = PAGE_APPLICATIONS;
 
2184
        else
 
2185
                num = 0;
 
2186
 
 
2187
        gtk_notebook_set_current_page (GTK_NOTEBOOK (self->priv->notebook), num);
 
2188
 
 
2189
        return TRUE;
 
2190
}