[gnome-media] Add UI support for profile switching
- From: Bastien Nocera <hadess src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnome-media] Add UI support for profile switching
- Date: Thu, 23 Jul 2009 15:31:40 +0000 (UTC)
commit 86d55bd74fb885ca285c98aeab0d3e2bf2e42535
Author: Bastien Nocera <hadess hadess net>
Date: Thu Jul 23 16:30:25 2009 +0100
Add UI support for profile switching
gnome-volume-control/src/gvc-mixer-dialog.c | 336 ++++++++++++++++++++++++++-
1 files changed, 330 insertions(+), 6 deletions(-)
---
diff --git a/gnome-volume-control/src/gvc-mixer-dialog.c b/gnome-volume-control/src/gvc-mixer-dialog.c
index 6f8d927..8736c82 100644
--- a/gnome-volume-control/src/gvc-mixer-dialog.c
+++ b/gnome-volume-control/src/gvc-mixer-dialog.c
@@ -34,6 +34,7 @@
#include "gvc-channel-bar.h"
#include "gvc-balance-bar.h"
#include "gvc-mixer-control.h"
+#include "gvc-mixer-card.h"
#include "gvc-mixer-sink.h"
#include "gvc-mixer-source.h"
#include "gvc-mixer-source-output.h"
@@ -56,6 +57,10 @@ struct GvcMixerDialogPrivate
GtkWidget *effects_bar;
GtkWidget *output_stream_box;
GtkWidget *sound_effects_box;
+ GtkWidget *hw_box;
+ GtkWidget *hw_treeview;
+ GtkWidget *hw_settings_box;
+ GtkWidget *hw_profile_combo;
GtkWidget *input_box;
GtkWidget *output_box;
GtkWidget *applications_box;
@@ -85,6 +90,16 @@ enum {
NUM_COLUMNS
};
+enum {
+ HW_ID_COLUMN,
+ HW_ICON_COLUMN,
+ HW_NAME_COLUMN,
+ HW_STATUS_COLUMN,
+ HW_PROFILE_COLUMN,
+ HW_PROFILE_HUMAN_COLUMN,
+ HW_NUM_COLUMNS
+};
+
enum
{
PROP_0,
@@ -831,8 +846,9 @@ on_control_stream_added (GvcMixerControl *control,
}
static gboolean
-find_stream_by_id (GtkTreeModel *model,
+find_item_by_id (GtkTreeModel *model,
guint id,
+ guint column,
GtkTreeIter *iter)
{
gboolean found_item;
@@ -847,7 +863,7 @@ find_stream_by_id (GtkTreeModel *model,
guint t_id;
gtk_tree_model_get (model, iter,
- ID_COLUMN, &t_id, -1);
+ column, &t_id, -1);
if (id == t_id) {
found_item = TRUE;
@@ -885,12 +901,12 @@ remove_stream (GvcMixerDialog *dialog,
/* remove from any models */
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
- found = find_stream_by_id (GTK_TREE_MODEL (model), id, &iter);
+ 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));
- found = find_stream_by_id (GTK_TREE_MODEL (model), id, &iter);
+ found = find_item_by_id (GTK_TREE_MODEL (model), id, ID_COLUMN, &iter);
if (found) {
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
}
@@ -905,6 +921,71 @@ on_control_stream_removed (GvcMixerControl *control,
}
static void
+add_card (GvcMixerDialog *dialog,
+ GvcMixerCard *card)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GvcMixerCardProfile *profile;
+ GIcon *icon;
+ guint index;
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview));
+ index = gvc_mixer_card_get_index (card);
+ if (find_item_by_id (GTK_TREE_MODEL (model), index, HW_ID_COLUMN, &iter) == FALSE)
+ gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+ profile = gvc_mixer_card_get_profile (card);
+ g_assert (profile != NULL);
+ icon = g_themed_icon_new_with_default_fallbacks (gvc_mixer_card_get_icon_name (card));
+ //FIXME we need the status (default for a profile?) here
+ gtk_list_store_set (GTK_LIST_STORE (model),
+ &iter,
+ HW_NAME_COLUMN, gvc_mixer_card_get_name (card),
+ HW_ID_COLUMN, index,
+ HW_ICON_COLUMN, icon,
+ HW_PROFILE_COLUMN, profile->profile,
+ HW_PROFILE_HUMAN_COLUMN, profile->human_profile,
+ HW_STATUS_COLUMN, "Ready",
+ -1);
+}
+
+static void
+on_control_card_added (GvcMixerControl *control,
+ guint id,
+ GvcMixerDialog *dialog)
+{
+ GvcMixerCard *card;
+
+ card = gvc_mixer_control_lookup_card_id (control, id);
+ if (card != NULL) {
+ add_card (dialog, card);
+ }
+}
+
+static void
+remove_card (GvcMixerDialog *dialog,
+ guint id)
+{
+ gboolean found;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+
+ /* remove from any models */
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview));
+ found = find_item_by_id (GTK_TREE_MODEL (model), id, HW_ID_COLUMN, &iter);
+ if (found) {
+ gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
+ }
+}
+static void
+on_control_card_removed (GvcMixerControl *control,
+ guint id,
+ GvcMixerDialog *dialog)
+{
+ remove_card (dialog, id);
+}
+
+static void
_gtk_label_make_bold (GtkLabel *label)
{
PangoFontDescription *font_desc;
@@ -1017,7 +1098,7 @@ name_to_text (GtkTreeViewColumn *column,
} else {
char *str;
- str = g_strdup_printf ("%s\n\t<i>%s</i>",
+ str = g_strdup_printf ("%s\n<i>%s</i>",
name, mapping);
g_object_set (cell, "markup", str, NULL);
g_free (str);
@@ -1027,7 +1108,6 @@ name_to_text (GtkTreeViewColumn *column,
g_free (mapping);
}
-
static GtkWidget *
create_stream_treeview (GvcMixerDialog *dialog,
GCallback on_toggled)
@@ -1077,6 +1157,187 @@ create_stream_treeview (GvcMixerDialog *dialog,
return treeview;
}
+enum {
+ PROFILE_NAME,
+ PROFILE_HUMAN_NAME,
+ PROFILE_NUM_COLS
+};
+
+static void
+on_profile_changed (GtkComboBox *widget,
+ gpointer user_data)
+{
+ GtkTreeModel *model;
+ GvcMixerDialog *dialog = GVC_MIXER_DIALOG (user_data);
+ GvcMixerCard *card;
+ GtkTreeIter iter;
+ char *profile;
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->priv->hw_profile_combo));
+
+ card = g_object_get_data (G_OBJECT (dialog->priv->hw_profile_combo), "card");
+ if (card == NULL) {
+ g_warning ("Could not find card for combobox");
+ return;
+ }
+
+ if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (dialog->priv->hw_profile_combo), &iter) == FALSE) {
+ g_warning ("Could not find an active profile");
+ return;
+ }
+
+ gtk_tree_model_get (model, &iter,
+ PROFILE_NAME, &profile,
+ -1);
+ gvc_mixer_card_change_profile (card, profile);
+ g_free (profile);
+}
+
+static void
+on_card_selection_changed (GtkTreeSelection *selection,
+ gpointer user_data)
+{
+ GvcMixerDialog *dialog = GVC_MIXER_DIALOG (user_data);
+ GtkTreeModel *model, *profile_model;
+ GtkTreeIter iter;
+ const GList *profiles, *l;
+ guint id, i, current_index;
+ GvcMixerCard *card;
+ GvcMixerCardProfile *current_profile;
+ GtkCellRenderer *renderer;
+
+ g_debug ("Card selection changed");
+
+ if (dialog->priv->hw_profile_combo != NULL) {
+ gtk_container_remove (GTK_CONTAINER (dialog->priv->hw_settings_box),
+ dialog->priv->hw_profile_combo);
+ gtk_widget_destroy (dialog->priv->hw_profile_combo);
+ dialog->priv->hw_profile_combo = NULL;
+ }
+
+ if (gtk_tree_selection_get_selected (selection,
+ NULL,
+ &iter) == FALSE) {
+ return;
+ }
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview));
+ gtk_tree_model_get (model, &iter,
+ HW_ID_COLUMN, &id,
+ -1);
+ card = gvc_mixer_control_lookup_card_id (dialog->priv->mixer_control, id);
+ if (card == NULL) {
+ g_warning ("Unable to find card for id: %u", id);
+ return;
+ }
+
+ current_profile = gvc_mixer_card_get_profile (card);
+ profiles = gvc_mixer_card_get_profiles (card);
+ profile_model = GTK_TREE_MODEL (gtk_list_store_new (PROFILE_NUM_COLS,
+ G_TYPE_STRING,
+ G_TYPE_STRING));
+ current_index = 0;
+ for (l = profiles, i = 0; l != NULL; l = l->next, i++) {
+ GvcMixerCardProfile *p = l->data;
+
+ if (g_str_equal (p->profile, current_profile->profile))
+ current_index = i;
+
+ gtk_list_store_insert_with_values (GTK_LIST_STORE (profile_model),
+ NULL,
+ G_MAXINT,
+ PROFILE_NAME, p->profile,
+ PROFILE_HUMAN_NAME, p->human_profile,
+ -1);
+ }
+
+ dialog->priv->hw_profile_combo = gtk_combo_box_new_with_model (profile_model);
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (dialog->priv->hw_profile_combo),
+ renderer, FALSE);
+ gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (dialog->priv->hw_profile_combo),
+ renderer,
+ "text", PROFILE_HUMAN_NAME);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->priv->hw_profile_combo), current_index);
+ //FIXME layout is wrong, missing label
+ gtk_box_pack_start (GTK_BOX (dialog->priv->hw_settings_box),
+ dialog->priv->hw_profile_combo,
+ FALSE, FALSE, 12);
+ gtk_widget_show (dialog->priv->hw_profile_combo);
+
+ g_signal_connect (G_OBJECT (dialog->priv->hw_profile_combo), "changed",
+ G_CALLBACK (on_profile_changed), dialog);
+ g_object_set_data (G_OBJECT (dialog->priv->hw_profile_combo), "card", card);
+}
+
+static void
+card_to_text (GtkTreeViewColumn *column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ char *name, *status, *profile, *str;
+
+ gtk_tree_model_get(model, iter,
+ HW_NAME_COLUMN, &name,
+ HW_STATUS_COLUMN, &status,
+ HW_PROFILE_HUMAN_COLUMN, &profile,
+ -1);
+
+ //FIXME colors?
+ str = g_strdup_printf ("%s\n<i>%s</i>\n<i>%s</i>",
+ name, status, profile);
+ g_object_set (cell, "markup", str, NULL);
+ g_free (str);
+
+ g_free (name);
+ g_free (status);
+ g_free (profile);
+}
+
+static GtkWidget *
+create_cards_treeview (GvcMixerDialog *dialog,
+ GCallback on_changed)
+{
+ GtkWidget *treeview;
+ GtkListStore *store;
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+ GtkTreeSelection *selection;
+
+ treeview = gtk_tree_view_new ();
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+ g_signal_connect (G_OBJECT (selection), "changed",
+ on_changed, dialog);
+
+ store = gtk_list_store_new (HW_NUM_COLUMNS,
+ G_TYPE_UINT,
+ G_TYPE_ICON,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
+ GTK_TREE_MODEL (store));
+
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (G_OBJECT (renderer), "stock-size", GTK_ICON_SIZE_DIALOG, NULL);
+ column = gtk_tree_view_column_new_with_attributes (NULL,
+ renderer,
+ "gicon", HW_ICON_COLUMN,
+ NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+ gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (treeview), -1,
+ _("Name"), gtk_cell_renderer_text_new (),
+ card_to_text, NULL, NULL);
+
+ return treeview;
+}
+
static const guint tab_accel_keys[] = {
GDK_1, GDK_2, GDK_3, GDK_4
};
@@ -1117,8 +1378,10 @@ gvc_mixer_dialog_constructor (GType type,
GtkWidget *sbox;
GtkWidget *ebox;
GSList *streams;
+ GSList *cards;
GSList *l;
GvcMixerStream *stream;
+ GvcMixerCard *card;
GtkTreeSelection *selection;
GtkAccelGroup *accel_group;
GClosure *closure;
@@ -1186,6 +1449,46 @@ gvc_mixer_dialog_constructor (GType type,
self->priv->sound_theme_chooser,
TRUE, TRUE, 6);
+ /* Hardware page */
+ self->priv->hw_box = gtk_vbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (self->priv->hw_box), 12);
+ label = gtk_label_new (_("Hardware"));
+ gtk_notebook_append_page (GTK_NOTEBOOK (self->priv->notebook),
+ self->priv->hw_box,
+ label);
+
+ box = gtk_frame_new (_("Choose a device to configure"));
+ label = gtk_frame_get_label_widget (GTK_FRAME (box));
+ _gtk_label_make_bold (GTK_LABEL (label));
+ gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+ gtk_box_pack_start (GTK_BOX (self->priv->hw_box), box, TRUE, TRUE, 0);
+
+ alignment = gtk_alignment_new (0, 0, 1, 1);
+ gtk_container_add (GTK_CONTAINER (box), alignment);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 0, 0);
+
+ self->priv->hw_treeview = create_cards_treeview (self,
+ G_CALLBACK (on_card_selection_changed));
+ box = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (box),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (box),
+ GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (box), self->priv->hw_treeview);
+ gtk_container_add (GTK_CONTAINER (alignment), box);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->hw_treeview));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+
+ box = gtk_frame_new (_("Settings for the selected device:"));
+ label = gtk_frame_get_label_widget (GTK_FRAME (box));
+ _gtk_label_make_bold (GTK_LABEL (label));
+ gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
+ gtk_box_pack_start (GTK_BOX (self->priv->hw_box), box, TRUE, TRUE, 12);
+ self->priv->hw_settings_box = gtk_vbox_new (FALSE, 12);
+ gtk_container_add (GTK_CONTAINER (box), self->priv->hw_settings_box);
+
/* Input page */
self->priv->input_box = gtk_vbox_new (FALSE, 12);
gtk_container_set_border_width (GTK_CONTAINER (self->priv->input_box), 12);
@@ -1322,6 +1625,14 @@ gvc_mixer_dialog_constructor (GType type,
"stream-removed",
G_CALLBACK (on_control_stream_removed),
self);
+ g_signal_connect (self->priv->mixer_control,
+ "card-added",
+ G_CALLBACK (on_control_card_added),
+ self);
+ g_signal_connect (self->priv->mixer_control,
+ "card-removed",
+ G_CALLBACK (on_control_card_removed),
+ self);
gtk_widget_show_all (GTK_WIDGET (self));
@@ -1332,6 +1643,13 @@ gvc_mixer_dialog_constructor (GType type,
}
g_slist_free (streams);
+ cards = gvc_mixer_control_get_cards (self->priv->mixer_control);
+ for (l = cards; l != NULL; l = l->next) {
+ card = l->data;
+ add_card (self, card);
+ }
+ g_slist_free (cards);
+
return object;
}
@@ -1347,6 +1665,12 @@ gvc_mixer_dialog_dispose (GObject *object)
g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
on_control_stream_removed,
dialog);
+ g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
+ on_control_card_added,
+ dialog);
+ g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
+ on_control_card_removed,
+ dialog);
g_object_unref (dialog->priv->mixer_control);
dialog->priv->mixer_control = NULL;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]