~ubuntu-branches/ubuntu/saucy/gnome-control-center/saucy-proposed

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Sebastien Bacher, Sebastien Bacher, Robert Ancell, Iain Lane, Edward Donovan, Rico Tzschichholz, Jeremy Bicha, David Henningsson
  • Date: 2012-11-21 19:32:45 UTC
  • mfrom: (1.1.63)
  • Revision ID: package-import@ubuntu.com-20121121193245-mj61nzz1z4fk3z25
Tags: 1:3.6.3-0ubuntu1
[ Sebastien Bacher ]
* New upstream version
* debian/control.in: recommends libcanberra-pulse (lp: #1004973)
* debian/patches/58_ubuntu_icon_views_redesign.patch:
  - drop most of the changes, keep the different grid size though
    to fit on screen with our extra icons
* debian/patches/91_dont_show_in_unity.patch:
  - dropped, show the upstream printer panel and the layout tab
* debian/patches/revert_git_keyboard_gsettings.patch,
  debian/patches/revert_git_stop_using_gconf.patch:
  - dropped the gconf->gsettings reverts

[ Robert Ancell ]
* New upstream release (LP: #1010317)
* debian/control:
  - Bump build-depends on libgnome-desktop-3-dev, libwacom-dev
  - Add build-depends on libclutter-1.0-dev, libclutter-gtk-1.0-dev,
    libpwquality-dev
  - Drop build-depends on libgnomekbd-dev
* debian/patches/60_ubuntu_nav_bar.patch:
  - Disabled for now, doesn't apply
* debian/patches/revert_ua_gsettings.patch:
  - We can use GSettings for universal access now
* debian/patches/00git_online_accounts_gtkgrid.patch:
* debian/patches/00git_online_accounts_layout.part:
* debian/patches/git_wacom_translations.patch:
  - Applied upstream

[ Iain Lane ]
* Add Build-Depends on libxkbfile-dev
* New upstream release.
* Refresh all patches to apply cleanly.

[ Edward Donovan ]
* debian/source_gnome-control-center.py: Fix for Python 3. (LP: #1013171)

[ Rico Tzschichholz ]
* debian/control.in:
  - Build-depend on gtk-doc-tools instead of docbook directly
  - Bump minimum glib-2.0, gnome-desktop3, gnome-settings-daemon
     and gsettings-desktop-schemas

[ Jeremy Bicha ]
* Dropped more patches applied in new version:
  - git_unmute_sound_event.patch
  - git_fix_big_editable_labels.patch
  - 96_sound_nua_panel.patch
* debian/patches/04_new_appearance_settings.patch:
  - Dropped, this is now packaged separately as gnome-control-center-unity
* debian/patches/10_keyboard_layout_on_unity.patch:
  - Don't change the keyboard panel name when not running Unity
* debian/patches/52_ubuntu_language_list_mods.patch:
  - Don't disable adding current language to the list. While this
    fix shows the current language twice, at least it avoids the
    "Ubuntu suddenly in Chinese" bug (LP: #1035219)
* debian/patches/53_use_ubuntu_help.patch:
  - Only show Ubuntu help when running Unity
* debian/patches/58_hide_gdm_notifications.patch:
  - Hide "Show notifications when locked" settings when running Unity
    since it's a GNOME Shell-specific feature
* debian/patches/63_normal_scrollbar_in_a11y.patch:
  - Drop, overlay-scrollbars should handle this instead
* debian/patches/91_dont_show_in_unity.patch:
  - Hide Printers & Region panels in Unity until we're ready to switch
    to them.
* debian/patches/fix-crash-on-user-panel.patch:
  - Dropped, GNOME says it's obsolete
* debian/rules:
  - Build with -z,defs again
  - Explicitly disable ibus support since ibus 1.4 isn't supported in
    this version
* debian/control.in:
  - Drop ubuntu-docs and gnome-user-guide from recommends to suggests
  - Don't recommend indicators; let's leave that to Unity

[ David Henningsson ]
* sound_nua_panel.patch: Rebase to gnome 3.6 

Show diffs side-by-side

added added

removed removed

Lines of Context:
52
52
struct GvcMixerDialogPrivate
53
53
{
54
54
        GvcMixerControl *mixer_control;
55
 
        GHashTable      *bars;
 
55
        GHashTable      *bars; /* Application and event bars only */
56
56
        GtkWidget       *notebook;
57
57
        GtkWidget       *output_bar;
58
58
        GtkWidget       *input_bar;
60
60
        GtkWidget       *effects_bar;
61
61
        GtkWidget       *output_stream_box;
62
62
        GtkWidget       *sound_effects_box;
63
 
        GtkWidget       *hw_box;
64
 
        GtkWidget       *hw_treeview;
65
 
        GtkWidget       *hw_settings_box;
66
 
        GtkWidget       *hw_profile_combo;
67
63
        GtkWidget       *input_box;
68
64
        GtkWidget       *output_box;
69
65
        GtkWidget       *applications_box;
73
69
        GtkWidget       *output_balance_bar;
74
70
        GtkWidget       *output_fade_bar;
75
71
        GtkWidget       *output_lfe_bar;
76
 
        GtkWidget       *output_port_combo;
 
72
        GtkWidget       *output_profile_combo;
77
73
        GtkWidget       *input_treeview;
78
 
        GtkWidget       *input_port_combo;
 
74
        GtkWidget       *input_profile_combo;
79
75
        GtkWidget       *input_settings_box;
80
76
        GtkWidget       *sound_theme_chooser;
81
77
        GtkWidget       *click_feedback_button;
122
118
 
123
119
static void     on_adjustment_value_changed (GtkAdjustment  *adjustment,
124
120
                                             GvcMixerDialog *dialog);
 
121
static void     on_control_active_output_update (GvcMixerControl *control,
 
122
                                                 guint            id,
 
123
                                                 GvcMixerDialog  *dialog);
 
124
 
 
125
static void     on_control_active_input_update (GvcMixerControl *control,
 
126
                                                guint            id,
 
127
                                                GvcMixerDialog  *dialog);
 
128
 
 
129
static void     on_test_speakers_clicked (GvcComboBox *widget,
 
130
                                          gpointer     user_data);
 
131
 
125
132
 
126
133
G_DEFINE_TYPE (GvcMixerDialog, gvc_mixer_dialog, GTK_TYPE_VBOX)
127
134
 
128
135
static void
129
 
update_default_input (GvcMixerDialog *dialog)
130
 
{
131
 
        GtkTreeModel *model;
132
 
        GtkTreeIter   iter;
133
 
        gboolean      ret;
134
 
 
135
 
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
136
 
        ret = gtk_tree_model_get_iter_first (model, &iter);
137
 
        if (ret == FALSE) {
138
 
                g_debug ("No default input selected or available");
139
 
                return;
140
 
        }
141
 
        do {
142
 
                gboolean        toggled;
143
 
                gboolean        is_default;
144
 
                guint           id;
145
 
                GvcMixerStream *stream;
146
 
 
147
 
                gtk_tree_model_get (model, &iter,
148
 
                                    ID_COLUMN, &id,
149
 
                                    ACTIVE_COLUMN, &toggled,
150
 
                                    -1);
151
 
 
152
 
                stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id);
153
 
                if (stream == NULL) {
154
 
                        g_warning ("Unable to find stream for id: %u", id);
155
 
                        continue;
156
 
                }
157
 
 
158
 
                is_default = FALSE;
159
 
                if (stream == gvc_mixer_control_get_default_source (dialog->priv->mixer_control)) {
160
 
                        is_default = TRUE;
161
 
                }
162
 
 
163
 
                gtk_list_store_set (GTK_LIST_STORE (model),
164
 
                                    &iter,
165
 
                                    ACTIVE_COLUMN, is_default,
166
 
                                    -1);
167
 
                if (is_default) {
168
 
                        GtkTreeSelection *selection;
169
 
 
170
 
                        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->input_treeview));
171
 
                        gtk_tree_selection_select_iter (selection, &iter);
172
 
                }
173
 
        } while (gtk_tree_model_iter_next (model, &iter));
174
 
}
175
 
 
176
 
static void
177
 
update_description (GvcMixerDialog *dialog,
178
 
                    guint column,
179
 
                    const char *value,
180
 
                    GvcMixerStream *stream)
181
 
{
182
 
        GtkTreeModel *model;
183
 
        GtkTreeIter   iter;
184
 
        guint         id;
185
 
 
186
 
        if (GVC_IS_MIXER_SOURCE (stream))
187
 
                model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
188
 
        else if (GVC_IS_MIXER_SINK (stream))
189
 
                model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
190
 
        else
191
 
                g_assert_not_reached ();
192
 
        gtk_tree_model_get_iter_first (model, &iter);
193
 
 
194
 
        id = gvc_mixer_stream_get_id (stream);
195
 
        do {
196
 
                guint       current_id;
197
 
 
198
 
                gtk_tree_model_get (model, &iter,
199
 
                                    ID_COLUMN, &current_id,
200
 
                                    -1);
201
 
                if (id != current_id)
202
 
                        continue;
203
 
 
204
 
                gtk_list_store_set (GTK_LIST_STORE (model),
205
 
                                    &iter,
206
 
                                    column, value,
207
 
                                    -1);
208
 
                break;
209
 
        } while (gtk_tree_model_iter_next (model, &iter));
210
 
}
211
 
 
212
 
static void
213
 
port_selection_changed (GvcComboBox *combo_box,
214
 
                        const char  *port,
215
 
                        GvcMixerDialog *dialog)
216
 
{
217
 
        GvcMixerStream *stream;
218
 
 
219
 
        stream = g_object_get_data (G_OBJECT (combo_box), "stream");
220
 
        if (stream == NULL) {
221
 
                g_warning ("Could not find stream for port combo box");
222
 
                return;
223
 
        }
224
 
        if (gvc_mixer_stream_change_port (stream, port) == FALSE) {
225
 
                g_warning ("Could not change port for stream");
226
 
        }
227
 
}
228
 
 
229
 
static void
230
 
update_output_settings (GvcMixerDialog *dialog)
 
136
profile_selection_changed (GvcComboBox    *combo_box,
 
137
                           const char     *profile,
 
138
                           GvcMixerDialog *dialog)
 
139
{
 
140
        GvcMixerUIDevice *output;
 
141
 
 
142
        g_debug ("profile_selection_changed() to %s", profile);
 
143
 
 
144
        output = g_object_get_data (G_OBJECT (combo_box), "uidevice");
 
145
 
 
146
        if (output == NULL) {
 
147
                g_warning ("Could not find Output for profile combo box");
 
148
                return;
 
149
        }
 
150
 
 
151
        g_debug ("on profile selection changed on output '%s' (origin: %s, id: %i)",
 
152
                gvc_mixer_ui_device_get_description (output),
 
153
                gvc_mixer_ui_device_get_origin (output),
 
154
                gvc_mixer_ui_device_get_id (output));
 
155
 
 
156
        if (gvc_mixer_control_change_profile_on_selected_device (dialog->priv->mixer_control, output, profile) == FALSE) {
 
157
                g_warning ("Could not change profile on device %s",
 
158
                           gvc_mixer_ui_device_get_description (output));
 
159
         }
 
160
}
 
161
 
 
162
static void
 
163
update_output_settings (GvcMixerDialog      *dialog,
 
164
                        GvcMixerUIDevice    *device)
231
165
{
232
166
        GvcMixerStream      *stream;
233
167
        const GvcChannelMap *map;
234
 
        const GList         *ports;
 
168
        const GList         *profiles;
235
169
        GtkAdjustment       *adj;
236
170
 
237
171
        g_debug ("Updating output settings");
250
184
                                      dialog->priv->output_lfe_bar);
251
185
                dialog->priv->output_lfe_bar = NULL;
252
186
        }
253
 
        if (dialog->priv->output_port_combo != NULL) {
 
187
        if (dialog->priv->output_profile_combo != NULL) {
254
188
                gtk_container_remove (GTK_CONTAINER (dialog->priv->output_settings_box),
255
 
                                      dialog->priv->output_port_combo);
256
 
                dialog->priv->output_port_combo = NULL;
 
189
                                      dialog->priv->output_profile_combo);
 
190
                dialog->priv->output_profile_combo = NULL;
257
191
        }
258
192
 
259
 
        stream = gvc_mixer_control_get_default_sink (dialog->priv->mixer_control);
 
193
        stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control,
 
194
                                                           device);
260
195
        if (stream == NULL) {
261
196
                g_warning ("Default sink stream not found");
262
197
                return;
316
251
                gtk_widget_show (dialog->priv->output_lfe_bar);
317
252
        }
318
253
 
319
 
        ports = gvc_mixer_stream_get_ports (stream);
320
 
        if (ports != NULL) {
321
 
                const GvcMixerStreamPort *port;
322
 
                port = gvc_mixer_stream_get_port (stream);
323
 
 
324
 
                dialog->priv->output_port_combo = gvc_combo_box_new (_("Co_nnector:"));
325
 
                gvc_combo_box_set_ports (GVC_COMBO_BOX (dialog->priv->output_port_combo),
326
 
                                         ports);
327
 
                gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->output_port_combo), port->port);
328
 
                g_object_set_data (G_OBJECT (dialog->priv->output_port_combo), "stream", stream);
329
 
                g_signal_connect (G_OBJECT (dialog->priv->output_port_combo), "changed",
330
 
                                  G_CALLBACK (port_selection_changed), dialog);
331
 
 
 
254
        profiles = gvc_mixer_ui_device_get_profiles (device);
 
255
        /* FIXME: How do we make sure the "Test speakers" button is shown
 
256
         * even when there are no profiles to choose between? */
 
257
        if (TRUE /*g_list_length((GList *) profiles) >= 2 */) {
 
258
                const gchar *active_profile;
 
259
 
 
260
                dialog->priv->output_profile_combo = gvc_combo_box_new (_("_Profile:"));
 
261
 
 
262
                g_object_set (G_OBJECT (dialog->priv->output_profile_combo), "button-label", _("_Test Speakers"), NULL);
 
263
                g_object_set (G_OBJECT (dialog->priv->output_profile_combo),
 
264
                              "show-button", TRUE, NULL);
 
265
                g_signal_connect (G_OBJECT (dialog->priv->output_profile_combo), "button-clicked",
 
266
                                  G_CALLBACK (on_test_speakers_clicked), dialog);
 
267
 
 
268
                if (profiles)
 
269
                        gvc_combo_box_set_profiles (GVC_COMBO_BOX (dialog->priv->output_profile_combo),
 
270
                                                    profiles);
332
271
                gtk_box_pack_start (GTK_BOX (dialog->priv->output_settings_box),
333
 
                                    dialog->priv->output_port_combo,
 
272
                                    dialog->priv->output_profile_combo,
334
273
                                    TRUE, FALSE, 6);
335
274
 
336
275
                if (dialog->priv->size_group != NULL) {
337
 
                        gvc_combo_box_set_size_group (GVC_COMBO_BOX (dialog->priv->output_port_combo),
 
276
                        gvc_combo_box_set_size_group (GVC_COMBO_BOX (dialog->priv->output_profile_combo),
338
277
                                                      dialog->priv->size_group, FALSE);
339
278
                }
340
279
 
341
 
                gtk_widget_show (dialog->priv->output_port_combo);
 
280
                active_profile = gvc_mixer_ui_device_get_active_profile (device);
 
281
                if (active_profile)
 
282
                        gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->output_profile_combo), active_profile);
 
283
 
 
284
                g_object_set_data (G_OBJECT (dialog->priv->output_profile_combo),
 
285
                                   "uidevice",
 
286
                                   device);
 
287
                if (g_list_length((GList *) profiles))
 
288
                        g_signal_connect (G_OBJECT (dialog->priv->output_profile_combo), "changed",
 
289
                                          G_CALLBACK (profile_selection_changed), dialog);
 
290
 
 
291
                gtk_widget_show (dialog->priv->output_profile_combo);
342
292
        }
343
293
 
344
294
        /* FIXME: We could make this into a "No settings" label instead */
345
295
        gtk_widget_set_sensitive (dialog->priv->output_balance_bar, gvc_channel_map_can_balance (map));
346
296
}
347
297
 
348
 
static void
349
 
update_default_output (GvcMixerDialog *dialog)
350
 
{
351
 
        GtkTreeModel *model;
352
 
        GtkTreeIter   iter;
353
 
 
354
 
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
355
 
        gtk_tree_model_get_iter_first (model, &iter);
356
 
        do {
357
 
                gboolean        toggled;
358
 
                gboolean        is_default;
359
 
                guint           id;
360
 
                GvcMixerStream *stream;
361
 
 
362
 
                gtk_tree_model_get (model, &iter,
363
 
                                    ID_COLUMN, &id,
364
 
                                    ACTIVE_COLUMN, &toggled,
365
 
                                    -1);
366
 
 
367
 
                stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id);
368
 
                if (stream == NULL) {
369
 
                        g_warning ("Unable to find stream for id: %u", id);
370
 
                        continue;
371
 
                }
372
 
 
373
 
                is_default = FALSE;
374
 
                if (stream == gvc_mixer_control_get_default_sink (dialog->priv->mixer_control)) {
375
 
                        is_default = TRUE;
376
 
                }
377
 
 
378
 
                gtk_list_store_set (GTK_LIST_STORE (model),
379
 
                                    &iter,
380
 
                                    ACTIVE_COLUMN, is_default,
381
 
                                    -1);
382
 
                if (is_default) {
383
 
                        GtkTreeSelection *selection;
384
 
 
385
 
                        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->output_treeview));
386
 
                        gtk_tree_selection_select_iter (selection, &iter);
387
 
                }
388
 
        } while (gtk_tree_model_iter_next (model, &iter));
389
 
}
390
 
 
391
 
static void
392
 
on_mixer_control_default_sink_changed (GvcMixerControl *control,
393
 
                                       guint            id,
394
 
                                       GvcMixerDialog  *dialog)
395
 
{
396
 
        GvcMixerStream *stream;
397
 
 
398
 
        g_debug ("GvcMixerDialog: default sink changed: %u", id);
399
 
 
400
 
        if (id == PA_INVALID_INDEX)
401
 
                stream = NULL;
402
 
        else
403
 
                stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control,
404
 
                                                             id);
405
 
        bar_set_stream (dialog, dialog->priv->output_bar, stream);
406
 
 
407
 
        update_output_settings (dialog);
408
 
 
409
 
        update_default_output (dialog);
410
 
}
411
 
 
412
 
 
413
298
#define DECAY_STEP .15
414
299
 
415
300
static void
594
479
}
595
480
 
596
481
static void
597
 
update_input_settings (GvcMixerDialog *dialog)
 
482
update_input_settings (GvcMixerDialog   *dialog,
 
483
                       GvcMixerUIDevice *device)
598
484
{
599
 
        const GList    *ports;
600
485
        GvcMixerStream *stream;
 
486
        const GList    *profiles;
601
487
        GtkAdjustment  *adj;
602
488
 
603
489
        g_debug ("Updating input settings");
604
490
 
605
491
        stop_monitor_stream_for_source (dialog);
606
492
 
607
 
        if (dialog->priv->input_port_combo != NULL) {
 
493
        if (dialog->priv->input_profile_combo != NULL) {
608
494
                gtk_container_remove (GTK_CONTAINER (dialog->priv->input_settings_box),
609
 
                                      dialog->priv->input_port_combo);
610
 
                dialog->priv->input_port_combo = NULL;
 
495
                                      dialog->priv->input_profile_combo);
 
496
                dialog->priv->input_profile_combo = NULL;
611
497
        }
612
498
 
613
 
        stream = gvc_mixer_control_get_default_source (dialog->priv->mixer_control);
 
499
        stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control,
 
500
                                                           device);
614
501
        if (stream == NULL) {
615
502
                g_debug ("Default source stream not found");
616
503
                return;
627
514
        gtk_adjustment_set_value (adj,
628
515
                                  gvc_mixer_stream_get_volume (stream));
629
516
 
630
 
        ports = gvc_mixer_stream_get_ports (stream);
631
 
        if (ports != NULL) {
632
 
                const GvcMixerStreamPort *port;
633
 
                port = gvc_mixer_stream_get_port (stream);
634
 
 
635
 
                dialog->priv->input_port_combo = gvc_combo_box_new (_("Co_nnector:"));
636
 
                gvc_combo_box_set_ports (GVC_COMBO_BOX (dialog->priv->input_port_combo),
637
 
                                         ports);
638
 
                gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->input_port_combo), port->port);
639
 
                g_object_set_data (G_OBJECT (dialog->priv->input_port_combo), "stream", stream);
640
 
                g_signal_connect (G_OBJECT (dialog->priv->input_port_combo), "changed",
641
 
                                  G_CALLBACK (port_selection_changed), dialog);
642
 
 
643
 
                if (dialog->priv->size_group != NULL) {
644
 
                        gvc_combo_box_set_size_group (GVC_COMBO_BOX (dialog->priv->input_port_combo),
645
 
                                                      dialog->priv->size_group, FALSE);
646
 
                }
 
517
        profiles = gvc_mixer_ui_device_get_profiles (device);
 
518
        if (g_list_length ((GList *) profiles) >= 2) {
 
519
                const gchar *active_profile;
 
520
 
 
521
                dialog->priv->input_profile_combo = gvc_combo_box_new (_("_Profile:"));
 
522
                gvc_combo_box_set_profiles (GVC_COMBO_BOX (dialog->priv->input_profile_combo),
 
523
                                            profiles);
 
524
 
647
525
                gtk_box_pack_start (GTK_BOX (dialog->priv->input_settings_box),
648
 
                                    dialog->priv->input_port_combo,
 
526
                                    dialog->priv->input_profile_combo,
649
527
                                    TRUE, TRUE, 0);
650
 
                gtk_widget_show (dialog->priv->input_port_combo);
 
528
 
 
529
                if (dialog->priv->size_group != NULL) {
 
530
                        gvc_combo_box_set_size_group (GVC_COMBO_BOX (dialog->priv->input_profile_combo),
 
531
                                                      dialog->priv->size_group, FALSE);
 
532
                }
 
533
 
 
534
                active_profile = gvc_mixer_ui_device_get_active_profile (device);
 
535
                if (active_profile)
 
536
                        gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->input_profile_combo), active_profile);
 
537
 
 
538
                g_object_set_data (G_OBJECT (dialog->priv->input_profile_combo),
 
539
                                   "uidevice",
 
540
                                   device);
 
541
                g_signal_connect (G_OBJECT (dialog->priv->input_profile_combo), "changed",
 
542
                                  G_CALLBACK (profile_selection_changed), dialog);
 
543
 
 
544
                gtk_widget_show (dialog->priv->input_profile_combo);
651
545
        }
652
546
 
653
547
        create_monitor_stream_for_source (dialog, stream);
654
548
}
655
549
 
656
550
static void
657
 
on_mixer_control_default_source_changed (GvcMixerControl *control,
658
 
                                         guint            id,
659
 
                                         GvcMixerDialog  *dialog)
660
 
{
661
 
        GvcMixerStream *stream;
662
 
        GtkAdjustment *adj;
663
 
 
664
 
        g_debug ("GvcMixerDialog: default source changed: %u", id);
665
 
 
666
 
        if (id == PA_INVALID_INDEX)
667
 
                stream = NULL;
668
 
        else
669
 
                stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id);
670
 
 
671
 
        /* Disconnect the adj, otherwise it might change if is_amplified changes */
672
 
        adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (dialog->priv->input_bar)));
673
 
        g_signal_handlers_disconnect_by_func(adj, on_adjustment_value_changed, dialog);
674
 
 
675
 
        bar_set_stream (dialog, dialog->priv->input_bar, stream);
676
 
        update_input_settings (dialog);
677
 
 
678
 
        g_signal_connect (adj,
679
 
                          "value-changed",
680
 
                          G_CALLBACK (on_adjustment_value_changed),
681
 
                          dialog);
682
 
 
683
 
        update_default_input (dialog);
684
 
}
685
 
 
686
 
static void
687
551
gvc_mixer_dialog_set_mixer_control (GvcMixerDialog  *dialog,
688
552
                                    GvcMixerControl *control)
689
553
{
694
558
 
695
559
        if (dialog->priv->mixer_control != NULL) {
696
560
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
697
 
                                                      G_CALLBACK (on_mixer_control_default_sink_changed),
 
561
                                                      G_CALLBACK (on_control_active_input_update),
698
562
                                                      dialog);
699
563
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
700
 
                                                      G_CALLBACK (on_mixer_control_default_source_changed),
 
564
                                                      G_CALLBACK (on_control_active_output_update),
701
565
                                                      dialog);
702
566
                g_object_unref (dialog->priv->mixer_control);
703
567
        }
704
568
 
705
569
        dialog->priv->mixer_control = control;
706
570
 
 
571
        /* FIXME: Why are some mixer_control signals connected here,
 
572
         * and others in the dialog constructor? (And similar for disconnect) */
707
573
        g_signal_connect (dialog->priv->mixer_control,
708
 
                          "default-sink-changed",
709
 
                          G_CALLBACK (on_mixer_control_default_sink_changed),
 
574
                          "active-input-update",
 
575
                          G_CALLBACK (on_control_active_input_update),
710
576
                          dialog);
711
577
        g_signal_connect (dialog->priv->mixer_control,
712
 
                          "default-source-changed",
713
 
                          G_CALLBACK (on_mixer_control_default_source_changed),
 
578
                          "active-output-update",
 
579
                          G_CALLBACK (on_control_active_output_update),
714
580
                          dialog);
715
581
 
716
582
        g_object_notify (G_OBJECT (dialog), "mixer-control");
785
651
                if (volume == 0.0)
786
652
                        gvc_mixer_stream_set_is_muted (stream, TRUE);
787
653
                /* Only push the volume if it's actually changed */
788
 
                if (gvc_mixer_stream_set_volume(stream, (pa_volume_t) rounded) != FALSE)
 
654
                if (gvc_mixer_stream_set_volume (stream, (pa_volume_t) rounded) != FALSE)
789
655
                        gvc_mixer_stream_push_volume (stream);
790
656
        }
791
657
}
822
688
        return bar;
823
689
}
824
690
 
825
 
static GtkWidget *
826
 
lookup_combo_box_for_stream (GvcMixerDialog *dialog,
827
 
                             GvcMixerStream *stream)
828
 
{
829
 
        GvcMixerStream *combo_stream;
830
 
        guint id;
831
 
 
832
 
        id = gvc_mixer_stream_get_id (stream);
833
 
 
834
 
        if (dialog->priv->output_port_combo != NULL) {
835
 
                combo_stream = g_object_get_data (G_OBJECT (dialog->priv->output_port_combo),
836
 
                                                  "stream");
837
 
                if (combo_stream != NULL) {
838
 
                        if (id == gvc_mixer_stream_get_id (combo_stream))
839
 
                                return dialog->priv->output_port_combo;
840
 
                }
841
 
        }
842
 
 
843
 
        if (dialog->priv->input_port_combo != NULL) {
844
 
                combo_stream = g_object_get_data (G_OBJECT (dialog->priv->input_port_combo),
845
 
                                                  "stream");
846
 
                if (combo_stream != NULL) {
847
 
                        if (id == gvc_mixer_stream_get_id (combo_stream))
848
 
                                return dialog->priv->input_port_combo;
849
 
                }
850
 
        }
851
 
 
852
 
        return NULL;
853
 
}
854
 
 
855
 
static void
856
 
on_stream_description_notify (GvcMixerStream *stream,
857
 
                              GParamSpec     *pspec,
858
 
                              GvcMixerDialog *dialog)
859
 
{
860
 
        update_description (dialog, NAME_COLUMN,
861
 
                            gvc_mixer_stream_get_description (stream),
862
 
                            stream);
863
 
}
864
 
 
865
 
static void
866
 
on_stream_port_notify (GObject        *object,
867
 
                       GParamSpec     *pspec,
868
 
                       GvcMixerDialog *dialog)
869
 
{
870
 
        GvcComboBox *combo_box;
871
 
        char *port;
872
 
 
873
 
        combo_box = GVC_COMBO_BOX (lookup_combo_box_for_stream (dialog, GVC_MIXER_STREAM (object)));
874
 
        if (combo_box == NULL)
875
 
                return;
876
 
 
877
 
        g_signal_handlers_block_by_func (G_OBJECT (combo_box),
878
 
                                         port_selection_changed,
879
 
                                         dialog);
880
 
 
881
 
        g_object_get (object, "port", &port, NULL);
882
 
        gvc_combo_box_set_active (GVC_COMBO_BOX (combo_box), port);
883
 
 
884
 
        g_signal_handlers_unblock_by_func (G_OBJECT (combo_box),
885
 
                                         port_selection_changed,
886
 
                                         dialog);
887
 
}
888
 
 
889
691
static void
890
692
on_stream_volume_notify (GObject        *object,
891
693
                         GParamSpec     *pspec,
1008
810
        return bar;
1009
811
}
1010
812
 
 
813
/* active_input_update
 
814
 * Handle input update change from the backend (control).
 
815
 * Trust the backend whole-heartedly to deliver the correct input. */
 
816
static void
 
817
active_input_update (GvcMixerDialog *dialog,
 
818
                     GvcMixerUIDevice *active_input)
 
819
{
 
820
        /* First make sure the correct UI device is selected. */
 
821
        GtkTreeModel   *model;
 
822
        GtkTreeIter     iter;
 
823
        GvcMixerStream *stream;
 
824
 
 
825
        g_debug ("active_input_update device id = %i",
 
826
                 gvc_mixer_ui_device_get_id (active_input));
 
827
 
 
828
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
 
829
 
 
830
        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
 
831
                g_warning ("No devices in the tree, so cannot set the active output");
 
832
                return;
 
833
        }
 
834
 
 
835
        do {
 
836
                gboolean         is_selected = FALSE;
 
837
                gint             id;
 
838
 
 
839
                gtk_tree_model_get (model, &iter,
 
840
                                    ID_COLUMN, &id,
 
841
                                    -1);
 
842
 
 
843
                is_selected = id == gvc_mixer_ui_device_get_id (active_input);
 
844
 
 
845
                gtk_list_store_set (GTK_LIST_STORE (model),
 
846
                                    &iter,
 
847
                                    ACTIVE_COLUMN, is_selected,
 
848
                                    -1);
 
849
 
 
850
                if (is_selected) {
 
851
                        GtkTreeSelection *selection;
 
852
                        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->input_treeview));
 
853
                        gtk_tree_selection_select_iter (selection, &iter);
 
854
                }
 
855
        } while (gtk_tree_model_iter_next (model, &iter));
 
856
 
 
857
        stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control,
 
858
                                                           active_input);
 
859
        if (stream == NULL) {
 
860
                g_warning ("Couldn't find a stream from the active input");
 
861
                gtk_widget_set_sensitive (dialog->priv->input_bar, FALSE);
 
862
                return;
 
863
        }
 
864
 
 
865
        bar_set_stream (dialog, dialog->priv->input_bar, stream);
 
866
        update_input_settings (dialog, active_input);
 
867
 
 
868
}
 
869
 
 
870
/* active_output_update
 
871
 * Handle output update change from the backend (control).
 
872
 * Trust the backend whole heartedly to deliver the correct output. */
 
873
static void
 
874
active_output_update (GvcMixerDialog   *dialog,
 
875
                      GvcMixerUIDevice *active_output)
 
876
{
 
877
        /* First make sure the correct UI device is selected. */
 
878
        GvcMixerStream *stream;
 
879
        GtkTreeModel   *model;
 
880
        GtkTreeIter     iter;
 
881
 
 
882
        g_debug ("active output update device id = %i",
 
883
                 gvc_mixer_ui_device_get_id (active_output));
 
884
 
 
885
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
 
886
 
 
887
        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE){
 
888
                g_warning ("No devices in the tree, so cannot set the active output");
 
889
                return;
 
890
        }
 
891
 
 
892
        do {
 
893
                gboolean         is_selected;
 
894
                gint             id;
 
895
 
 
896
                gtk_tree_model_get (model, &iter,
 
897
                                    ID_COLUMN, &id,
 
898
                                    ACTIVE_COLUMN, &is_selected,
 
899
                                    -1);
 
900
 
 
901
                if (is_selected && id == gvc_mixer_ui_device_get_id (active_output)) {
 
902
                        /* XXX: profile change on the same device? */
 
903
                        g_debug ("Unneccessary active output update");
 
904
                }
 
905
 
 
906
                is_selected = id == gvc_mixer_ui_device_get_id (active_output);
 
907
 
 
908
                gtk_list_store_set (GTK_LIST_STORE (model),
 
909
                                    &iter,
 
910
                                    ACTIVE_COLUMN, is_selected,
 
911
                                    -1);
 
912
 
 
913
                if (is_selected) {
 
914
                        GtkTreeSelection *selection;
 
915
                        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->output_treeview));
 
916
                        gtk_tree_selection_select_iter (selection, &iter);
 
917
                }
 
918
        } while (gtk_tree_model_iter_next (model, &iter));
 
919
 
 
920
        stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control,
 
921
                                                           active_output);
 
922
        if (stream == NULL) {
 
923
                g_warning ("Couldn't find a stream from the active output");
 
924
                return;
 
925
        }
 
926
 
 
927
        bar_set_stream (dialog, dialog->priv->output_bar, stream);
 
928
        update_output_settings (dialog, active_output);
 
929
}
 
930
 
1011
931
static void
1012
932
bar_set_stream (GvcMixerDialog *dialog,
1013
933
                GtkWidget      *bar,
1029
949
 
1030
950
                g_signal_handlers_disconnect_by_func (old_stream, on_stream_is_muted_notify, dialog);
1031
951
                g_signal_handlers_disconnect_by_func (old_stream, on_stream_volume_notify, dialog);
1032
 
                g_signal_handlers_disconnect_by_func (old_stream, on_stream_port_notify, dialog);
1033
952
                g_hash_table_remove (dialog->priv->bars, GUINT_TO_POINTER (gvc_mixer_stream_get_id (old_stream)));
1034
953
        }
1035
954
 
1040
959
        g_signal_handlers_disconnect_by_func (adj, on_adjustment_value_changed, dialog);
1041
960
 
1042
961
        g_object_set_data (G_OBJECT (bar), "gvc-mixer-dialog-stream", stream);
 
962
        g_object_set_data (G_OBJECT (bar), "gvc-mixer-dialog-stream-id",
 
963
                           GUINT_TO_POINTER (gvc_mixer_stream_get_id (stream)));
1043
964
        g_object_set_data (G_OBJECT (adj), "gvc-mixer-dialog-stream", stream);
1044
965
        g_object_set_data (G_OBJECT (adj), "gvc-mixer-dialog-bar", bar);
1045
966
 
1049
970
                is_muted = gvc_mixer_stream_get_is_muted (stream);
1050
971
                gvc_channel_bar_set_is_muted (GVC_CHANNEL_BAR (bar), is_muted);
1051
972
 
1052
 
                save_bar_for_stream (dialog, stream, bar);
1053
 
 
1054
973
                gtk_adjustment_set_value (adj,
1055
974
                                          gvc_mixer_stream_get_volume (stream));
1056
975
 
1062
981
                                  "notify::volume",
1063
982
                                  G_CALLBACK (on_stream_volume_notify),
1064
983
                                  dialog);
1065
 
                g_signal_connect (stream,
1066
 
                                  "notify::port",
1067
 
                                  G_CALLBACK (on_stream_port_notify),
1068
 
                                  dialog);
1069
984
                g_signal_connect (adj,
1070
985
                                  "value-changed",
1071
986
                                  G_CALLBACK (on_adjustment_value_changed),
1077
992
add_stream (GvcMixerDialog *dialog,
1078
993
            GvcMixerStream *stream)
1079
994
{
1080
 
        GtkWidget     *bar;
1081
 
        gboolean       is_muted;
1082
 
        gboolean       is_default;
1083
 
        GtkAdjustment *adj;
1084
 
        const char    *id;
1085
 
 
1086
 
        g_assert (stream != NULL);
1087
 
 
1088
 
        if (gvc_mixer_stream_is_event_stream (stream) != FALSE)
1089
 
                return;
 
995
        GtkWidget      *bar;
 
996
        GvcMixerStream *old_stream;
1090
997
 
1091
998
        bar = NULL;
1092
 
        is_default = FALSE;
1093
 
        id = gvc_mixer_stream_get_application_id (stream);
1094
999
 
1095
 
        if (stream == gvc_mixer_control_get_default_sink (dialog->priv->mixer_control)) {
1096
 
                bar = dialog->priv->output_bar;
1097
 
                is_muted = gvc_mixer_stream_get_is_muted (stream);
1098
 
                is_default = TRUE;
1099
 
                gtk_widget_set_sensitive (dialog->priv->applications_box,
1100
 
                                          !is_muted);
1101
 
                adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (bar)));
1102
 
                g_signal_handlers_disconnect_by_func(adj, on_adjustment_value_changed, dialog);
1103
 
                update_output_settings (dialog);
1104
 
        } else if (stream == gvc_mixer_control_get_default_source (dialog->priv->mixer_control)) {
1105
 
                bar = dialog->priv->input_bar;
1106
 
                adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (bar)));
1107
 
                g_signal_handlers_disconnect_by_func(adj, on_adjustment_value_changed, dialog);
1108
 
                update_input_settings (dialog);
1109
 
                is_default = TRUE;
1110
 
        } else if (stream == gvc_mixer_control_get_event_sink_input (dialog->priv->mixer_control)) {
 
1000
        if (GVC_IS_MIXER_SOURCE (stream) || GVC_IS_MIXER_SINK (stream))
 
1001
                return;
 
1002
        else if (stream == gvc_mixer_control_get_event_sink_input (dialog->priv->mixer_control)) {
1111
1003
                bar = dialog->priv->effects_bar;
1112
1004
                g_debug ("Adding effects stream");
1113
 
        } else if (! GVC_IS_MIXER_SOURCE (stream)
1114
 
                   && !GVC_IS_MIXER_SINK (stream)
1115
 
                   && !gvc_mixer_stream_is_virtual (stream)
1116
 
                   && g_strcmp0 (id, "org.gnome.VolumeControl") != 0
1117
 
                   && g_strcmp0 (id, "org.PulseAudio.pavucontrol") != 0) {
 
1005
        } else {
 
1006
                /* Must be an application stream */
1118
1007
                const char *name;
1119
 
 
1120
1008
                name = gvc_mixer_stream_get_name (stream);
 
1009
                g_debug ("Add bar for application stream : %s", name);
 
1010
 
1121
1011
                bar = create_app_bar (dialog, name,
1122
1012
                                      gvc_mixer_stream_get_icon_name (stream));
1123
 
 
1124
1013
                gtk_box_pack_start (GTK_BOX (dialog->priv->applications_box), bar, FALSE, FALSE, 12);
1125
1014
                dialog->priv->num_apps++;
1126
1015
                gtk_widget_hide (dialog->priv->no_apps_label);
1127
1016
        }
1128
1017
 
1129
 
        if (GVC_IS_MIXER_SOURCE (stream)) {
1130
 
                GtkTreeModel *model;
1131
 
                GtkTreeIter   iter;
1132
 
                GIcon        *icon;
1133
 
 
1134
 
                model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
1135
 
                gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1136
 
 
1137
 
                icon = gvc_mixer_stream_get_gicon (stream);
1138
 
                gtk_list_store_set (GTK_LIST_STORE (model),
1139
 
                                    &iter,
1140
 
                                    NAME_COLUMN, gvc_mixer_stream_get_description (stream),
1141
 
                                    DEVICE_COLUMN, "",
1142
 
                                    ACTIVE_COLUMN, is_default,
1143
 
                                    ICON_COLUMN, icon,
1144
 
                                    ID_COLUMN, gvc_mixer_stream_get_id (stream),
1145
 
                                    -1);
1146
 
                if (icon != NULL)
1147
 
                        g_object_unref (icon);
1148
 
 
1149
 
                if (is_default) {
1150
 
                        GtkTreeSelection *selection;
1151
 
 
1152
 
                        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->input_treeview));
1153
 
                        gtk_tree_selection_select_iter (selection, &iter);
1154
 
                }
1155
 
 
1156
 
                g_signal_connect (stream,
1157
 
                                  "notify::description",
1158
 
                                  G_CALLBACK (on_stream_description_notify),
1159
 
                                  dialog);
1160
 
        } else if (GVC_IS_MIXER_SINK (stream)) {
1161
 
                GtkTreeModel        *model;
1162
 
                GtkTreeIter          iter;
1163
 
                GIcon               *icon;
1164
 
 
1165
 
                model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
1166
 
                gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1167
 
 
1168
 
                icon = gvc_mixer_stream_get_gicon (stream);
1169
 
                gtk_list_store_set (GTK_LIST_STORE (model),
1170
 
                                    &iter,
1171
 
                                    NAME_COLUMN, gvc_mixer_stream_get_description (stream),
1172
 
                                    DEVICE_COLUMN, "",
1173
 
                                    ACTIVE_COLUMN, is_default,
1174
 
                                    ICON_COLUMN, icon,
1175
 
                                    ID_COLUMN, gvc_mixer_stream_get_id (stream),
1176
 
                                    -1);
1177
 
                if (icon != NULL)
1178
 
                        g_object_unref (icon);
1179
 
 
1180
 
                if (is_default) {
1181
 
                        GtkTreeSelection *selection;
1182
 
 
1183
 
                        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->output_treeview));
1184
 
                        gtk_tree_selection_select_iter (selection, &iter);
1185
 
                }
1186
 
 
1187
 
                g_signal_connect (stream,
1188
 
                                  "notify::description",
1189
 
                                  G_CALLBACK (on_stream_description_notify),
1190
 
                                  dialog);
1191
 
        }
 
1018
        /* We should have a bar by now. */
 
1019
        g_assert (bar != NULL);
1192
1020
 
1193
1021
        if (bar != NULL) {
 
1022
                old_stream = g_object_get_data (G_OBJECT (bar), "gvc-mixer-dialog-stream");
 
1023
                if (old_stream != NULL) {
 
1024
                        char *name;
 
1025
 
 
1026
                        g_object_get (bar, "name", &name, NULL);
 
1027
                        g_debug ("Disconnecting old stream '%s' from bar '%s'",
 
1028
                                 gvc_mixer_stream_get_name (old_stream), name);
 
1029
                        g_free (name);
 
1030
 
 
1031
                        g_signal_handlers_disconnect_by_func (old_stream, on_stream_is_muted_notify, dialog);
 
1032
                        g_signal_handlers_disconnect_by_func (old_stream, on_stream_volume_notify, dialog);
 
1033
                        g_hash_table_remove (dialog->priv->bars, GUINT_TO_POINTER (gvc_mixer_stream_get_id (old_stream)));
 
1034
                }
 
1035
                save_bar_for_stream (dialog, stream, bar);
1194
1036
                bar_set_stream (dialog, bar, stream);
1195
1037
                gtk_widget_show (bar);
1196
1038
        }
1202
1044
                         GvcMixerDialog  *dialog)
1203
1045
{
1204
1046
        GvcMixerStream *stream;
1205
 
        GtkWidget      *bar;
1206
 
 
1207
 
        bar = g_hash_table_lookup (dialog->priv->bars, GUINT_TO_POINTER (id));
1208
 
        if (bar != NULL) {
1209
 
                g_debug ("GvcMixerDialog: Stream %u already added", id);
1210
 
                return;
1211
 
        }
 
1047
        const char     *app_id;
1212
1048
 
1213
1049
        stream = gvc_mixer_control_lookup_stream_id (control, id);
1214
 
        if (stream != NULL) {
 
1050
        if (stream == NULL)
 
1051
                return;
 
1052
 
 
1053
        app_id = gvc_mixer_stream_get_application_id (stream);
 
1054
 
 
1055
        if (stream == gvc_mixer_control_get_event_sink_input (dialog->priv->mixer_control) ||
 
1056
            (GVC_IS_MIXER_SOURCE (stream) == FALSE &&
 
1057
             GVC_IS_MIXER_SINK (stream) == FALSE &&
 
1058
             gvc_mixer_stream_is_virtual (stream) == FALSE &&
 
1059
             g_strcmp0 (app_id, "org.gnome.VolumeControl") != 0 &&
 
1060
             g_strcmp0 (app_id, "org.PulseAudio.pavucontrol") != 0)) {
 
1061
                GtkWidget      *bar;
 
1062
 
 
1063
                bar = g_hash_table_lookup (dialog->priv->bars, GUINT_TO_POINTER (id));
 
1064
                if (bar != NULL) {
 
1065
                        g_debug ("GvcMixerDialog: Stream %u already added", id);
 
1066
                        return;
 
1067
                }
1215
1068
                add_stream (dialog, stream);
1216
1069
        }
1217
1070
}
1245
1098
}
1246
1099
 
1247
1100
static void
 
1101
add_input_ui_entry (GvcMixerDialog *dialog,
 
1102
                    GvcMixerUIDevice *input)
 
1103
{
 
1104
        gchar               *final_name;
 
1105
        gchar               *port_name;
 
1106
        gchar               *origin;
 
1107
        gchar               *description;
 
1108
        gboolean             available;
 
1109
        gint                 stream_id;
 
1110
        GtkTreeModel        *model;
 
1111
        GtkTreeIter          iter;
 
1112
        GIcon               *icon;
 
1113
        GvcMixerCard        *card;
 
1114
 
 
1115
        g_debug ("Add input ui entry with id :%u",
 
1116
                  gvc_mixer_ui_device_get_id (input));
 
1117
 
 
1118
        g_object_get (G_OBJECT (input),
 
1119
                     "stream-id", &stream_id,
 
1120
                     "card", &card,
 
1121
                     "origin", &origin,
 
1122
                     "description", &description,
 
1123
                     "port-name", &port_name,
 
1124
                     "port-available", &available,
 
1125
                      NULL);
 
1126
 
 
1127
        if (origin && origin[0] != '\0')
 
1128
                final_name = g_strdup_printf ("%s - %s", description, origin);
 
1129
        else
 
1130
                final_name = g_strdup (description);
 
1131
 
 
1132
        g_free (port_name);
 
1133
        g_free (origin);
 
1134
        g_free (description);
 
1135
 
 
1136
        if (card == NULL) {
 
1137
                GvcMixerStream *stream;
 
1138
                g_debug ("just detected a network source");
 
1139
                stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control, input);
 
1140
                if (stream == NULL) {
 
1141
                        g_warning ("tried to add the network source but the stream was null - fail ?!");
 
1142
                        g_free (final_name);
 
1143
                        return;
 
1144
                }
 
1145
                icon = gvc_mixer_stream_get_gicon (stream);
 
1146
        } else
 
1147
                icon = gvc_mixer_card_get_gicon (card);
 
1148
 
 
1149
 
 
1150
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
 
1151
        gtk_list_store_append (GTK_LIST_STORE (model), &iter);
 
1152
 
 
1153
        gtk_list_store_set (GTK_LIST_STORE (model),
 
1154
                            &iter,
 
1155
                            NAME_COLUMN, final_name,
 
1156
                            DEVICE_COLUMN, "",
 
1157
                            ACTIVE_COLUMN, FALSE,
 
1158
                            ICON_COLUMN, icon,
 
1159
                            ID_COLUMN, gvc_mixer_ui_device_get_id (input),
 
1160
                            -1);
 
1161
 
 
1162
        if (icon != NULL)
 
1163
                g_object_unref (icon);
 
1164
        g_free (final_name);
 
1165
}
 
1166
 
 
1167
static void
 
1168
add_output_ui_entry (GvcMixerDialog   *dialog,
 
1169
                     GvcMixerUIDevice *output)
 
1170
{
 
1171
        gchar         *sink_port_name;
 
1172
        gchar         *origin;
 
1173
        gchar         *description;
 
1174
        gchar         *final_name;
 
1175
        gboolean       available;
 
1176
        gint           sink_stream_id;
 
1177
        GtkTreeModel  *model;
 
1178
        GtkTreeIter    iter;
 
1179
        GIcon         *icon;
 
1180
        GvcMixerCard  *card;
 
1181
 
 
1182
        g_debug ("Add output ui entry with id :%u",
 
1183
                  gvc_mixer_ui_device_get_id (output));
 
1184
 
 
1185
        g_object_get (G_OBJECT (output),
 
1186
                     "stream-id", &sink_stream_id,
 
1187
                     "card", &card,
 
1188
                     "origin", &origin,
 
1189
                     "description", &description,
 
1190
                     "port-name", &sink_port_name,
 
1191
                     "port-available", &available,
 
1192
                      NULL);
 
1193
 
 
1194
        if (origin && origin[0] != '\0')
 
1195
                final_name = g_strdup_printf ("%s - %s", description, origin);
 
1196
        else
 
1197
                final_name = g_strdup (description);
 
1198
 
 
1199
        g_free (sink_port_name);
 
1200
        g_free (origin);
 
1201
        g_free (description);
 
1202
 
 
1203
        if (card == NULL) {
 
1204
                GvcMixerStream *stream;
 
1205
 
 
1206
                g_debug ("just detected a network sink");
 
1207
                stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control, output);
 
1208
 
 
1209
                if (stream == NULL) {
 
1210
                        g_warning ("tried to add the network sink but the stream was null - fail ?!");
 
1211
                        g_free (final_name);
 
1212
                        return;
 
1213
                }
 
1214
                icon = gvc_mixer_stream_get_gicon (stream);
 
1215
        } else
 
1216
                icon = gvc_mixer_card_get_gicon (card);
 
1217
 
 
1218
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
 
1219
        gtk_list_store_append (GTK_LIST_STORE (model), &iter);
 
1220
 
 
1221
        gtk_list_store_set (GTK_LIST_STORE (model),
 
1222
                            &iter,
 
1223
                            NAME_COLUMN, final_name,
 
1224
                            DEVICE_COLUMN, "",
 
1225
                            ACTIVE_COLUMN, FALSE,
 
1226
                            ICON_COLUMN, icon,
 
1227
                            ID_COLUMN, gvc_mixer_ui_device_get_id (output),
 
1228
                            -1);
 
1229
 
 
1230
        if (icon != NULL)
 
1231
                g_object_unref (icon);
 
1232
        g_free (final_name);
 
1233
}
 
1234
 
 
1235
 
 
1236
static void
 
1237
on_control_active_input_update (GvcMixerControl *control,
 
1238
                                guint            id,
 
1239
                                GvcMixerDialog  *dialog)
 
1240
{
 
1241
        GvcMixerUIDevice* in = NULL;
 
1242
        in = gvc_mixer_control_lookup_input_id (control, id);
 
1243
 
 
1244
        if (in == NULL) {
 
1245
                g_warning ("on_control_active_input_update - tried to fetch an input of id %u but got nothing", id);
 
1246
                return;
 
1247
        }
 
1248
        active_input_update (dialog, in);
 
1249
}
 
1250
 
 
1251
static void
 
1252
on_control_active_output_update (GvcMixerControl *control,
 
1253
                                 guint            id,
 
1254
                                 GvcMixerDialog  *dialog)
 
1255
{
 
1256
        GvcMixerUIDevice* out = NULL;
 
1257
        out = gvc_mixer_control_lookup_output_id (control, id);
 
1258
 
 
1259
        if (out == NULL) {
 
1260
                g_warning ("on_control_active_output_update - tried to fetch an output of id %u but got nothing", id);
 
1261
                return;
 
1262
        }
 
1263
        active_output_update (dialog, out);
 
1264
}
 
1265
 
 
1266
static void
 
1267
on_control_input_added (GvcMixerControl *control,
 
1268
                        guint            id,
 
1269
                        GvcMixerDialog  *dialog)
 
1270
{
 
1271
        GvcMixerUIDevice* in = NULL;
 
1272
        in = gvc_mixer_control_lookup_input_id (control, id);
 
1273
 
 
1274
        if (in == NULL) {
 
1275
                g_warning ("on_control_input_added - tried to fetch an input of id %u but got nothing", id);
 
1276
                return;
 
1277
        }
 
1278
        add_input_ui_entry (dialog, in);
 
1279
}
 
1280
 
 
1281
static void
 
1282
on_control_input_removed (GvcMixerControl *control,
 
1283
                          guint           id,
 
1284
                          GvcMixerDialog  *dialog)
 
1285
{
 
1286
        gboolean          found;
 
1287
        GtkTreeIter       iter;
 
1288
        GtkTreeModel     *model;
 
1289
        gint              stream_id;
 
1290
        GvcMixerUIDevice *in;
 
1291
 
 
1292
        in = gvc_mixer_control_lookup_input_id (control, id);
 
1293
 
 
1294
        g_object_get (G_OBJECT (in),
 
1295
                     "stream-id", &stream_id,
 
1296
                      NULL);
 
1297
 
 
1298
        g_debug ("Remove input from dialog, id: %u, stream id: %i",
 
1299
                 id,
 
1300
                 stream_id);
 
1301
 
 
1302
        /* remove from any models */
 
1303
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
 
1304
        found = find_item_by_id (GTK_TREE_MODEL (model), id, ID_COLUMN, &iter);
 
1305
        if (found) {
 
1306
                gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
 
1307
        }
 
1308
}
 
1309
 
 
1310
static void
 
1311
on_control_output_added (GvcMixerControl *control,
 
1312
                         guint            id,
 
1313
                         GvcMixerDialog  *dialog)
 
1314
{
 
1315
        GvcMixerUIDevice* out = NULL;
 
1316
        out = gvc_mixer_control_lookup_output_id (control, id);
 
1317
 
 
1318
        if (out == NULL) {
 
1319
                g_warning ("on_control_output_added - tried to fetch an output of id %u but got nothing", id);
 
1320
                return;
 
1321
        }
 
1322
 
 
1323
        add_output_ui_entry (dialog, out);
 
1324
}
 
1325
 
 
1326
static void
 
1327
on_control_output_removed (GvcMixerControl *control,
 
1328
                           guint           id,
 
1329
                           GvcMixerDialog  *dialog)
 
1330
{
 
1331
        gboolean      found;
 
1332
        GtkTreeIter   iter;
 
1333
        GtkTreeModel *model;
 
1334
        gint          sink_stream_id;
 
1335
 
 
1336
        GvcMixerUIDevice* out = NULL;
 
1337
        out = gvc_mixer_control_lookup_output_id (control, id);
 
1338
 
 
1339
        g_object_get (G_OBJECT (out),
 
1340
                     "stream-id", &sink_stream_id,
 
1341
                      NULL);
 
1342
 
 
1343
        g_debug ("Remove output from dialog \n id : %u \n sink stream id : %i \n",
 
1344
                  id,
 
1345
                  sink_stream_id);
 
1346
 
 
1347
         /* remove from any models */
 
1348
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
 
1349
        found = find_item_by_id (GTK_TREE_MODEL (model), id, ID_COLUMN, &iter);
 
1350
        if (found) {
 
1351
                gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
 
1352
        }
 
1353
}
 
1354
 
 
1355
static void
1248
1356
remove_stream (GvcMixerDialog  *dialog,
1249
1357
               guint            id)
1250
1358
{
1251
 
        GtkWidget    *bar;
1252
 
        gboolean      found;
1253
 
        GtkTreeIter   iter;
1254
 
        GtkTreeModel *model;
 
1359
        GtkWidget *bar;
 
1360
        guint output_id, input_id;
1255
1361
 
1256
 
        /* remove bars for applications and reset fixed bars */
1257
1362
        bar = g_hash_table_lookup (dialog->priv->bars, GUINT_TO_POINTER (id));
1258
 
        if (bar == dialog->priv->output_bar
1259
 
            || bar == dialog->priv->input_bar
1260
 
            || bar == dialog->priv->effects_bar) {
1261
 
                char *name;
1262
 
                g_object_get (bar, "name", &name, NULL);
1263
 
                g_debug ("Removing stream for bar '%s'", name);
1264
 
                g_free (name);
1265
 
                bar_set_stream (dialog, bar, NULL);
1266
 
        } else if (bar != NULL) {
 
1363
        if (bar != NULL) {
1267
1364
                g_hash_table_remove (dialog->priv->bars, GUINT_TO_POINTER (id));
1268
1365
                gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (bar)),
1269
1366
                                      bar);
1271
1368
                if (dialog->priv->num_apps == 0) {
1272
1369
                        gtk_widget_show (dialog->priv->no_apps_label);
1273
1370
                }
1274
 
        }
1275
 
 
1276
 
        /* remove from any models */
1277
 
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
1278
 
        found = find_item_by_id (GTK_TREE_MODEL (model), id, ID_COLUMN, &iter);
1279
 
        if (found) {
1280
 
                gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
1281
 
        }
1282
 
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
1283
 
        found = find_item_by_id (GTK_TREE_MODEL (model), id, ID_COLUMN, &iter);
1284
 
        if (found) {
1285
 
                gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
1286
 
        }
 
1371
                return;
 
1372
        }
 
1373
 
 
1374
        output_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (dialog->priv->output_bar), "gvc-mixer-dialog-stream-id"));
 
1375
        input_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (dialog->priv->input_bar), "gvc-mixer-dialog-stream-id"));
 
1376
 
 
1377
        if (output_id == id)
 
1378
                bar = dialog->priv->output_bar;
 
1379
        else if (input_id == id)
 
1380
                bar = dialog->priv->input_bar;
 
1381
        else
 
1382
                return;
 
1383
 
 
1384
        g_object_set_data (G_OBJECT (bar), "gvc-mixer-dialog-stream-id", NULL);
 
1385
        g_object_set_data (G_OBJECT (bar), "gvc-mixer-dialog-stream", NULL);
1287
1386
}
1288
1387
 
1289
1388
static void
1295
1394
}
1296
1395
 
1297
1396
static void
1298
 
add_card (GvcMixerDialog *dialog,
1299
 
          GvcMixerCard   *card)
1300
 
{
1301
 
        GtkTreeModel        *model;
1302
 
        GtkTreeIter          iter;
1303
 
        GtkTreeSelection    *selection;
1304
 
        GvcMixerCardProfile *profile;
1305
 
        GIcon               *icon;
1306
 
        guint                index;
1307
 
 
1308
 
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview));
1309
 
        index = gvc_mixer_card_get_index (card);
1310
 
        if (find_item_by_id (GTK_TREE_MODEL (model), index, HW_ID_COLUMN, &iter) == FALSE)
1311
 
                gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1312
 
        profile = gvc_mixer_card_get_profile (card);
1313
 
        g_assert (profile != NULL);
1314
 
        icon = g_themed_icon_new_with_default_fallbacks (gvc_mixer_card_get_icon_name (card));
1315
 
        //FIXME we need the status (default for a profile?) here
1316
 
        gtk_list_store_set (GTK_LIST_STORE (model),
1317
 
                            &iter,
1318
 
                            HW_NAME_COLUMN, gvc_mixer_card_get_name (card),
1319
 
                            HW_ID_COLUMN, index,
1320
 
                            HW_ICON_COLUMN, icon,
1321
 
                            HW_PROFILE_COLUMN, profile->profile,
1322
 
                            HW_PROFILE_HUMAN_COLUMN, profile->human_profile,
1323
 
                            HW_STATUS_COLUMN, profile->status,
1324
 
                            HW_SENSITIVE_COLUMN, g_strcmp0 (profile->profile, "off") != 0,
1325
 
                            -1);
1326
 
        if (icon != NULL)
1327
 
                g_object_unref (icon);
1328
 
 
1329
 
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->hw_treeview));
1330
 
        if (gtk_tree_selection_get_selected (selection, NULL, NULL) == FALSE) {
1331
 
                gtk_tree_selection_select_iter (selection, &iter);
1332
 
        } else if (dialog->priv->hw_profile_combo != NULL) {
1333
 
                GvcMixerCard *selected;
1334
 
 
1335
 
                /* Set the current profile if it changed for the selected card */
1336
 
                selected = g_object_get_data (G_OBJECT (dialog->priv->hw_profile_combo), "card");
1337
 
                if (gvc_mixer_card_get_index (selected) == gvc_mixer_card_get_index (card)) {
1338
 
                        gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->hw_profile_combo),
1339
 
                                                  profile->profile);
1340
 
                        g_object_set (G_OBJECT (dialog->priv->hw_profile_combo),
1341
 
                                      "show-button", profile->n_sinks == 1,
1342
 
                                      NULL);
1343
 
                }
1344
 
        }
1345
 
}
1346
 
 
1347
 
static void
1348
 
on_control_card_added (GvcMixerControl *control,
1349
 
                       guint            id,
1350
 
                       GvcMixerDialog  *dialog)
1351
 
{
1352
 
        GvcMixerCard *card;
1353
 
 
1354
 
        card = gvc_mixer_control_lookup_card_id (control, id);
1355
 
        if (card != NULL) {
1356
 
                add_card (dialog, card);
1357
 
        }
1358
 
}
1359
 
 
1360
 
static void
1361
 
remove_card (GvcMixerDialog  *dialog,
1362
 
             guint            id)
1363
 
{
1364
 
        gboolean      found;
1365
 
        GtkTreeIter   iter;
1366
 
        GtkTreeModel *model;
1367
 
 
1368
 
        /* remove from any models */
1369
 
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview));
1370
 
        found = find_item_by_id (GTK_TREE_MODEL (model), id, HW_ID_COLUMN, &iter);
1371
 
        if (found) {
1372
 
                gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
1373
 
        }
1374
 
}
1375
 
static void
1376
 
on_control_card_removed (GvcMixerControl *control,
1377
 
                         guint            id,
1378
 
                         GvcMixerDialog  *dialog)
1379
 
{
1380
 
        remove_card (dialog, id);
1381
 
}
1382
 
 
1383
 
static void
1384
1397
_gtk_label_make_bold (GtkLabel *label)
1385
1398
{
1386
1399
        PangoFontDescription *font_desc;
1404
1417
on_input_selection_changed (GtkTreeSelection *selection,
1405
1418
                            GvcMixerDialog   *dialog)
1406
1419
{
1407
 
        GtkTreeModel *model;
1408
 
        GtkTreeIter   iter;
1409
 
        gboolean      toggled;
1410
 
        guint         id;
 
1420
        GtkTreeModel     *model;
 
1421
        GtkTreeIter       iter;
 
1422
        gboolean          active;
 
1423
        guint             id;
 
1424
        GvcMixerUIDevice *input;
1411
1425
 
1412
1426
        if (gtk_tree_selection_get_selected (selection, &model, &iter) == FALSE) {
1413
1427
                g_debug ("Could not get default input from selection");
1416
1430
 
1417
1431
        gtk_tree_model_get (model, &iter,
1418
1432
                            ID_COLUMN, &id,
1419
 
                            ACTIVE_COLUMN, &toggled,
 
1433
                            ACTIVE_COLUMN, &active,
1420
1434
                            -1);
1421
1435
 
1422
 
        toggled ^= 1;
1423
 
        if (toggled) {
1424
 
                GvcMixerStream *stream;
1425
 
 
1426
 
                g_debug ("Default input selected: %u", id);
1427
 
                stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id);
1428
 
                if (stream == NULL) {
1429
 
                        g_warning ("Unable to find stream for id: %u", id);
1430
 
                        return;
1431
 
                }
1432
 
 
1433
 
                gvc_mixer_control_set_default_source (dialog->priv->mixer_control, stream);
 
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;
1434
1441
        }
 
1442
 
 
1443
        gvc_mixer_control_change_input (dialog->priv->mixer_control, input);
1435
1444
}
1436
1445
 
1437
1446
static void
1438
1447
on_output_selection_changed (GtkTreeSelection *selection,
1439
1448
                             GvcMixerDialog   *dialog)
1440
1449
{
1441
 
        GtkTreeModel *model;
1442
 
        GtkTreeIter   iter;
1443
 
        gboolean      toggled;
1444
 
        guint         id;
 
1450
        GtkTreeModel     *model;
 
1451
        GtkTreeIter       iter;
 
1452
        gboolean          active;
 
1453
        guint             id;
 
1454
        GvcMixerUIDevice *output;
1445
1455
 
1446
1456
        if (gtk_tree_selection_get_selected (selection, &model, &iter) == FALSE) {
1447
1457
                g_debug ("Could not get default output from selection");
1450
1460
 
1451
1461
        gtk_tree_model_get (model, &iter,
1452
1462
                            ID_COLUMN, &id,
1453
 
                            ACTIVE_COLUMN, &toggled,
 
1463
                            ACTIVE_COLUMN, &active,
1454
1464
                            -1);
1455
1465
 
1456
 
        toggled ^= 1;
1457
 
        if (toggled) {
1458
 
                GvcMixerStream *stream;
1459
 
 
1460
 
                g_debug ("Default output selected: %u", id);
1461
 
                stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id);
1462
 
                if (stream == NULL) {
1463
 
                        g_warning ("Unable to find stream for id: %u", id);
1464
 
                        return;
1465
 
                }
1466
 
 
1467
 
                gvc_mixer_control_set_default_sink (dialog->priv->mixer_control, stream);
 
1466
        g_debug ("on_output_selection_changed() stream id: %u, active %i", id, active);
 
1467
        if (active)
 
1468
                return;
 
1469
 
 
1470
        output = gvc_mixer_control_lookup_output_id (dialog->priv->mixer_control, id);
 
1471
 
 
1472
        if (output == NULL) {
 
1473
                g_warning ("Unable to find output with id: %u", id);
 
1474
                return;
1468
1475
        }
 
1476
 
 
1477
        gvc_mixer_control_change_output (dialog->priv->mixer_control, output);
1469
1478
}
1470
1479
 
1471
1480
static GtkWidget *
1472
 
create_stream_treeview (GvcMixerDialog *dialog,
1473
 
                        GCallback       on_selection_changed)
 
1481
create_ui_device_treeview (GvcMixerDialog *dialog,
 
1482
                           GCallback       on_selection_changed)
1474
1483
{
1475
1484
        GtkWidget         *treeview;
1476
1485
        GtkListStore      *store;
1523
1532
}
1524
1533
 
1525
1534
static void
1526
 
on_profile_changed (GvcComboBox *widget,
1527
 
                    const char  *profile,
1528
 
                    gpointer     user_data)
1529
 
{
1530
 
        GvcMixerCard        *card;
1531
 
 
1532
 
        card = g_object_get_data (G_OBJECT (widget), "card");
1533
 
        if (card == NULL) {
1534
 
                g_warning ("Could not find card for combobox");
1535
 
                return;
1536
 
        }
1537
 
 
1538
 
        g_debug ("Profile changed to %s for card %s", profile,
1539
 
                 gvc_mixer_card_get_name (card));
1540
 
 
1541
 
        gvc_mixer_card_change_profile (card, profile);
1542
 
}
1543
 
 
1544
 
static void
1545
1535
on_test_speakers_clicked (GvcComboBox *widget,
1546
1536
                          gpointer     user_data)
1547
1537
{
1548
1538
        GvcMixerDialog      *dialog = GVC_MIXER_DIALOG (user_data);
1549
 
        GvcMixerCard        *card;
1550
 
        GvcMixerCardProfile *profile;
 
1539
        GtkTreeModel        *model;
 
1540
        GtkTreeIter          iter;
 
1541
        gint                 stream_id;
 
1542
        gint                 active_output = GVC_MIXER_UI_DEVICE_INVALID;
 
1543
        GvcMixerUIDevice    *output;
 
1544
        GvcMixerStream      *stream;
1551
1545
        GtkWidget           *d, *speaker_test, *container;
1552
1546
        char                *title;
1553
1547
 
1554
 
        card = g_object_get_data (G_OBJECT (widget), "card");
1555
 
        if (card == NULL) {
1556
 
                g_warning ("Could not find card for combobox");
1557
 
                return;
1558
 
        }
1559
 
        profile = gvc_mixer_card_get_profile (card);
1560
 
 
1561
 
        g_debug ("XXX Start speaker testing for profile '%s', card %s XXX",
1562
 
                 profile->profile, gvc_mixer_card_get_name (card));
1563
 
 
1564
 
        title = g_strdup_printf (_("Speaker Testing for %s"), gvc_mixer_card_get_name (card));
 
1548
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
 
1549
 
 
1550
        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
 
1551
                g_warning ("The tree is empty => we have no device to test speakers with return");
 
1552
                return;
 
1553
        }
 
1554
 
 
1555
        do {
 
1556
                gboolean         is_selected = FALSE;
 
1557
                gint             id;
 
1558
 
 
1559
                gtk_tree_model_get (model, &iter,
 
1560
                                    ID_COLUMN, &id,
 
1561
                                    ACTIVE_COLUMN, &is_selected,
 
1562
                                    -1);
 
1563
 
 
1564
                if (is_selected) {
 
1565
                        active_output = id;
 
1566
                        break;
 
1567
                }
 
1568
        } while (gtk_tree_model_iter_next (model, &iter));
 
1569
 
 
1570
        if (active_output == GVC_MIXER_UI_DEVICE_INVALID) {
 
1571
                g_warning ("Can't find the active output from the UI");
 
1572
                return;
 
1573
        }
 
1574
 
 
1575
        output = gvc_mixer_control_lookup_output_id (dialog->priv->mixer_control, (guint)active_output);
 
1576
        stream_id = gvc_mixer_ui_device_get_stream_id (output);
 
1577
 
 
1578
        if (stream_id == GVC_MIXER_UI_DEVICE_INVALID)
 
1579
                return;
 
1580
 
 
1581
        g_debug ("Test speakers on '%s'", gvc_mixer_ui_device_get_description (output));
 
1582
 
 
1583
        stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, stream_id);
 
1584
        if (stream == NULL) {
 
1585
                g_debug ("Stream/sink not found");
 
1586
                return;
 
1587
        }
 
1588
        title = g_strdup_printf (_("Speaker Testing for %s"), gvc_mixer_ui_device_get_description (output));
1565
1589
        d = gtk_dialog_new_with_buttons (title,
1566
1590
                                         GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (widget))),
1567
1591
                                         GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1568
1592
                                         GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
1569
1593
                                         NULL);
1570
 
        /* FIXME: this should not be necessary */
1571
1594
        gtk_window_set_has_resize_grip (GTK_WINDOW (d), FALSE);
1572
1595
 
1573
1596
        g_free (title);
1574
1597
        speaker_test = gvc_speaker_test_new (dialog->priv->mixer_control,
1575
 
                                             card);
 
1598
                                             stream);
1576
1599
        gtk_widget_show (speaker_test);
1577
1600
        container = gtk_dialog_get_content_area (GTK_DIALOG (d));
1578
1601
        gtk_container_add (GTK_CONTAINER (container), speaker_test);
1581
1604
        gtk_widget_destroy (d);
1582
1605
}
1583
1606
 
1584
 
static void
1585
 
on_card_selection_changed (GtkTreeSelection *selection,
1586
 
                           gpointer          user_data)
1587
 
{
1588
 
        GvcMixerDialog      *dialog = GVC_MIXER_DIALOG (user_data);
1589
 
        GtkTreeModel        *model;
1590
 
        GtkTreeIter          iter;
1591
 
        const GList         *profiles;
1592
 
        guint                id;
1593
 
        GvcMixerCard        *card;
1594
 
        GvcMixerCardProfile *current_profile;
1595
 
 
1596
 
        g_debug ("Card selection changed");
1597
 
 
1598
 
        if (dialog->priv->hw_profile_combo != NULL) {
1599
 
                gtk_container_remove (GTK_CONTAINER (dialog->priv->hw_settings_box),
1600
 
                                      dialog->priv->hw_profile_combo);
1601
 
                dialog->priv->hw_profile_combo = NULL;
1602
 
        }
1603
 
 
1604
 
        if (gtk_tree_selection_get_selected (selection,
1605
 
                                             NULL,
1606
 
                                             &iter) == FALSE) {
1607
 
                return;
1608
 
        }
1609
 
 
1610
 
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview));
1611
 
        gtk_tree_model_get (model, &iter,
1612
 
                            HW_ID_COLUMN, &id,
1613
 
                            -1);
1614
 
        card = gvc_mixer_control_lookup_card_id (dialog->priv->mixer_control, id);
1615
 
        if (card == NULL) {
1616
 
                g_warning ("Unable to find card for id: %u", id);
1617
 
                return;
1618
 
        }
1619
 
 
1620
 
        current_profile = gvc_mixer_card_get_profile (card);
1621
 
        profiles = gvc_mixer_card_get_profiles (card);
1622
 
        dialog->priv->hw_profile_combo = gvc_combo_box_new (_("_Profile:"));
1623
 
        g_object_set (G_OBJECT (dialog->priv->hw_profile_combo), "button-label", _("_Test Speakers"), NULL);
1624
 
        gvc_combo_box_set_profiles (GVC_COMBO_BOX (dialog->priv->hw_profile_combo), profiles);
1625
 
        gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->hw_profile_combo), current_profile->profile);
1626
 
 
1627
 
        gtk_box_pack_start (GTK_BOX (dialog->priv->hw_settings_box),
1628
 
                            dialog->priv->hw_profile_combo,
1629
 
                            TRUE, TRUE, 6);
1630
 
        g_object_set (G_OBJECT (dialog->priv->hw_profile_combo),
1631
 
                      "show-button", current_profile->n_sinks == 1,
1632
 
                      NULL);
1633
 
        gtk_widget_show (dialog->priv->hw_profile_combo);
1634
 
 
1635
 
        g_object_set_data (G_OBJECT (dialog->priv->hw_profile_combo), "card", card);
1636
 
        g_signal_connect (G_OBJECT (dialog->priv->hw_profile_combo), "changed",
1637
 
                          G_CALLBACK (on_profile_changed), dialog);
1638
 
        g_signal_connect (G_OBJECT (dialog->priv->hw_profile_combo), "button-clicked",
1639
 
                          G_CALLBACK (on_test_speakers_clicked), dialog);
1640
 
}
1641
 
 
1642
 
static void
1643
 
card_to_text (GtkTreeViewColumn *column,
1644
 
              GtkCellRenderer *cell,
1645
 
              GtkTreeModel *model,
1646
 
              GtkTreeIter *iter,
1647
 
              gpointer user_data)
1648
 
{
1649
 
        char *name, *status, *profile, *str;
1650
 
        gboolean sensitive;
1651
 
 
1652
 
        gtk_tree_model_get(model, iter,
1653
 
                           HW_NAME_COLUMN, &name,
1654
 
                           HW_STATUS_COLUMN, &status,
1655
 
                           HW_PROFILE_HUMAN_COLUMN, &profile,
1656
 
                           HW_SENSITIVE_COLUMN, &sensitive,
1657
 
                           -1);
1658
 
 
1659
 
        str = g_strdup_printf ("%s\n<i>%s</i>\n<i>%s</i>",
1660
 
                               name, status, profile);
1661
 
        g_object_set (cell,
1662
 
                      "markup", str,
1663
 
                      "sensitive", sensitive,
1664
 
                      NULL);
1665
 
        g_free (str);
1666
 
 
1667
 
        g_free (name);
1668
 
        g_free (status);
1669
 
        g_free (profile);
1670
 
}
1671
 
 
1672
 
static GtkWidget *
1673
 
create_cards_treeview (GvcMixerDialog *dialog,
1674
 
                       GCallback       on_changed)
1675
 
{
1676
 
        GtkWidget         *treeview;
1677
 
        GtkListStore      *store;
1678
 
        GtkCellRenderer   *renderer;
1679
 
        GtkTreeViewColumn *column;
1680
 
        GtkTreeSelection  *selection;
1681
 
 
1682
 
        treeview = gtk_tree_view_new ();
1683
 
        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
1684
 
 
1685
 
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
1686
 
        g_signal_connect (G_OBJECT (selection), "changed",
1687
 
                          on_changed, dialog);
1688
 
 
1689
 
        store = gtk_list_store_new (HW_NUM_COLUMNS,
1690
 
                                    G_TYPE_UINT,
1691
 
                                    G_TYPE_ICON,
1692
 
                                    G_TYPE_STRING,
1693
 
                                    G_TYPE_STRING,
1694
 
                                    G_TYPE_STRING,
1695
 
                                    G_TYPE_STRING,
1696
 
                                    G_TYPE_BOOLEAN);
1697
 
        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
1698
 
                                 GTK_TREE_MODEL (store));
1699
 
 
1700
 
        renderer = gtk_cell_renderer_pixbuf_new ();
1701
 
        g_object_set (G_OBJECT (renderer), "stock-size", GTK_ICON_SIZE_DIALOG, NULL);
1702
 
        column = gtk_tree_view_column_new_with_attributes (NULL,
1703
 
                                                           renderer,
1704
 
                                                           "gicon", HW_ICON_COLUMN,
1705
 
                                                           "sensitive", HW_SENSITIVE_COLUMN,
1706
 
                                                           NULL);
1707
 
        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
1708
 
 
1709
 
        gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (treeview), -1,
1710
 
                                                    _("Name"), gtk_cell_renderer_text_new (),
1711
 
                                                    card_to_text, NULL, NULL);
1712
 
 
1713
 
        return treeview;
1714
 
}
1715
 
 
1716
1607
static GObject *
1717
1608
gvc_mixer_dialog_constructor (GType                  type,
1718
1609
                              guint                  n_construct_properties,
1727
1618
        GtkWidget        *sbox;
1728
1619
        GtkWidget        *ebox;
1729
1620
        GSList           *streams;
1730
 
        GSList           *cards;
1731
1621
        GSList           *l;
1732
1622
        GvcMixerStream   *stream;
1733
 
        GvcMixerCard     *card;
1734
 
        GtkTreeSelection *selection;
1735
1623
 
1736
1624
        object = G_OBJECT_CLASS (gvc_mixer_dialog_parent_class)->constructor (type, n_construct_properties, construct_params);
1737
1625
 
1781
1669
        gtk_container_add (GTK_CONTAINER (box), alignment);
1782
1670
        gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 0, 0);
1783
1671
 
1784
 
        self->priv->output_treeview = create_stream_treeview (self,
1785
 
                                                              G_CALLBACK (on_output_selection_changed));
 
1672
        self->priv->output_treeview = create_ui_device_treeview (self,
 
1673
                                                                 G_CALLBACK (on_output_selection_changed));
1786
1674
        gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->priv->output_treeview);
1787
1675
 
1788
1676
        box = gtk_scrolled_window_new (NULL, NULL);
1875
1763
        gtk_container_add (GTK_CONTAINER (box), alignment);
1876
1764
        gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 0, 0);
1877
1765
 
1878
 
        self->priv->input_treeview = create_stream_treeview (self,
1879
 
                                                             G_CALLBACK (on_input_selection_changed));
 
1766
        self->priv->input_treeview = create_ui_device_treeview (self,
 
1767
                                                                G_CALLBACK (on_input_selection_changed));
1880
1768
        gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->priv->input_treeview);
1881
1769
 
1882
1770
        box = gtk_scrolled_window_new (NULL, NULL);
1888
1776
        gtk_container_add (GTK_CONTAINER (box), self->priv->input_treeview);
1889
1777
        gtk_container_add (GTK_CONTAINER (alignment), box);
1890
1778
 
1891
 
        /* Hardware page */
1892
 
        self->priv->hw_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
1893
 
        gtk_container_set_border_width (GTK_CONTAINER (self->priv->hw_box), 12);
1894
 
        label = gtk_label_new (_("Hardware"));
1895
 
        gtk_notebook_append_page (GTK_NOTEBOOK (self->priv->notebook),
1896
 
                                  self->priv->hw_box,
1897
 
                                  label);
1898
 
 
1899
 
        box = gtk_frame_new (_("C_hoose a device to configure:"));
1900
 
        label = gtk_frame_get_label_widget (GTK_FRAME (box));
1901
 
        _gtk_label_make_bold (GTK_LABEL (label));
1902
 
        gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
1903
 
        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
1904
 
        gtk_box_pack_start (GTK_BOX (self->priv->hw_box), box, TRUE, TRUE, 0);
1905
 
 
1906
 
        alignment = gtk_alignment_new (0, 0, 1, 1);
1907
 
        gtk_container_add (GTK_CONTAINER (box), alignment);
1908
 
        gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 0, 0);
1909
 
 
1910
 
        self->priv->hw_treeview = create_cards_treeview (self,
1911
 
                                                         G_CALLBACK (on_card_selection_changed));
1912
 
        gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->priv->hw_treeview);
1913
 
 
1914
 
        box = gtk_scrolled_window_new (NULL, NULL);
1915
 
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (box),
1916
 
                                        GTK_POLICY_NEVER,
1917
 
                                        GTK_POLICY_AUTOMATIC);
1918
 
        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (box),
1919
 
                                             GTK_SHADOW_IN);
1920
 
        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (box), 150);
1921
 
        gtk_container_add (GTK_CONTAINER (box), self->priv->hw_treeview);
1922
 
        gtk_container_add (GTK_CONTAINER (alignment), box);
1923
 
 
1924
 
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->hw_treeview));
1925
 
        gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
1926
 
 
1927
 
        box = gtk_frame_new (_("Settings for the selected device:"));
1928
 
        label = gtk_frame_get_label_widget (GTK_FRAME (box));
1929
 
        _gtk_label_make_bold (GTK_LABEL (label));
1930
 
        gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
1931
 
        gtk_box_pack_start (GTK_BOX (self->priv->hw_box), box, FALSE, TRUE, 12);
1932
 
        self->priv->hw_settings_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
1933
 
        gtk_container_add (GTK_CONTAINER (box), self->priv->hw_settings_box);
1934
 
 
1935
1779
        /* Effects page */
1936
1780
        self->priv->sound_effects_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
1937
1781
        gtk_container_set_border_width (GTK_CONTAINER (self->priv->sound_effects_box), 12);
1965
1809
                            TRUE, TRUE, 0);
1966
1810
 
1967
1811
        g_signal_connect (self->priv->mixer_control,
 
1812
                          "output-added",
 
1813
                          G_CALLBACK (on_control_output_added),
 
1814
                          self);
 
1815
        g_signal_connect (self->priv->mixer_control,
 
1816
                          "output-removed",
 
1817
                          G_CALLBACK (on_control_output_removed),
 
1818
                          self);
 
1819
        g_signal_connect (self->priv->mixer_control,
 
1820
                          "input-added",
 
1821
                          G_CALLBACK (on_control_input_added),
 
1822
                          self);
 
1823
        g_signal_connect (self->priv->mixer_control,
 
1824
                          "input-removed",
 
1825
                          G_CALLBACK (on_control_input_removed),
 
1826
                          self);
 
1827
 
 
1828
        g_signal_connect (self->priv->mixer_control,
1968
1829
                          "stream-added",
1969
1830
                          G_CALLBACK (on_control_stream_added),
1970
1831
                          self);
1972
1833
                          "stream-removed",
1973
1834
                          G_CALLBACK (on_control_stream_removed),
1974
1835
                          self);
1975
 
        g_signal_connect (self->priv->mixer_control,
1976
 
                          "card-added",
1977
 
                          G_CALLBACK (on_control_card_added),
1978
 
                          self);
1979
 
        g_signal_connect (self->priv->mixer_control,
1980
 
                          "card-removed",
1981
 
                          G_CALLBACK (on_control_card_removed),
1982
 
                          self);
1983
1836
 
1984
1837
        gtk_widget_show_all (main_vbox);
1985
1838
 
1990
1843
        }
1991
1844
        g_slist_free (streams);
1992
1845
 
1993
 
        cards = gvc_mixer_control_get_cards (self->priv->mixer_control);
1994
 
        for (l = cards; l != NULL; l = l->next) {
1995
 
                card = l->data;
1996
 
                add_card (self, card);
1997
 
        }
1998
 
        g_slist_free (cards);
1999
 
 
2000
1846
        return object;
2001
1847
}
2002
1848
 
2006
1852
        GvcMixerDialog *dialog = GVC_MIXER_DIALOG (object);
2007
1853
 
2008
1854
        if (dialog->priv->mixer_control != NULL) {
 
1855
 
 
1856
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
 
1857
                                                      on_control_output_added,
 
1858
                                                      dialog);
 
1859
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
 
1860
                                                      on_control_output_removed,
 
1861
                                                      dialog);
 
1862
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
 
1863
                                                      on_control_input_added,
 
1864
                                                      dialog);
 
1865
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
 
1866
                                                      on_control_input_removed,
 
1867
                                                      dialog);
 
1868
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
 
1869
                                                      on_control_active_input_update,
 
1870
                                                      dialog);
 
1871
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
 
1872
                                                      on_control_active_output_update,
 
1873
                                                      dialog);
2009
1874
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
2010
1875
                                                      on_control_stream_added,
2011
1876
                                                      dialog);
2012
1877
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
2013
1878
                                                      on_control_stream_removed,
2014
1879
                                                      dialog);
2015
 
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
2016
 
                                                      on_control_card_added,
2017
 
                                                      dialog);
2018
 
                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
2019
 
                                                      on_control_card_removed,
2020
 
                                                      dialog);
2021
1880
 
2022
1881
                g_object_unref (dialog->priv->mixer_control);
2023
1882
                dialog->priv->mixer_control = NULL;
2089
1948
enum {
2090
1949
        PAGE_OUTPUT,
2091
1950
        PAGE_INPUT,
2092
 
        PAGE_HARDWARE,
2093
1951
        PAGE_EVENTS,
2094
1952
        PAGE_APPLICATIONS
2095
1953
};
2106
1964
 
2107
1965
        if (g_str_equal (page, "effects"))
2108
1966
                num = PAGE_EVENTS;
2109
 
        else if (g_str_equal (page, "hardware"))
2110
 
                num = PAGE_HARDWARE;
2111
1967
        else if (g_str_equal (page, "input"))
2112
1968
                num = PAGE_INPUT;
2113
1969
        else if (g_str_equal (page, "output"))