[gnome-control-center] sound: Make the dialog UI use GvcMixerUIDevice



commit b3fe98e7c1eca17ef8e2e728e44a9a42edd0e149
Author: David Henningsson <david henningsson canonical com>
Date:   Tue Jul 10 17:45:27 2012 +0200

    sound: Make the dialog UI use GvcMixerUIDevice
    
    The input and output treeview now represent GvcMixerUIDevices,
    not sinks and sources. Also turn the connector combobox into a
    profile combobox.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=674831

 panels/sound/gvc-mixer-dialog.c | 1054 +++++++++++++++++++++------------------
 1 files changed, 579 insertions(+), 475 deletions(-)
---
diff --git a/panels/sound/gvc-mixer-dialog.c b/panels/sound/gvc-mixer-dialog.c
index b573e23..d50a48c 100644
--- a/panels/sound/gvc-mixer-dialog.c
+++ b/panels/sound/gvc-mixer-dialog.c
@@ -52,7 +52,7 @@
 struct GvcMixerDialogPrivate
 {
         GvcMixerControl *mixer_control;
-        GHashTable      *bars;
+        GHashTable      *bars; /* Application and event bars only */
         GtkWidget       *notebook;
         GtkWidget       *output_bar;
         GtkWidget       *input_bar;
@@ -73,9 +73,9 @@ struct GvcMixerDialogPrivate
         GtkWidget       *output_balance_bar;
         GtkWidget       *output_fade_bar;
         GtkWidget       *output_lfe_bar;
-        GtkWidget       *output_port_combo;
+        GtkWidget       *output_profile_combo;
         GtkWidget       *input_treeview;
-        GtkWidget       *input_port_combo;
+        GtkWidget       *input_profile_combo;
         GtkWidget       *input_settings_box;
         GtkWidget       *sound_theme_chooser;
         GtkWidget       *click_feedback_button;
@@ -122,116 +122,51 @@ static void     bar_set_stream              (GvcMixerDialog      *dialog,
 
 static void     on_adjustment_value_changed (GtkAdjustment  *adjustment,
                                              GvcMixerDialog *dialog);
+static void     on_control_active_output_update (GvcMixerControl *control,
+                                                 guint            id,
+                                                 GvcMixerDialog  *dialog);
 
-G_DEFINE_TYPE (GvcMixerDialog, gvc_mixer_dialog, GTK_TYPE_VBOX)
-
-static void
-update_default_input (GvcMixerDialog *dialog)
-{
-        GtkTreeModel *model;
-        GtkTreeIter   iter;
-        gboolean      ret;
-
-        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
-        ret = gtk_tree_model_get_iter_first (model, &iter);
-        if (ret == FALSE) {
-                g_debug ("No default input selected or available");
-                return;
-        }
-        do {
-                gboolean        toggled;
-                gboolean        is_default;
-                guint           id;
-                GvcMixerStream *stream;
-
-                gtk_tree_model_get (model, &iter,
-                                    ID_COLUMN, &id,
-                                    ACTIVE_COLUMN, &toggled,
-                                    -1);
-
-                stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id);
-                if (stream == NULL) {
-                        g_warning ("Unable to find stream for id: %u", id);
-                        continue;
-                }
+static void     on_control_active_input_update (GvcMixerControl *control,
+                                                guint            id,
+                                                GvcMixerDialog  *dialog);
 
-                is_default = FALSE;
-                if (stream == gvc_mixer_control_get_default_source (dialog->priv->mixer_control)) {
-                        is_default = TRUE;
-                }
 
-                gtk_list_store_set (GTK_LIST_STORE (model),
-                                    &iter,
-                                    ACTIVE_COLUMN, is_default,
-                                    -1);
-                if (is_default) {
-                        GtkTreeSelection *selection;
-
-                        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->input_treeview));
-                        gtk_tree_selection_select_iter (selection, &iter);
-                }
-        } while (gtk_tree_model_iter_next (model, &iter));
-}
+G_DEFINE_TYPE (GvcMixerDialog, gvc_mixer_dialog, GTK_TYPE_VBOX)
 
 static void
-update_description (GvcMixerDialog *dialog,
-                    guint column,
-                    const char *value,
-                    GvcMixerStream *stream)
+profile_selection_changed (GvcComboBox    *combo_box,
+                           const char     *profile,
+                           GvcMixerDialog *dialog)
 {
-        GtkTreeModel *model;
-        GtkTreeIter   iter;
-        guint         id;
+        GvcMixerUIDevice *output;
 
-        if (GVC_IS_MIXER_SOURCE (stream))
-                model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
-        else if (GVC_IS_MIXER_SINK (stream))
-                model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
-        else
-                g_assert_not_reached ();
-        gtk_tree_model_get_iter_first (model, &iter);
+        g_debug ("profile_selection_changed() to %s", profile);
 
-        id = gvc_mixer_stream_get_id (stream);
-        do {
-                guint       current_id;
+        output = g_object_get_data (G_OBJECT (combo_box), "uidevice");
 
-                gtk_tree_model_get (model, &iter,
-                                    ID_COLUMN, &current_id,
-                                    -1);
-                if (id != current_id)
-                        continue;
-
-                gtk_list_store_set (GTK_LIST_STORE (model),
-                                    &iter,
-                                    column, value,
-                                    -1);
-                break;
-        } while (gtk_tree_model_iter_next (model, &iter));
-}
-
-static void
-port_selection_changed (GvcComboBox *combo_box,
-                        const char  *port,
-                        GvcMixerDialog *dialog)
-{
-        GvcMixerStream *stream;
-
-        stream = g_object_get_data (G_OBJECT (combo_box), "stream");
-        if (stream == NULL) {
-                g_warning ("Could not find stream for port combo box");
+        if (output == NULL) {
+                g_warning ("Could not find Output for profile combo box");
                 return;
         }
-        if (gvc_mixer_stream_change_port (stream, port) == FALSE) {
-                g_warning ("Could not change port for stream");
-        }
+
+        g_debug ("on profile selection changed on output '%s' (origin: %s, id: %i)",
+                gvc_mixer_ui_device_get_description (output),
+                gvc_mixer_ui_device_get_origin (output),
+                gvc_mixer_ui_device_get_id (output));
+
+        if (gvc_mixer_control_change_profile_on_selected_device (dialog->priv->mixer_control, output, profile) == FALSE) {
+                g_warning ("Could not change profile on device %s",
+                           gvc_mixer_ui_device_get_description (output));
+         }
 }
 
 static void
-update_output_settings (GvcMixerDialog *dialog)
+update_output_settings (GvcMixerDialog      *dialog,
+                        GvcMixerUIDevice    *device)
 {
         GvcMixerStream      *stream;
         const GvcChannelMap *map;
-        const GList         *ports;
+        const GList         *profiles;
         GtkAdjustment       *adj;
 
         g_debug ("Updating output settings");
@@ -250,13 +185,14 @@ update_output_settings (GvcMixerDialog *dialog)
                                       dialog->priv->output_lfe_bar);
                 dialog->priv->output_lfe_bar = NULL;
         }
-        if (dialog->priv->output_port_combo != NULL) {
+        if (dialog->priv->output_profile_combo != NULL) {
                 gtk_container_remove (GTK_CONTAINER (dialog->priv->output_settings_box),
-                                      dialog->priv->output_port_combo);
-                dialog->priv->output_port_combo = NULL;
+                                      dialog->priv->output_profile_combo);
+                dialog->priv->output_profile_combo = NULL;
         }
 
-        stream = gvc_mixer_control_get_default_sink (dialog->priv->mixer_control);
+        stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control,
+                                                           device);
         if (stream == NULL) {
                 g_warning ("Default sink stream not found");
                 return;
@@ -316,100 +252,40 @@ update_output_settings (GvcMixerDialog *dialog)
                 gtk_widget_show (dialog->priv->output_lfe_bar);
         }
 
-        ports = gvc_mixer_stream_get_ports (stream);
-        if (ports != NULL) {
-                const GvcMixerStreamPort *port;
-                port = gvc_mixer_stream_get_port (stream);
+        profiles = gvc_mixer_ui_device_get_profiles (device);
+        if (g_list_length ((GList *) profiles) >= 2) {
+                const gchar *active_profile;
 
-                dialog->priv->output_port_combo = gvc_combo_box_new (_("Co_nnector:"));
-                gvc_combo_box_set_ports (GVC_COMBO_BOX (dialog->priv->output_port_combo),
-                                         ports);
-                gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->output_port_combo), port->port);
-                g_object_set_data (G_OBJECT (dialog->priv->output_port_combo), "stream", stream);
-                g_signal_connect (G_OBJECT (dialog->priv->output_port_combo), "changed",
-                                  G_CALLBACK (port_selection_changed), dialog);
+                dialog->priv->output_profile_combo = gvc_combo_box_new (_("_Profile:"));
+                gvc_combo_box_set_profiles (GVC_COMBO_BOX (dialog->priv->output_profile_combo),
+                                            profiles);
 
                 gtk_box_pack_start (GTK_BOX (dialog->priv->output_settings_box),
-                                    dialog->priv->output_port_combo,
+                                    dialog->priv->output_profile_combo,
                                     TRUE, FALSE, 6);
 
                 if (dialog->priv->size_group != NULL) {
-                        gvc_combo_box_set_size_group (GVC_COMBO_BOX (dialog->priv->output_port_combo),
+                        gvc_combo_box_set_size_group (GVC_COMBO_BOX (dialog->priv->output_profile_combo),
                                                       dialog->priv->size_group, FALSE);
                 }
 
-                gtk_widget_show (dialog->priv->output_port_combo);
+                active_profile = gvc_mixer_ui_device_get_active_profile (device);
+                if (active_profile)
+                        gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->output_profile_combo), active_profile);
+
+                g_object_set_data (G_OBJECT (dialog->priv->output_profile_combo),
+                                   "uidevice",
+                                   device);
+                g_signal_connect (G_OBJECT (dialog->priv->output_profile_combo), "changed",
+                                  G_CALLBACK (profile_selection_changed), dialog);
+
+                gtk_widget_show (dialog->priv->output_profile_combo);
         }
 
         /* FIXME: We could make this into a "No settings" label instead */
         gtk_widget_set_sensitive (dialog->priv->output_balance_bar, gvc_channel_map_can_balance (map));
 }
 
-static void
-update_default_output (GvcMixerDialog *dialog)
-{
-        GtkTreeModel *model;
-        GtkTreeIter   iter;
-
-        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
-        gtk_tree_model_get_iter_first (model, &iter);
-        do {
-                gboolean        toggled;
-                gboolean        is_default;
-                guint           id;
-                GvcMixerStream *stream;
-
-                gtk_tree_model_get (model, &iter,
-                                    ID_COLUMN, &id,
-                                    ACTIVE_COLUMN, &toggled,
-                                    -1);
-
-                stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id);
-                if (stream == NULL) {
-                        g_warning ("Unable to find stream for id: %u", id);
-                        continue;
-                }
-
-                is_default = FALSE;
-                if (stream == gvc_mixer_control_get_default_sink (dialog->priv->mixer_control)) {
-                        is_default = TRUE;
-                }
-
-                gtk_list_store_set (GTK_LIST_STORE (model),
-                                    &iter,
-                                    ACTIVE_COLUMN, is_default,
-                                    -1);
-                if (is_default) {
-                        GtkTreeSelection *selection;
-
-                        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->output_treeview));
-                        gtk_tree_selection_select_iter (selection, &iter);
-                }
-        } while (gtk_tree_model_iter_next (model, &iter));
-}
-
-static void
-on_mixer_control_default_sink_changed (GvcMixerControl *control,
-                                       guint            id,
-                                       GvcMixerDialog  *dialog)
-{
-        GvcMixerStream *stream;
-
-        g_debug ("GvcMixerDialog: default sink changed: %u", id);
-
-        if (id == PA_INVALID_INDEX)
-                stream = NULL;
-        else
-                stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control,
-                                                             id);
-        bar_set_stream (dialog, dialog->priv->output_bar, stream);
-
-        update_output_settings (dialog);
-
-        update_default_output (dialog);
-}
-
-
 #define DECAY_STEP .15
 
 static void
@@ -594,23 +470,25 @@ stop_monitor_stream_for_source (GvcMixerDialog *dialog)
 }
 
 static void
-update_input_settings (GvcMixerDialog *dialog)
+update_input_settings (GvcMixerDialog   *dialog,
+                       GvcMixerUIDevice *device)
 {
-        const GList    *ports;
         GvcMixerStream *stream;
+        const GList    *profiles;
         GtkAdjustment  *adj;
 
         g_debug ("Updating input settings");
 
         stop_monitor_stream_for_source (dialog);
 
-        if (dialog->priv->input_port_combo != NULL) {
+        if (dialog->priv->input_profile_combo != NULL) {
                 gtk_container_remove (GTK_CONTAINER (dialog->priv->input_settings_box),
-                                      dialog->priv->input_port_combo);
-                dialog->priv->input_port_combo = NULL;
+                                      dialog->priv->input_profile_combo);
+                dialog->priv->input_profile_combo = NULL;
         }
 
-        stream = gvc_mixer_control_get_default_source (dialog->priv->mixer_control);
+        stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control,
+                                                           device);
         if (stream == NULL) {
                 g_debug ("Default source stream not found");
                 return;
@@ -627,60 +505,37 @@ update_input_settings (GvcMixerDialog *dialog)
 	gtk_adjustment_set_value (adj,
 				  gvc_mixer_stream_get_volume (stream));
 
-        ports = gvc_mixer_stream_get_ports (stream);
-        if (ports != NULL) {
-                const GvcMixerStreamPort *port;
-                port = gvc_mixer_stream_get_port (stream);
+        profiles = gvc_mixer_ui_device_get_profiles (device);
+        if (g_list_length ((GList *) profiles) >= 2) {
+                const gchar *active_profile;
 
-                dialog->priv->input_port_combo = gvc_combo_box_new (_("Co_nnector:"));
-                gvc_combo_box_set_ports (GVC_COMBO_BOX (dialog->priv->input_port_combo),
-                                         ports);
-                gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->input_port_combo), port->port);
-                g_object_set_data (G_OBJECT (dialog->priv->input_port_combo), "stream", stream);
-                g_signal_connect (G_OBJECT (dialog->priv->input_port_combo), "changed",
-                                  G_CALLBACK (port_selection_changed), dialog);
+                dialog->priv->input_profile_combo = gvc_combo_box_new (_("_Profile:"));
+                gvc_combo_box_set_profiles (GVC_COMBO_BOX (dialog->priv->input_profile_combo),
+                                            profiles);
 
-                if (dialog->priv->size_group != NULL) {
-                        gvc_combo_box_set_size_group (GVC_COMBO_BOX (dialog->priv->input_port_combo),
-                                                      dialog->priv->size_group, FALSE);
-                }
                 gtk_box_pack_start (GTK_BOX (dialog->priv->input_settings_box),
-                                    dialog->priv->input_port_combo,
+                                    dialog->priv->input_profile_combo,
                                     TRUE, TRUE, 0);
-                gtk_widget_show (dialog->priv->input_port_combo);
-        }
 
-        create_monitor_stream_for_source (dialog, stream);
-}
-
-static void
-on_mixer_control_default_source_changed (GvcMixerControl *control,
-                                         guint            id,
-                                         GvcMixerDialog  *dialog)
-{
-        GvcMixerStream *stream;
-        GtkAdjustment *adj;
+                if (dialog->priv->size_group != NULL) {
+                        gvc_combo_box_set_size_group (GVC_COMBO_BOX (dialog->priv->input_profile_combo),
+                                                      dialog->priv->size_group, FALSE);
+                }
 
-        g_debug ("GvcMixerDialog: default source changed: %u", id);
+                active_profile = gvc_mixer_ui_device_get_active_profile (device);
+                if (active_profile)
+                        gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->input_profile_combo), active_profile);
 
-        if (id == PA_INVALID_INDEX)
-                stream = NULL;
-        else
-                stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id);
+                g_object_set_data (G_OBJECT (dialog->priv->input_profile_combo),
+                                   "uidevice",
+                                   device);
+                g_signal_connect (G_OBJECT (dialog->priv->input_profile_combo), "changed",
+                                  G_CALLBACK (profile_selection_changed), dialog);
 
-        /* Disconnect the adj, otherwise it might change if is_amplified changes */
-        adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (dialog->priv->input_bar)));
-        g_signal_handlers_disconnect_by_func(adj, on_adjustment_value_changed, dialog);
-
-        bar_set_stream (dialog, dialog->priv->input_bar, stream);
-        update_input_settings (dialog);
-
-        g_signal_connect (adj,
-                          "value-changed",
-                          G_CALLBACK (on_adjustment_value_changed),
-                          dialog);
+                gtk_widget_show (dialog->priv->input_profile_combo);
+        }
 
-        update_default_input (dialog);
+        create_monitor_stream_for_source (dialog, stream);
 }
 
 static void
@@ -694,23 +549,25 @@ gvc_mixer_dialog_set_mixer_control (GvcMixerDialog  *dialog,
 
         if (dialog->priv->mixer_control != NULL) {
                 g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
-                                                      G_CALLBACK (on_mixer_control_default_sink_changed),
+                                                      G_CALLBACK (on_control_active_input_update),
                                                       dialog);
                 g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
-                                                      G_CALLBACK (on_mixer_control_default_source_changed),
+                                                      G_CALLBACK (on_control_active_output_update),
                                                       dialog);
                 g_object_unref (dialog->priv->mixer_control);
         }
 
         dialog->priv->mixer_control = control;
 
+        /* FIXME: Why are some mixer_control signals connected here,
+         * and others in the dialog constructor? (And similar for disconnect) */
         g_signal_connect (dialog->priv->mixer_control,
-                          "default-sink-changed",
-                          G_CALLBACK (on_mixer_control_default_sink_changed),
+                          "active-input-update",
+                          G_CALLBACK (on_control_active_input_update),
                           dialog);
         g_signal_connect (dialog->priv->mixer_control,
-                          "default-source-changed",
-                          G_CALLBACK (on_mixer_control_default_source_changed),
+                          "active-output-update",
+                          G_CALLBACK (on_control_active_output_update),
                           dialog);
 
         g_object_notify (G_OBJECT (dialog), "mixer-control");
@@ -785,7 +642,7 @@ on_adjustment_value_changed (GtkAdjustment  *adjustment,
                 if (volume == 0.0)
                         gvc_mixer_stream_set_is_muted (stream, TRUE);
                 /* Only push the volume if it's actually changed */
-                if (gvc_mixer_stream_set_volume(stream, (pa_volume_t) rounded) != FALSE)
+                if (gvc_mixer_stream_set_volume (stream, (pa_volume_t) rounded) != FALSE)
                         gvc_mixer_stream_push_volume (stream);
         }
 }
@@ -822,70 +679,6 @@ lookup_bar_for_stream (GvcMixerDialog *dialog,
         return bar;
 }
 
-static GtkWidget *
-lookup_combo_box_for_stream (GvcMixerDialog *dialog,
-                             GvcMixerStream *stream)
-{
-        GvcMixerStream *combo_stream;
-        guint id;
-
-        id = gvc_mixer_stream_get_id (stream);
-
-        if (dialog->priv->output_port_combo != NULL) {
-                combo_stream = g_object_get_data (G_OBJECT (dialog->priv->output_port_combo),
-                                                  "stream");
-                if (combo_stream != NULL) {
-                        if (id == gvc_mixer_stream_get_id (combo_stream))
-                                return dialog->priv->output_port_combo;
-                }
-        }
-
-        if (dialog->priv->input_port_combo != NULL) {
-                combo_stream = g_object_get_data (G_OBJECT (dialog->priv->input_port_combo),
-                                                  "stream");
-                if (combo_stream != NULL) {
-                        if (id == gvc_mixer_stream_get_id (combo_stream))
-                                return dialog->priv->input_port_combo;
-                }
-        }
-
-        return NULL;
-}
-
-static void
-on_stream_description_notify (GvcMixerStream *stream,
-                              GParamSpec     *pspec,
-                              GvcMixerDialog *dialog)
-{
-        update_description (dialog, NAME_COLUMN,
-                            gvc_mixer_stream_get_description (stream),
-                            stream);
-}
-
-static void
-on_stream_port_notify (GObject        *object,
-                       GParamSpec     *pspec,
-                       GvcMixerDialog *dialog)
-{
-        GvcComboBox *combo_box;
-        char *port;
-
-        combo_box = GVC_COMBO_BOX (lookup_combo_box_for_stream (dialog, GVC_MIXER_STREAM (object)));
-        if (combo_box == NULL)
-                return;
-
-        g_signal_handlers_block_by_func (G_OBJECT (combo_box),
-                                         port_selection_changed,
-                                         dialog);
-
-        g_object_get (object, "port", &port, NULL);
-        gvc_combo_box_set_active (GVC_COMBO_BOX (combo_box), port);
-
-        g_signal_handlers_unblock_by_func (G_OBJECT (combo_box),
-                                         port_selection_changed,
-                                         dialog);
-}
-
 static void
 on_stream_volume_notify (GObject        *object,
                          GParamSpec     *pspec,
@@ -1008,6 +801,124 @@ create_app_bar (GvcMixerDialog *dialog,
         return bar;
 }
 
+/* active_input_update
+ * Handle input update change from the backend (control).
+ * Trust the backend whole-heartedly to deliver the correct input. */
+static void
+active_input_update (GvcMixerDialog *dialog,
+                     GvcMixerUIDevice *active_input)
+{
+        /* First make sure the correct UI device is selected. */
+        GtkTreeModel   *model;
+        GtkTreeIter     iter;
+        GvcMixerStream *stream;
+
+        g_debug ("active_input_update device id = %i",
+                 gvc_mixer_ui_device_get_id (active_input));
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
+                g_warning ("No devices in the tree, so cannot set the active output");
+                return;
+        }
+
+        do {
+                gboolean         is_selected = FALSE;
+                gint             id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ID_COLUMN, &id,
+                                    -1);
+
+                is_selected = id == gvc_mixer_ui_device_get_id (active_input);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ACTIVE_COLUMN, is_selected,
+                                    -1);
+
+                if (is_selected) {
+                        GtkTreeSelection *selection;
+                        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->input_treeview));
+                        gtk_tree_selection_select_iter (selection, &iter);
+                }
+        } while (gtk_tree_model_iter_next (model, &iter));
+
+        stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control,
+                                                           active_input);
+        if (stream == NULL) {
+                g_warning ("Couldn't find a stream from the active input");
+                gtk_widget_set_sensitive (dialog->priv->input_bar, FALSE);
+                return;
+        }
+
+        bar_set_stream (dialog, dialog->priv->input_bar, stream);
+        update_input_settings (dialog, active_input);
+
+}
+
+/* active_output_update
+ * Handle output update change from the backend (control).
+ * Trust the backend whole heartedly to deliver the correct output. */
+static void
+active_output_update (GvcMixerDialog   *dialog,
+                      GvcMixerUIDevice *active_output)
+{
+        /* First make sure the correct UI device is selected. */
+        GvcMixerStream *stream;
+        GtkTreeModel   *model;
+        GtkTreeIter     iter;
+
+        g_debug ("active output update device id = %i",
+                 gvc_mixer_ui_device_get_id (active_output));
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
+
+        if (gtk_tree_model_get_iter_first (model, &iter) == FALSE){
+                g_warning ("No devices in the tree, so cannot set the active output");
+                return;
+        }
+
+        do {
+                gboolean         is_selected;
+                gint             id;
+
+                gtk_tree_model_get (model, &iter,
+                                    ID_COLUMN, &id,
+                                    ACTIVE_COLUMN, &is_selected,
+                                    -1);
+
+                if (is_selected && id == gvc_mixer_ui_device_get_id (active_output)) {
+                        /* XXX: profile change on the same device? */
+                        g_debug ("Unneccessary active output update");
+                }
+
+                is_selected = id == gvc_mixer_ui_device_get_id (active_output);
+
+                gtk_list_store_set (GTK_LIST_STORE (model),
+                                    &iter,
+                                    ACTIVE_COLUMN, is_selected,
+                                    -1);
+
+                if (is_selected) {
+                        GtkTreeSelection *selection;
+                        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->output_treeview));
+                        gtk_tree_selection_select_iter (selection, &iter);
+                }
+        } while (gtk_tree_model_iter_next (model, &iter));
+
+        stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control,
+                                                           active_output);
+        if (stream == NULL) {
+                g_warning ("Couldn't find a stream from the active output");
+                return;
+        }
+
+        bar_set_stream (dialog, dialog->priv->output_bar, stream);
+        update_output_settings (dialog, active_output);
+}
+
 static void
 bar_set_stream (GvcMixerDialog *dialog,
                 GtkWidget      *bar,
@@ -1029,7 +940,6 @@ bar_set_stream (GvcMixerDialog *dialog,
 
                 g_signal_handlers_disconnect_by_func (old_stream, on_stream_is_muted_notify, dialog);
                 g_signal_handlers_disconnect_by_func (old_stream, on_stream_volume_notify, dialog);
-                g_signal_handlers_disconnect_by_func (old_stream, on_stream_port_notify, dialog);
                 g_hash_table_remove (dialog->priv->bars, GUINT_TO_POINTER (gvc_mixer_stream_get_id (old_stream)));
         }
 
@@ -1049,8 +959,6 @@ bar_set_stream (GvcMixerDialog *dialog,
                 is_muted = gvc_mixer_stream_get_is_muted (stream);
                 gvc_channel_bar_set_is_muted (GVC_CHANNEL_BAR (bar), is_muted);
 
-                save_bar_for_stream (dialog, stream, bar);
-
                 gtk_adjustment_set_value (adj,
                                           gvc_mixer_stream_get_volume (stream));
 
@@ -1062,10 +970,6 @@ bar_set_stream (GvcMixerDialog *dialog,
                                   "notify::volume",
                                   G_CALLBACK (on_stream_volume_notify),
                                   dialog);
-                g_signal_connect (stream,
-                                  "notify::port",
-                                  G_CALLBACK (on_stream_port_notify),
-                                  dialog);
                 g_signal_connect (adj,
                                   "value-changed",
                                   G_CALLBACK (on_adjustment_value_changed),
@@ -1077,120 +981,47 @@ static void
 add_stream (GvcMixerDialog *dialog,
             GvcMixerStream *stream)
 {
-        GtkWidget     *bar;
-        gboolean       is_muted;
-        gboolean       is_default;
-        GtkAdjustment *adj;
-        const char    *id;
-
-        g_assert (stream != NULL);
-
-        if (gvc_mixer_stream_is_event_stream (stream) != FALSE)
-                return;
+        GtkWidget      *bar;
+        GvcMixerStream *old_stream;
 
         bar = NULL;
-        is_default = FALSE;
-        id = gvc_mixer_stream_get_application_id (stream);
 
-        if (stream == gvc_mixer_control_get_default_sink (dialog->priv->mixer_control)) {
-                bar = dialog->priv->output_bar;
-                is_muted = gvc_mixer_stream_get_is_muted (stream);
-                is_default = TRUE;
-                gtk_widget_set_sensitive (dialog->priv->applications_box,
-                                          !is_muted);
-                adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (bar)));
-                g_signal_handlers_disconnect_by_func(adj, on_adjustment_value_changed, dialog);
-                update_output_settings (dialog);
-        } else if (stream == gvc_mixer_control_get_default_source (dialog->priv->mixer_control)) {
-                bar = dialog->priv->input_bar;
-                adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (bar)));
-                g_signal_handlers_disconnect_by_func(adj, on_adjustment_value_changed, dialog);
-                update_input_settings (dialog);
-                is_default = TRUE;
-        } else if (stream == gvc_mixer_control_get_event_sink_input (dialog->priv->mixer_control)) {
+        if (GVC_IS_MIXER_SOURCE (stream) || GVC_IS_MIXER_SINK (stream))
+                return;
+        else if (stream == gvc_mixer_control_get_event_sink_input (dialog->priv->mixer_control)) {
                 bar = dialog->priv->effects_bar;
                 g_debug ("Adding effects stream");
-        } else if (! GVC_IS_MIXER_SOURCE (stream)
-                   && !GVC_IS_MIXER_SINK (stream)
-                   && !gvc_mixer_stream_is_virtual (stream)
-                   && g_strcmp0 (id, "org.gnome.VolumeControl") != 0
-                   && g_strcmp0 (id, "org.PulseAudio.pavucontrol") != 0) {
+        } else {
+                /* Must be an application stream */
                 const char *name;
-
                 name = gvc_mixer_stream_get_name (stream);
+                g_debug ("Add bar for application stream : %s", name);
+
                 bar = create_app_bar (dialog, name,
                                       gvc_mixer_stream_get_icon_name (stream));
-
                 gtk_box_pack_start (GTK_BOX (dialog->priv->applications_box), bar, FALSE, FALSE, 12);
                 dialog->priv->num_apps++;
                 gtk_widget_hide (dialog->priv->no_apps_label);
         }
 
-        if (GVC_IS_MIXER_SOURCE (stream)) {
-                GtkTreeModel *model;
-                GtkTreeIter   iter;
-                GIcon        *icon;
-
-                model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
-                gtk_list_store_append (GTK_LIST_STORE (model), &iter);
-
-                icon = gvc_mixer_stream_get_gicon (stream);
-                gtk_list_store_set (GTK_LIST_STORE (model),
-                                    &iter,
-                                    NAME_COLUMN, gvc_mixer_stream_get_description (stream),
-                                    DEVICE_COLUMN, "",
-                                    ACTIVE_COLUMN, is_default,
-                                    ICON_COLUMN, icon,
-                                    ID_COLUMN, gvc_mixer_stream_get_id (stream),
-                                    -1);
-                if (icon != NULL)
-                        g_object_unref (icon);
-
-                if (is_default) {
-                        GtkTreeSelection *selection;
-
-                        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->input_treeview));
-                        gtk_tree_selection_select_iter (selection, &iter);
-                }
-
-                g_signal_connect (stream,
-                                  "notify::description",
-                                  G_CALLBACK (on_stream_description_notify),
-                                  dialog);
-        } else if (GVC_IS_MIXER_SINK (stream)) {
-                GtkTreeModel        *model;
-                GtkTreeIter          iter;
-                GIcon               *icon;
-
-                model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
-                gtk_list_store_append (GTK_LIST_STORE (model), &iter);
-
-                icon = gvc_mixer_stream_get_gicon (stream);
-                gtk_list_store_set (GTK_LIST_STORE (model),
-                                    &iter,
-                                    NAME_COLUMN, gvc_mixer_stream_get_description (stream),
-                                    DEVICE_COLUMN, "",
-                                    ACTIVE_COLUMN, is_default,
-                                    ICON_COLUMN, icon,
-                                    ID_COLUMN, gvc_mixer_stream_get_id (stream),
-                                    -1);
-                if (icon != NULL)
-                        g_object_unref (icon);
-
-                if (is_default) {
-                        GtkTreeSelection *selection;
-
-                        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->output_treeview));
-                        gtk_tree_selection_select_iter (selection, &iter);
-                }
-
-                g_signal_connect (stream,
-                                  "notify::description",
-                                  G_CALLBACK (on_stream_description_notify),
-                                  dialog);
-        }
+        /* We should have a bar by now. */
+        g_assert (bar != NULL);
 
         if (bar != NULL) {
+                old_stream = g_object_get_data (G_OBJECT (bar), "gvc-mixer-dialog-stream");
+                if (old_stream != NULL) {
+                        char *name;
+
+                        g_object_get (bar, "name", &name, NULL);
+                        g_debug ("Disconnecting old stream '%s' from bar '%s'",
+                                 gvc_mixer_stream_get_name (old_stream), name);
+                        g_free (name);
+
+                        g_signal_handlers_disconnect_by_func (old_stream, on_stream_is_muted_notify, dialog);
+                        g_signal_handlers_disconnect_by_func (old_stream, on_stream_volume_notify, dialog);
+                        g_hash_table_remove (dialog->priv->bars, GUINT_TO_POINTER (gvc_mixer_stream_get_id (old_stream)));
+                }
+                save_bar_for_stream (dialog, stream, bar);
                 bar_set_stream (dialog, bar, stream);
                 gtk_widget_show (bar);
         }
@@ -1202,16 +1033,27 @@ on_control_stream_added (GvcMixerControl *control,
                          GvcMixerDialog  *dialog)
 {
         GvcMixerStream *stream;
-        GtkWidget      *bar;
+        const char     *app_id;
 
-        bar = g_hash_table_lookup (dialog->priv->bars, GUINT_TO_POINTER (id));
-        if (bar != NULL) {
-                g_debug ("GvcMixerDialog: Stream %u already added", id);
+        stream = gvc_mixer_control_lookup_stream_id (control, id);
+        if (stream == NULL)
                 return;
-        }
 
-        stream = gvc_mixer_control_lookup_stream_id (control, id);
-        if (stream != NULL) {
+        app_id = gvc_mixer_stream_get_application_id (stream);
+
+        if (stream == gvc_mixer_control_get_event_sink_input (dialog->priv->mixer_control) ||
+            (GVC_IS_MIXER_SOURCE (stream) == FALSE &&
+             GVC_IS_MIXER_SINK (stream) == FALSE &&
+             gvc_mixer_stream_is_virtual (stream) == FALSE &&
+             g_strcmp0 (app_id, "org.gnome.VolumeControl") != 0 &&
+             g_strcmp0 (app_id, "org.PulseAudio.pavucontrol") != 0)) {
+                GtkWidget      *bar;
+
+                bar = g_hash_table_lookup (dialog->priv->bars, GUINT_TO_POINTER (id));
+                if (bar != NULL) {
+                        g_debug ("GvcMixerDialog: Stream %u already added", id);
+                        return;
+                }
                 add_stream (dialog, stream);
         }
 }
@@ -1245,41 +1087,254 @@ find_item_by_id (GtkTreeModel *model,
 }
 
 static void
-remove_stream (GvcMixerDialog  *dialog,
-               guint            id)
+add_input_ui_entry (GvcMixerDialog *dialog,
+                    GvcMixerUIDevice *input)
 {
-        GtkWidget    *bar;
-        gboolean      found;
-        GtkTreeIter   iter;
-        GtkTreeModel *model;
+        gchar               *final_name;
+        gchar               *port_name;
+        gchar               *origin;
+        gchar               *description;
+        gboolean             available;
+        gint                 stream_id;
+        GtkTreeModel        *model;
+        GtkTreeIter          iter;
+        GIcon               *icon;
+        GvcMixerCard        *card;
 
-        /* remove bars for applications and reset fixed bars */
-        bar = g_hash_table_lookup (dialog->priv->bars, GUINT_TO_POINTER (id));
-        if (bar == dialog->priv->output_bar
-            || bar == dialog->priv->input_bar
-            || bar == dialog->priv->effects_bar) {
-                char *name;
-                g_object_get (bar, "name", &name, NULL);
-                g_debug ("Removing stream for bar '%s'", name);
-                g_free (name);
-                bar_set_stream (dialog, bar, NULL);
-        } else if (bar != NULL) {
-                g_hash_table_remove (dialog->priv->bars, GUINT_TO_POINTER (id));
-                gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (bar)),
-                                      bar);
-                dialog->priv->num_apps--;
-                if (dialog->priv->num_apps == 0) {
-                        gtk_widget_show (dialog->priv->no_apps_label);
+        g_debug ("Add input ui entry with id :%u",
+                  gvc_mixer_ui_device_get_id (input));
+
+        g_object_get (G_OBJECT (input),
+                     "stream-id", &stream_id,
+                     "card", &card,
+                     "origin", &origin,
+                     "description", &description,
+                     "port-name", &port_name,
+                     "port-available", &available,
+                      NULL);
+
+        if (origin && origin[0] != '\0')
+                final_name = g_strdup_printf ("%s - %s", description, origin);
+        else
+                final_name = g_strdup (description);
+
+        g_free (port_name);
+        g_free (origin);
+        g_free (description);
+
+        if (card == NULL) {
+                GvcMixerStream *stream;
+                g_debug ("just detected a network source");
+                stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control, input);
+                if (stream == NULL) {
+                        g_warning ("tried to add the network source but the stream was null - fail ?!");
+                        g_free (final_name);
+                        return;
+                }
+                icon = gvc_mixer_stream_get_gicon (stream);
+        } else
+                icon = gvc_mixer_card_get_gicon (card);
+
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
+        gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+
+        gtk_list_store_set (GTK_LIST_STORE (model),
+                            &iter,
+                            NAME_COLUMN, final_name,
+                            DEVICE_COLUMN, "",
+                            ACTIVE_COLUMN, FALSE,
+                            ICON_COLUMN, icon,
+                            ID_COLUMN, gvc_mixer_ui_device_get_id (input),
+                            -1);
+
+        if (icon != NULL)
+                g_object_unref (icon);
+        g_free (final_name);
+}
+
+static void
+add_output_ui_entry (GvcMixerDialog   *dialog,
+                     GvcMixerUIDevice *output)
+{
+        gchar         *sink_port_name;
+        gchar         *origin;
+        gchar         *description;
+        gchar         *final_name;
+        gboolean       available;
+        gint           sink_stream_id;
+        GtkTreeModel  *model;
+        GtkTreeIter    iter;
+        GIcon         *icon;
+        GvcMixerCard  *card;
+
+        g_debug ("Add output ui entry with id :%u",
+                  gvc_mixer_ui_device_get_id (output));
+
+        g_object_get (G_OBJECT (output),
+                     "stream-id", &sink_stream_id,
+                     "card", &card,
+                     "origin", &origin,
+                     "description", &description,
+                     "port-name", &sink_port_name,
+                     "port-available", &available,
+                      NULL);
+
+        if (origin && origin[0] != '\0')
+                final_name = g_strdup_printf ("%s - %s", description, origin);
+        else
+                final_name = g_strdup (description);
+
+        g_free (sink_port_name);
+        g_free (origin);
+        g_free (description);
+
+        if (card == NULL) {
+                GvcMixerStream *stream;
+
+                g_debug ("just detected a network sink");
+                stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control, output);
+
+                if (stream == NULL) {
+                        g_warning ("tried to add the network sink but the stream was null - fail ?!");
+                        g_free (final_name);
+                        return;
                 }
+                icon = gvc_mixer_stream_get_gicon (stream);
+        } else
+                icon = gvc_mixer_card_get_gicon (card);
+
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
+        gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+
+        gtk_list_store_set (GTK_LIST_STORE (model),
+                            &iter,
+                            NAME_COLUMN, final_name,
+                            DEVICE_COLUMN, "",
+                            ACTIVE_COLUMN, FALSE,
+                            ICON_COLUMN, icon,
+                            ID_COLUMN, gvc_mixer_ui_device_get_id (output),
+                            -1);
+
+        if (icon != NULL)
+                g_object_unref (icon);
+        g_free (final_name);
+}
+
+
+static void
+on_control_active_input_update (GvcMixerControl *control,
+                                guint            id,
+                                GvcMixerDialog  *dialog)
+{
+        GvcMixerUIDevice* in = NULL;
+        in = gvc_mixer_control_lookup_input_id (control, id);
+
+        if (in == NULL) {
+                g_warning ("on_control_active_input_update - tried to fetch an input of id %u but got nothing", id);
+                return;
         }
+        active_input_update (dialog, in);
+}
+
+static void
+on_control_active_output_update (GvcMixerControl *control,
+                                 guint            id,
+                                 GvcMixerDialog  *dialog)
+{
+        GvcMixerUIDevice* out = NULL;
+        out = gvc_mixer_control_lookup_output_id (control, id);
+
+        if (out == NULL) {
+                g_warning ("on_control_active_output_update - tried to fetch an output of id %u but got nothing", id);
+                return;
+        }
+        active_output_update (dialog, out);
+}
+
+static void
+on_control_input_added (GvcMixerControl *control,
+                        guint            id,
+                        GvcMixerDialog  *dialog)
+{
+        GvcMixerUIDevice* in = NULL;
+        in = gvc_mixer_control_lookup_input_id (control, id);
+
+        if (in == NULL) {
+                g_warning ("on_control_input_added - tried to fetch an input of id %u but got nothing", id);
+                return;
+        }
+        add_input_ui_entry (dialog, in);
+}
+
+static void
+on_control_input_removed (GvcMixerControl *control,
+                          guint           id,
+                          GvcMixerDialog  *dialog)
+{
+        gboolean          found;
+        GtkTreeIter       iter;
+        GtkTreeModel     *model;
+        gint              stream_id;
+        GvcMixerUIDevice *in;
+
+        in = gvc_mixer_control_lookup_input_id (control, id);
+
+        g_object_get (G_OBJECT (in),
+                     "stream-id", &stream_id,
+                      NULL);
+
+        g_debug ("Remove input from dialog, id: %u, stream id: %i",
+                 id,
+                 stream_id);
 
         /* remove from any models */
-        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
         found = find_item_by_id (GTK_TREE_MODEL (model), id, ID_COLUMN, &iter);
         if (found) {
                 gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
         }
-        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
+}
+
+static void
+on_control_output_added (GvcMixerControl *control,
+                         guint            id,
+                         GvcMixerDialog  *dialog)
+{
+        GvcMixerUIDevice* out = NULL;
+        out = gvc_mixer_control_lookup_output_id (control, id);
+
+        if (out == NULL) {
+                g_warning ("on_control_output_added - tried to fetch an output of id %u but got nothing", id);
+                return;
+        }
+
+        add_output_ui_entry (dialog, out);
+}
+
+static void
+on_control_output_removed (GvcMixerControl *control,
+                           guint           id,
+                           GvcMixerDialog  *dialog)
+{
+        gboolean      found;
+        GtkTreeIter   iter;
+        GtkTreeModel *model;
+        gint          sink_stream_id;
+
+        GvcMixerUIDevice* out = NULL;
+        out = gvc_mixer_control_lookup_output_id (control, id);
+
+        g_object_get (G_OBJECT (out),
+                     "stream-id", &sink_stream_id,
+                      NULL);
+
+        g_debug ("Remove output from dialog \n id : %u \n sink stream id : %i \n",
+                  id,
+                  sink_stream_id);
+
+         /* remove from any models */
+        model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
         found = find_item_by_id (GTK_TREE_MODEL (model), id, ID_COLUMN, &iter);
         if (found) {
                 gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
@@ -1287,6 +1342,23 @@ remove_stream (GvcMixerDialog  *dialog,
 }
 
 static void
+remove_stream (GvcMixerDialog  *dialog,
+               guint            id)
+{
+        GtkWidget *bar;
+        bar = g_hash_table_lookup (dialog->priv->bars, GUINT_TO_POINTER (id));
+        if (bar != NULL) {
+                g_hash_table_remove (dialog->priv->bars, GUINT_TO_POINTER (id));
+                gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (bar)),
+                                      bar);
+                dialog->priv->num_apps--;
+                if (dialog->priv->num_apps == 0) {
+                        gtk_widget_show (dialog->priv->no_apps_label);
+                }
+        }
+}
+
+static void
 on_control_stream_removed (GvcMixerControl *control,
                            guint            id,
                            GvcMixerDialog  *dialog)
@@ -1404,10 +1476,11 @@ static void
 on_input_selection_changed (GtkTreeSelection *selection,
                             GvcMixerDialog   *dialog)
 {
-        GtkTreeModel *model;
-        GtkTreeIter   iter;
-        gboolean      toggled;
-        guint         id;
+        GtkTreeModel     *model;
+        GtkTreeIter       iter;
+        gboolean          active;
+        guint             id;
+        GvcMixerUIDevice *input;
 
         if (gtk_tree_selection_get_selected (selection, &model, &iter) == FALSE) {
                 g_debug ("Could not get default input from selection");
@@ -1416,32 +1489,28 @@ on_input_selection_changed (GtkTreeSelection *selection,
 
         gtk_tree_model_get (model, &iter,
                             ID_COLUMN, &id,
-                            ACTIVE_COLUMN, &toggled,
+                            ACTIVE_COLUMN, &active,
                             -1);
 
-        toggled ^= 1;
-        if (toggled) {
-                GvcMixerStream *stream;
-
-                g_debug ("Default input selected: %u", id);
-                stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id);
-                if (stream == NULL) {
-                        g_warning ("Unable to find stream for id: %u", id);
-                        return;
-                }
+        input = gvc_mixer_control_lookup_input_id (dialog->priv->mixer_control, id);
 
-                gvc_mixer_control_set_default_source (dialog->priv->mixer_control, stream);
+        if (input == NULL) {
+                g_warning ("on_input_selection_changed - Unable to find input with id: %u", id);
+                return;
         }
+
+        gvc_mixer_control_change_input (dialog->priv->mixer_control, input);
 }
 
 static void
 on_output_selection_changed (GtkTreeSelection *selection,
                              GvcMixerDialog   *dialog)
 {
-        GtkTreeModel *model;
-        GtkTreeIter   iter;
-        gboolean      toggled;
-        guint         id;
+        GtkTreeModel     *model;
+        GtkTreeIter       iter;
+        gboolean          active;
+        guint             id;
+        GvcMixerUIDevice *output;
 
         if (gtk_tree_selection_get_selected (selection, &model, &iter) == FALSE) {
                 g_debug ("Could not get default output from selection");
@@ -1450,27 +1519,26 @@ on_output_selection_changed (GtkTreeSelection *selection,
 
         gtk_tree_model_get (model, &iter,
                             ID_COLUMN, &id,
-                            ACTIVE_COLUMN, &toggled,
+                            ACTIVE_COLUMN, &active,
                             -1);
 
-        toggled ^= 1;
-        if (toggled) {
-                GvcMixerStream *stream;
+        g_debug ("on_output_selection_changed() stream id: %u, active %i", id, active);
+        if (active)
+                return;
 
-                g_debug ("Default output selected: %u", id);
-                stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id);
-                if (stream == NULL) {
-                        g_warning ("Unable to find stream for id: %u", id);
-                        return;
-                }
+        output = gvc_mixer_control_lookup_output_id (dialog->priv->mixer_control, id);
 
-                gvc_mixer_control_set_default_sink (dialog->priv->mixer_control, stream);
+        if (output == NULL) {
+                g_warning ("Unable to find output with id: %u", id);
+                return;
         }
+
+        gvc_mixer_control_change_output (dialog->priv->mixer_control, output);
 }
 
 static GtkWidget *
-create_stream_treeview (GvcMixerDialog *dialog,
-                        GCallback       on_selection_changed)
+create_ui_device_treeview (GvcMixerDialog *dialog,
+                           GCallback       on_selection_changed)
 {
         GtkWidget         *treeview;
         GtkListStore      *store;
@@ -1781,8 +1849,8 @@ gvc_mixer_dialog_constructor (GType                  type,
         gtk_container_add (GTK_CONTAINER (box), alignment);
         gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 0, 0);
 
-        self->priv->output_treeview = create_stream_treeview (self,
-                                                              G_CALLBACK (on_output_selection_changed));
+        self->priv->output_treeview = create_ui_device_treeview (self,
+                                                                 G_CALLBACK (on_output_selection_changed));
         gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->priv->output_treeview);
 
         box = gtk_scrolled_window_new (NULL, NULL);
@@ -1875,8 +1943,8 @@ gvc_mixer_dialog_constructor (GType                  type,
         gtk_container_add (GTK_CONTAINER (box), alignment);
         gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 0, 0);
 
-        self->priv->input_treeview = create_stream_treeview (self,
-                                                             G_CALLBACK (on_input_selection_changed));
+        self->priv->input_treeview = create_ui_device_treeview (self,
+                                                                G_CALLBACK (on_input_selection_changed));
         gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->priv->input_treeview);
 
         box = gtk_scrolled_window_new (NULL, NULL);
@@ -1965,6 +2033,23 @@ gvc_mixer_dialog_constructor (GType                  type,
                             TRUE, TRUE, 0);
 
         g_signal_connect (self->priv->mixer_control,
+                          "output-added",
+                          G_CALLBACK (on_control_output_added),
+                          self);
+        g_signal_connect (self->priv->mixer_control,
+                          "output-removed",
+                          G_CALLBACK (on_control_output_removed),
+                          self);
+        g_signal_connect (self->priv->mixer_control,
+                          "input-added",
+                          G_CALLBACK (on_control_input_added),
+                          self);
+        g_signal_connect (self->priv->mixer_control,
+                          "input-removed",
+                          G_CALLBACK (on_control_input_removed),
+                          self);
+
+        g_signal_connect (self->priv->mixer_control,
                           "stream-added",
                           G_CALLBACK (on_control_stream_added),
                           self);
@@ -2006,6 +2091,25 @@ gvc_mixer_dialog_dispose (GObject *object)
         GvcMixerDialog *dialog = GVC_MIXER_DIALOG (object);
 
         if (dialog->priv->mixer_control != NULL) {
+
+                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
+                                                      on_control_output_added,
+                                                      dialog);
+                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
+                                                      on_control_output_removed,
+                                                      dialog);
+                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
+                                                      on_control_input_added,
+                                                      dialog);
+                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
+                                                      on_control_input_removed,
+                                                      dialog);
+                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
+                                                      on_control_active_input_update,
+                                                      dialog);
+                g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
+                                                      on_control_active_output_update,
+                                                      dialog);
                 g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
                                                       on_control_stream_added,
                                                       dialog);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]