diff options
Diffstat (limited to 'mate-volume-control/src/gvc-mixer-dialog.c')
-rw-r--r-- | mate-volume-control/src/gvc-mixer-dialog.c | 2606 |
1 files changed, 0 insertions, 2606 deletions
diff --git a/mate-volume-control/src/gvc-mixer-dialog.c b/mate-volume-control/src/gvc-mixer-dialog.c deleted file mode 100644 index b6525fb..0000000 --- a/mate-volume-control/src/gvc-mixer-dialog.c +++ /dev/null @@ -1,2606 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 William Jon McCann - * Copyright (C) 2014 Michal Ratajsky <[email protected]> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" - -#include <glib.h> -#include <glib/gi18n.h> -#include <glib-object.h> -#include <gdk/gdk.h> -#include <gdk/gdkkeysyms.h> -#include <gtk/gtk.h> -#include <libmatemixer/matemixer.h> - -#include "gvc-channel-bar.h" -#include "gvc-balance-bar.h" -#include "gvc-combo-box.h" -#include "gvc-mixer-dialog.h" -#include "gvc-sound-theme-chooser.h" -#include "gvc-level-bar.h" -#include "gvc-speaker-test.h" -#include "gvc-utils.h" - -#define GVC_MIXER_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_DIALOG, GvcMixerDialogPrivate)) - -struct _GvcMixerDialogPrivate -{ - MateMixerContext *context; - GHashTable *bars; - GtkWidget *notebook; - GtkWidget *output_bar; - GtkWidget *input_bar; - GtkWidget *input_level_bar; - 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; - GtkWidget *applications_window; - GtkWidget *no_apps_label; - GtkWidget *output_treeview; - GtkWidget *output_settings_frame; - GtkWidget *output_settings_box; - GtkWidget *output_balance_bar; - GtkWidget *output_fade_bar; - GtkWidget *output_lfe_bar; - GtkWidget *output_port_combo; - GtkWidget *input_treeview; - GtkWidget *input_port_combo; - GtkWidget *input_settings_box; - GtkWidget *sound_theme_chooser; - GtkSizeGroup *size_group; - gdouble last_input_peak; - guint num_apps; -}; - -enum { - ICON_COLUMN, - NAME_COLUMN, - LABEL_COLUMN, - ACTIVE_COLUMN, - SPEAKERS_COLUMN, - NUM_COLUMNS -}; - -enum { - HW_ICON_COLUMN, - HW_NAME_COLUMN, - HW_LABEL_COLUMN, - HW_STATUS_COLUMN, - HW_PROFILE_COLUMN, - HW_NUM_COLUMNS -}; - -enum { - PAGE_EFFECTS, - PAGE_HARDWARE, - PAGE_INPUT, - PAGE_OUTPUT, - PAGE_APPLICATIONS -}; - -enum { - PROP_0, - PROP_CONTEXT -}; - -static const guint tab_accel_keys[] = { - GDK_KEY_1, GDK_KEY_2, GDK_KEY_3, GDK_KEY_4, GDK_KEY_5 -}; - -static void gvc_mixer_dialog_class_init (GvcMixerDialogClass *klass); -static void gvc_mixer_dialog_init (GvcMixerDialog *dialog); -static void gvc_mixer_dialog_finalize (GObject *object); - -static void add_stream (GvcMixerDialog *dialog, - MateMixerStream *stream); -static void add_application_control (GvcMixerDialog *dialog, - MateMixerStreamControl *control); -static void add_effects_control (GvcMixerDialog *dialog, - MateMixerStreamControl *control); - -static void remove_stream (GvcMixerDialog *dialog, - const gchar *name); -static void remove_application_control (GvcMixerDialog *dialog, - const gchar *name); - -static void bar_set_stream (GvcMixerDialog *dialog, - GtkWidget *bar, - MateMixerStream *stream); -static void bar_set_stream_control (GvcMixerDialog *dialog, - GtkWidget *bar, - MateMixerStreamControl *control); - -G_DEFINE_TYPE (GvcMixerDialog, gvc_mixer_dialog, GTK_TYPE_DIALOG) - -static MateMixerSwitch * -find_stream_port_switch (MateMixerStream *stream) -{ - const GList *switches; - - switches = mate_mixer_stream_list_switches (stream); - while (switches != NULL) { - MateMixerSwitch *swtch = MATE_MIXER_SWITCH (switches->data); - MateMixerSwitchFlags flags; - - flags = mate_mixer_switch_get_flags (swtch); - if ((flags & MATE_MIXER_SWITCH_TOGGLE) == 0 && - mate_mixer_switch_get_role (swtch) == MATE_MIXER_SWITCH_ROLE_PORT) - return swtch; - - switches = switches->next; - } - return NULL; -} - -static MateMixerSwitch * -find_device_profile_switch (MateMixerDevice *device) -{ - const GList *switches; - - switches = mate_mixer_device_list_switches (device); - while (switches != NULL) { - MateMixerSwitch *swtch = MATE_MIXER_SWITCH (switches->data); - - if (mate_mixer_switch_get_role (swtch) == MATE_MIXER_SWITCH_ROLE_DEVICE_PROFILE) - return swtch; - - switches = switches->next; - } - return NULL; -} - -static MateMixerStream * -find_device_test_stream (GvcMixerDialog *dialog, MateMixerDevice *device) -{ - const GList *streams; - - streams = mate_mixer_device_list_streams (device); - while (streams != NULL) { - MateMixerStream *stream; - MateMixerDirection direction; - - stream = MATE_MIXER_STREAM (streams->data); - direction = mate_mixer_stream_get_direction (stream); - - if (direction == MATE_MIXER_DIRECTION_OUTPUT) { - MateMixerStreamControl *control; - - control = mate_mixer_stream_get_default_control (stream); - if (mate_mixer_stream_control_get_num_channels (control) > 0) - return stream; - } - streams = streams->next; - } - return FALSE; -} - -static gboolean -find_tree_item_by_name (GtkTreeModel *model, - const gchar *name, - guint column, - GtkTreeIter *iter) -{ - gboolean found = FALSE; - - if (!gtk_tree_model_get_iter_first (model, iter)) - return FALSE; - - do { - gchar *n; - gtk_tree_model_get (model, iter, column, &n, -1); - - if (!g_strcmp0 (name, n)) - found = TRUE; - - g_free (n); - } while (!found && gtk_tree_model_iter_next (model, iter)); - - return found; -} - -static void -update_default_tree_item (GvcMixerDialog *dialog, - GtkTreeModel *model, - MateMixerStream *stream) -{ - GtkTreeIter iter; - const gchar *name = NULL; - - if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) - return; - - /* The supplied stream is the default, or the selected item. Traverse - * the item list and mark each item as being selected or not. Also do not - * presume some known stream is selected and allow NULL here. */ - if (stream != NULL) - name = mate_mixer_stream_get_name (stream); - - do { - gchar *n; - gtk_tree_model_get (model, &iter, - NAME_COLUMN, &n, - -1); - gtk_list_store_set (GTK_LIST_STORE (model), - &iter, - ACTIVE_COLUMN, !g_strcmp0 (name, n), - -1); - g_free (n); - } while (gtk_tree_model_iter_next (model, &iter)); -} - -static void -on_combobox_option_changed (GvcComboBox *combo, - const gchar *name, - GvcMixerDialog *dialog) -{ - MateMixerSwitch *swtch; - MateMixerSwitchOption *option; - const GList *options; - - swtch = g_object_get_data (G_OBJECT (combo), "switch"); - if (G_UNLIKELY (swtch == NULL)) { - g_warn_if_reached (); - return; - } - - options = mate_mixer_switch_list_options (swtch); - while (options != NULL) { - option = MATE_MIXER_SWITCH_OPTION (options->data); - - if (g_strcmp0 (mate_mixer_switch_option_get_name (option), name) == 0) - break; - - option = NULL; - options = options->next; - } - - if (G_UNLIKELY (option == NULL)) { - g_warn_if_reached (); - return; - } - - mate_mixer_switch_set_active_option (swtch, option); -} - -static GtkWidget * -create_port_combo_box (GvcMixerDialog *dialog, - MateMixerSwitch *swtch, - const gchar *name, - const GList *items, - const gchar *active) -{ - GtkWidget *combobox; - - combobox = gvc_combo_box_new (name); - - gvc_combo_box_set_options (GVC_COMBO_BOX (combobox), items); - gvc_combo_box_set_active (GVC_COMBO_BOX (combobox), active); - - gvc_combo_box_set_size_group (GVC_COMBO_BOX (combobox), - dialog->priv->size_group, - FALSE); - - g_object_set_data_full (G_OBJECT (combobox), - "switch", - g_object_ref (swtch), - g_object_unref); - - g_signal_connect (G_OBJECT (combobox), - "changed", - G_CALLBACK (on_combobox_option_changed), - dialog); - return combobox; -} - -static void -update_output_settings (GvcMixerDialog *dialog) -{ - MateMixerStream *stream; - MateMixerStreamControl *control; - MateMixerStreamControlFlags flags; - MateMixerSwitch *port_switch; - gboolean has_settings = FALSE; - - g_debug ("Updating output settings"); - - if (dialog->priv->output_balance_bar != NULL) { - gtk_container_remove (GTK_CONTAINER (dialog->priv->output_settings_box), - dialog->priv->output_balance_bar); - - dialog->priv->output_balance_bar = NULL; - } - if (dialog->priv->output_fade_bar != NULL) { - gtk_container_remove (GTK_CONTAINER (dialog->priv->output_settings_box), - dialog->priv->output_fade_bar); - - dialog->priv->output_fade_bar = NULL; - } - if (dialog->priv->output_lfe_bar != NULL) { - gtk_container_remove (GTK_CONTAINER (dialog->priv->output_settings_box), - dialog->priv->output_lfe_bar); - - dialog->priv->output_lfe_bar = NULL; - } - if (dialog->priv->output_port_combo != NULL) { - gtk_container_remove (GTK_CONTAINER (dialog->priv->output_settings_box), - dialog->priv->output_port_combo); - - dialog->priv->output_port_combo = NULL; - } - - /* Get the control currently associated with the output slider */ - control = gvc_channel_bar_get_control (GVC_CHANNEL_BAR (dialog->priv->output_bar)); - if (control == NULL) { - g_debug ("There is no control for the default output stream"); - gtk_widget_hide (dialog->priv->output_settings_frame); - return; - } - flags = mate_mixer_stream_control_get_flags (control); - - /* Enable balance bar if it is available */ - if (flags & MATE_MIXER_STREAM_CONTROL_CAN_BALANCE) { - dialog->priv->output_balance_bar = - gvc_balance_bar_new (control, BALANCE_TYPE_RL); - - gvc_balance_bar_set_size_group (GVC_BALANCE_BAR (dialog->priv->output_balance_bar), - dialog->priv->size_group, - TRUE); - - gtk_box_pack_start (GTK_BOX (dialog->priv->output_settings_box), - dialog->priv->output_balance_bar, - FALSE, FALSE, 6); - - gtk_widget_show (dialog->priv->output_balance_bar); - has_settings = TRUE; - } - - /* Enable fade bar if it is available */ - if (flags & MATE_MIXER_STREAM_CONTROL_CAN_FADE) { - dialog->priv->output_fade_bar = - gvc_balance_bar_new (control, BALANCE_TYPE_FR); - - gvc_balance_bar_set_size_group (GVC_BALANCE_BAR (dialog->priv->output_fade_bar), - dialog->priv->size_group, - TRUE); - - gtk_box_pack_start (GTK_BOX (dialog->priv->output_settings_box), - dialog->priv->output_fade_bar, - FALSE, FALSE, 6); - - gtk_widget_show (dialog->priv->output_fade_bar); - has_settings = TRUE; - } - - /* Enable subwoofer volume bar if subwoofer is available */ - if (mate_mixer_stream_control_has_channel_position (control, MATE_MIXER_CHANNEL_LFE)) { - dialog->priv->output_lfe_bar = - gvc_balance_bar_new (control, BALANCE_TYPE_LFE); - - gvc_balance_bar_set_size_group (GVC_BALANCE_BAR (dialog->priv->output_lfe_bar), - dialog->priv->size_group, - TRUE); - - gtk_box_pack_start (GTK_BOX (dialog->priv->output_settings_box), - dialog->priv->output_lfe_bar, - FALSE, FALSE, 6); - - gtk_widget_show (dialog->priv->output_lfe_bar); - has_settings = TRUE; - } - - /* Get owning stream of the control */ - stream = mate_mixer_stream_control_get_stream (control); - if (G_UNLIKELY (stream == NULL)) - return; - - /* Enable the port selector if the stream has one */ - port_switch = find_stream_port_switch (stream); - if (port_switch != NULL) { - const GList *options; - const gchar *active_name = NULL; - MateMixerSwitchOption *active; - - options = mate_mixer_switch_list_options (port_switch); - active = mate_mixer_switch_get_active_option (port_switch); - if (active != NULL) - active_name = mate_mixer_switch_option_get_name (active); - - dialog->priv->output_port_combo = - create_port_combo_box (dialog, - port_switch, - _("Co_nnector:"), - options, - active_name); - - gtk_box_pack_start (GTK_BOX (dialog->priv->output_settings_box), - dialog->priv->output_port_combo, - TRUE, FALSE, 6); - - gtk_widget_show (dialog->priv->output_port_combo); - has_settings = TRUE; - } - - if (has_settings == TRUE) - gtk_widget_show (dialog->priv->output_settings_frame); - else - gtk_widget_hide (dialog->priv->output_settings_frame); -} - -static void -set_output_stream (GvcMixerDialog *dialog, MateMixerStream *stream) -{ - GtkTreeModel *model; - MateMixerSwitch *swtch; - MateMixerStreamControl *control; - - control = gvc_channel_bar_get_control (GVC_CHANNEL_BAR (dialog->priv->output_bar)); - if (control != NULL) { - /* Disconnect port switch of the previous stream */ - if (dialog->priv->output_port_combo != NULL) { - swtch = g_object_get_data (G_OBJECT (dialog->priv->output_port_combo), - "switch"); - if (swtch != NULL) - g_signal_handlers_disconnect_by_data (G_OBJECT (swtch), - dialog); - } - } - - bar_set_stream (dialog, dialog->priv->output_bar, stream); - - if (stream != NULL) { - const GList *controls; - - controls = mate_mixer_context_list_stored_controls (dialog->priv->context); - - /* Move all stored controls to the newly selected default stream */ - while (controls != NULL) { - MateMixerStream *parent; - MateMixerStreamControl *control; - - control = MATE_MIXER_STREAM_CONTROL (controls->data); - parent = mate_mixer_stream_control_get_stream (control); - - /* Prefer streamless controls to stay the way they are, forcing them to - * a particular owning stream would be wrong for eg. event controls */ - if (parent != NULL && parent != stream) { - MateMixerDirection direction = - mate_mixer_stream_get_direction (parent); - - if (direction == MATE_MIXER_DIRECTION_OUTPUT) - mate_mixer_stream_control_set_stream (control, stream); - } - controls = controls->next; - } - } - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview)); - update_default_tree_item (dialog, model, stream); - - update_output_settings (dialog); -} - -static void -on_context_default_output_stream_notify (MateMixerContext *context, - GParamSpec *pspec, - GvcMixerDialog *dialog) -{ - MateMixerStream *stream; - - stream = mate_mixer_context_get_default_output_stream (context); - - set_output_stream (dialog, stream); -} - -#define DECAY_STEP .15 - -static void -on_stream_control_monitor_value (MateMixerStream *stream, - gdouble value, - GvcMixerDialog *dialog) -{ - GtkAdjustment *adj; - - if (dialog->priv->last_input_peak >= DECAY_STEP) { - if (value < dialog->priv->last_input_peak - DECAY_STEP) { - value = dialog->priv->last_input_peak - DECAY_STEP; - } - } - - dialog->priv->last_input_peak = value; - - adj = gvc_level_bar_get_peak_adjustment (GVC_LEVEL_BAR (dialog->priv->input_level_bar)); - if (value >= 0) - gtk_adjustment_set_value (adj, value); - else - gtk_adjustment_set_value (adj, 0.0); -} - -static void -update_input_settings (GvcMixerDialog *dialog) -{ - MateMixerStream *stream; - MateMixerStreamControl *control; - MateMixerStreamControlFlags flags; - MateMixerSwitch *port_switch; - - g_debug ("Updating input settings"); - - if (dialog->priv->input_port_combo != NULL) { - gtk_container_remove (GTK_CONTAINER (dialog->priv->input_settings_box), - dialog->priv->input_port_combo); - - dialog->priv->input_port_combo = NULL; - } - - /* Get the control currently associated with the input slider */ - control = gvc_channel_bar_get_control (GVC_CHANNEL_BAR (dialog->priv->input_bar)); - if (control == NULL) - return; - - flags = mate_mixer_stream_control_get_flags (control); - - /* Enable level bar only if supported by the control */ - if (flags & MATE_MIXER_STREAM_CONTROL_HAS_MONITOR) - g_signal_connect (G_OBJECT (control), - "monitor-value", - G_CALLBACK (on_stream_control_monitor_value), - dialog); - - /* Get owning stream of the control */ - stream = mate_mixer_stream_control_get_stream (control); - if (G_UNLIKELY (stream == NULL)) - return; - - /* Enable the port selector if the stream has one */ - port_switch = find_stream_port_switch (stream); - if (port_switch != NULL) { - const GList *options; - const gchar *active_name = NULL; - MateMixerSwitchOption *active; - - options = mate_mixer_switch_list_options (port_switch); - active = mate_mixer_switch_get_active_option (port_switch); - if (active != NULL) - active_name = mate_mixer_switch_option_get_name (active); - - dialog->priv->input_port_combo = - create_port_combo_box (dialog, - port_switch, - _("Co_nnector:"), - options, - active_name); - - gtk_box_pack_start (GTK_BOX (dialog->priv->input_settings_box), - dialog->priv->input_port_combo, - TRUE, TRUE, 0); - - gtk_widget_show (dialog->priv->input_port_combo); - } -} - -static void -on_stream_control_mute_notify (MateMixerStreamControl *control, - GParamSpec *pspec, - GvcMixerDialog *dialog) -{ - /* Stop monitoring the input stream when it gets muted */ - if (mate_mixer_stream_control_get_mute (control) == TRUE) - mate_mixer_stream_control_set_monitor_enabled (control, FALSE); - else - mate_mixer_stream_control_set_monitor_enabled (control, TRUE); -} - -static void -set_input_stream (GvcMixerDialog *dialog, MateMixerStream *stream) -{ - GtkTreeModel *model; - MateMixerSwitch *swtch; - MateMixerStreamControl *control; - - control = gvc_channel_bar_get_control (GVC_CHANNEL_BAR (dialog->priv->input_bar)); - if (control != NULL) { - /* Disconnect port switch of the previous stream */ - if (dialog->priv->input_port_combo != NULL) { - swtch = g_object_get_data (G_OBJECT (dialog->priv->input_port_combo), - "switch"); - if (swtch != NULL) - g_signal_handlers_disconnect_by_data (G_OBJECT (swtch), - dialog); - } - - /* Disable monitoring of the previous control */ - g_signal_handlers_disconnect_by_func (G_OBJECT (control), - G_CALLBACK (on_stream_control_monitor_value), - dialog); - - mate_mixer_stream_control_set_monitor_enabled (control, FALSE); - } - - bar_set_stream (dialog, dialog->priv->input_bar, stream); - - if (stream != NULL) { - const GList *controls; - guint page = gtk_notebook_get_current_page (GTK_NOTEBOOK (dialog->priv->notebook)); - - controls = mate_mixer_context_list_stored_controls (dialog->priv->context); - - /* Move all stored controls to the newly selected default stream */ - while (controls != NULL) { - MateMixerStream *parent; - - control = MATE_MIXER_STREAM_CONTROL (controls->data); - parent = mate_mixer_stream_control_get_stream (control); - - /* Prefer streamless controls to stay the way they are, forcing them to - * a particular owning stream would be wrong for eg. event controls */ - if (parent != NULL && parent != stream) { - MateMixerDirection direction = - mate_mixer_stream_get_direction (parent); - - if (direction == MATE_MIXER_DIRECTION_INPUT) - mate_mixer_stream_control_set_stream (control, stream); - } - controls = controls->next; - } - - if (page == PAGE_INPUT) { - MateMixerStreamControl *control = - gvc_channel_bar_get_control (GVC_CHANNEL_BAR (dialog->priv->input_bar)); - - if (G_LIKELY (control != NULL)) - mate_mixer_stream_control_set_monitor_enabled (control, TRUE); - } - - /* Enable/disable the peak level monitor according to mute state */ - g_signal_connect (G_OBJECT (stream), - "notify::mute", - G_CALLBACK (on_stream_control_mute_notify), - dialog); - } - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview)); - update_default_tree_item (dialog, model, stream); - - update_input_settings (dialog); -} - -static void -on_context_default_input_stream_notify (MateMixerContext *context, - GParamSpec *pspec, - GvcMixerDialog *dialog) -{ - MateMixerStream *stream; - - g_debug ("Default input stream has changed"); - - stream = mate_mixer_context_get_default_input_stream (context); - - set_input_stream (dialog, stream); -} - -static GvcComboBox * -find_combo_box_by_switch (GvcMixerDialog *dialog, MateMixerSwitch *swtch) -{ - MateMixerSwitch *combo_switch; - - if (dialog->priv->output_port_combo != NULL) { - combo_switch = g_object_get_data (G_OBJECT (dialog->priv->output_port_combo), - "switch"); - if (combo_switch == swtch) - return GVC_COMBO_BOX (dialog->priv->output_port_combo); - } - - if (dialog->priv->input_port_combo != NULL) { - combo_switch = g_object_get_data (G_OBJECT (dialog->priv->input_port_combo), - "switch"); - if (combo_switch == swtch) - return GVC_COMBO_BOX (dialog->priv->input_port_combo); - } - return NULL; -} - -static void -on_switch_option_notify (MateMixerSwitch *swtch, - GParamSpec *pspec, - GvcMixerDialog *dialog) -{ - GvcComboBox *combobox; - MateMixerSwitchOption *port; - - combobox = find_combo_box_by_switch (dialog, swtch); - if (G_UNLIKELY (combobox == NULL)) { - g_warn_if_reached (); - return; - } - - g_signal_handlers_block_by_func (G_OBJECT (combobox), - on_combobox_option_changed, - dialog); - - port = mate_mixer_switch_get_active_option (swtch); - if (G_LIKELY (port != NULL)) - gvc_combo_box_set_active (GVC_COMBO_BOX (combobox), - mate_mixer_switch_option_get_name (port)); - - g_signal_handlers_unblock_by_func (G_OBJECT (combobox), - on_combobox_option_changed, - dialog); -} - -static GtkWidget * -create_bar (GvcMixerDialog *dialog, gboolean use_size_group, gboolean symmetric) -{ - GtkWidget *bar; - - bar = gvc_channel_bar_new (NULL); - - if (use_size_group == TRUE) - gvc_channel_bar_set_size_group (GVC_CHANNEL_BAR (bar), - dialog->priv->size_group, - symmetric); - - g_object_set (G_OBJECT (bar), - "orientation", GTK_ORIENTATION_HORIZONTAL, - "show-mute", TRUE, - "show-icons", TRUE, - "show-marks", TRUE, - "extended", TRUE, NULL); - return bar; -} - -static void -bar_set_stream (GvcMixerDialog *dialog, - GtkWidget *bar, - MateMixerStream *stream) -{ - MateMixerStreamControl *control = NULL; - - if (stream != NULL) { - MateMixerSwitch *port_switch; - - control = mate_mixer_stream_get_default_control (stream); - - port_switch = find_stream_port_switch (stream); - if (port_switch != NULL) - g_signal_connect (G_OBJECT (port_switch), - "notify::active-option", - G_CALLBACK (on_switch_option_notify), - dialog); - } - - bar_set_stream_control (dialog, bar, control); -} - -static void -bar_set_stream_control (GvcMixerDialog *dialog, - GtkWidget *bar, - MateMixerStreamControl *control) -{ - MateMixerStreamControl *previous; - - previous = gvc_channel_bar_get_control (GVC_CHANNEL_BAR (bar)); - if (previous != NULL) { - const gchar *name = mate_mixer_stream_control_get_name (previous); - - g_debug ("Disconnecting old stream control %s", name); - - g_signal_handlers_disconnect_by_data (G_OBJECT (previous), dialog); - - /* This may not do anything because we no longer have the information - * about the owning stream, in case it was an input stream, make - * sure to disconnected from the peak level monitor */ - mate_mixer_stream_control_set_monitor_enabled (previous, FALSE); - - g_hash_table_remove (dialog->priv->bars, name); - } - - gvc_channel_bar_set_control (GVC_CHANNEL_BAR (bar), control); - - if (control != NULL) { - const gchar *name = mate_mixer_stream_control_get_name (control); - - g_hash_table_insert (dialog->priv->bars, - (gpointer) name, - bar); - - gtk_widget_set_sensitive (GTK_WIDGET (bar), TRUE); - } else - gtk_widget_set_sensitive (GTK_WIDGET (bar), TRUE); -} - -static void -add_application_control (GvcMixerDialog *dialog, MateMixerStreamControl *control) -{ - MateMixerStream *stream; - MateMixerStreamControlMediaRole media_role; - MateMixerAppInfo *info; - MateMixerDirection direction = MATE_MIXER_DIRECTION_UNKNOWN; - GtkWidget *bar; - const gchar *app_id; - const gchar *app_name; - const gchar *app_icon; - - media_role = mate_mixer_stream_control_get_media_role (control); - - /* Add stream to the applications page, but make sure the stream qualifies - * for the inclusion */ - info = mate_mixer_stream_control_get_app_info (control); - if (info == NULL) - return; - - /* Skip streams with roles we don't care about */ - if (media_role == MATE_MIXER_STREAM_CONTROL_MEDIA_ROLE_EVENT || - media_role == MATE_MIXER_STREAM_CONTROL_MEDIA_ROLE_TEST || - media_role == MATE_MIXER_STREAM_CONTROL_MEDIA_ROLE_ABSTRACT || - media_role == MATE_MIXER_STREAM_CONTROL_MEDIA_ROLE_FILTER) - return; - - app_id = mate_mixer_app_info_get_id (info); - - /* These applications may have associated streams because they do peak - * level monitoring, skip these too */ - if (!g_strcmp0 (app_id, "org.mate.VolumeControl") || - !g_strcmp0 (app_id, "org.gnome.VolumeControl") || - !g_strcmp0 (app_id, "org.PulseAudio.pavucontrol")) - return; - - app_name = mate_mixer_app_info_get_name (info); - if (app_name == NULL) - app_name = mate_mixer_stream_control_get_label (control); - if (app_name == NULL) - app_name = mate_mixer_stream_control_get_name (control); - if (G_UNLIKELY (app_name == NULL)) - return; - - bar = create_bar (dialog, FALSE, FALSE); - - g_object_set (G_OBJECT (bar), - "show-marks", FALSE, - "extended", FALSE, - NULL); - - /* By default channel bars use speaker icons, use microphone icons - * instead for recording applications */ - stream = mate_mixer_stream_control_get_stream (control); - if (stream != NULL) - direction = mate_mixer_stream_get_direction (stream); - - if (direction == MATE_MIXER_DIRECTION_INPUT) - g_object_set (G_OBJECT (bar), - "low-icon-name", "audio-input-microphone-low", - "high-icon-name", "audio-input-microphone-high", - NULL); - - app_icon = mate_mixer_app_info_get_icon (info); - if (app_icon == NULL) { - if (direction == MATE_MIXER_DIRECTION_INPUT) - app_icon = "audio-input-microphone"; - else - app_icon = "applications-multimedia"; - } - - gvc_channel_bar_set_name (GVC_CHANNEL_BAR (bar), app_name); - gvc_channel_bar_set_icon_name (GVC_CHANNEL_BAR (bar), app_icon); - - gtk_box_pack_start (GTK_BOX (dialog->priv->applications_box), - bar, - FALSE, FALSE, 12); - - bar_set_stream_control (dialog, bar, control); - dialog->priv->num_apps++; - - gtk_widget_hide (dialog->priv->no_apps_label); - gtk_widget_show (bar); -} - -static void -add_effects_control (GvcMixerDialog *dialog, MateMixerStreamControl *control) -{ - MateMixerStreamControl *previous; - const gchar *name; - - /* We use a stored event control for the effects volume slider, - * because regular streams are only created when an event sound - * is played and then immediately destroyed. - * The stored event control should exist all the time. */ - previous = gvc_channel_bar_get_control (GVC_CHANNEL_BAR (dialog->priv->effects_bar)); - if (previous != NULL) { - name = mate_mixer_stream_control_get_name (previous); - - g_signal_handlers_disconnect_by_data (G_OBJECT (previous), dialog); - g_hash_table_remove (dialog->priv->bars, name); - } - - gvc_channel_bar_set_control (GVC_CHANNEL_BAR (dialog->priv->effects_bar), control); - - if (control != NULL) { - name = mate_mixer_stream_control_get_name (control); - g_hash_table_insert (dialog->priv->bars, - (gpointer) name, - dialog->priv->effects_bar); - - gtk_widget_set_sensitive (GTK_WIDGET (dialog->priv->effects_bar), TRUE); - } else - gtk_widget_set_sensitive (GTK_WIDGET (dialog->priv->effects_bar), FALSE); -} - -static void -on_stream_control_added (MateMixerStream *stream, - const gchar *name, - GvcMixerDialog *dialog) -{ - MateMixerStreamControl *control; - MateMixerStreamControlRole role; - - control = mate_mixer_stream_get_control (stream, name); - if G_UNLIKELY (control == NULL) - return; - - role = mate_mixer_stream_control_get_role (control); - - if (role == MATE_MIXER_STREAM_CONTROL_ROLE_APPLICATION) - add_application_control (dialog, control); -} - -static void -on_stream_control_removed (MateMixerStream *stream, - const gchar *name, - GvcMixerDialog *dialog) -{ - MateMixerStreamControl *control; - - control = gvc_channel_bar_get_control (GVC_CHANNEL_BAR (dialog->priv->input_bar)); - if (control != NULL) { - const gchar *input_name = mate_mixer_stream_control_get_name (control); - - if (strcmp (name, input_name) == 0) { - // XXX probably can't even happen, but handle it somehow - return; - } - } - - control = gvc_channel_bar_get_control (GVC_CHANNEL_BAR (dialog->priv->output_bar)); - if (control != NULL) { - const gchar *input_name = mate_mixer_stream_control_get_name (control); - - if (strcmp (name, input_name) == 0) { - // XXX probably can't even happen, but handle it somehow - return; - } - } - - /* No way to be sure that it is an application control, but we don't have - * any other than application bars that could match the name */ - remove_application_control (dialog, name); -} - -static void -add_stream (GvcMixerDialog *dialog, MateMixerStream *stream) -{ - GtkTreeModel *model = NULL; - GtkTreeIter iter; - const gchar *speakers = NULL; - const GList *controls; - gboolean is_default = FALSE; - MateMixerDirection direction; - - direction = mate_mixer_stream_get_direction (stream); - - if (direction == MATE_MIXER_DIRECTION_INPUT) { - MateMixerStream *input; - - input = mate_mixer_context_get_default_input_stream (dialog->priv->context); - if (stream == input) { - bar_set_stream (dialog, dialog->priv->input_bar, stream); - - update_input_settings (dialog); - is_default = TRUE; - } - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview)); - } - else if (direction == MATE_MIXER_DIRECTION_OUTPUT) { - MateMixerStream *output; - MateMixerStreamControl *control; - - output = mate_mixer_context_get_default_output_stream (dialog->priv->context); - if (stream == output) { - bar_set_stream (dialog, dialog->priv->output_bar, stream); - - update_output_settings (dialog); - is_default = TRUE; - } - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview)); - - control = mate_mixer_stream_get_default_control (stream); - if (G_LIKELY (control != NULL)) - speakers = gvc_channel_map_to_pretty_string (control); - } - - controls = mate_mixer_stream_list_controls (stream); - while (controls != NULL) { - MateMixerStreamControl *control = MATE_MIXER_STREAM_CONTROL (controls->data); - MateMixerStreamControlRole role; - - role = mate_mixer_stream_control_get_role (control); - - if (role == MATE_MIXER_STREAM_CONTROL_ROLE_APPLICATION) - add_application_control (dialog, control); - - controls = controls->next; - } - - if (model != NULL) { - const gchar *name; - const gchar *label; - - name = mate_mixer_stream_get_name (stream); - label = mate_mixer_stream_get_label (stream); - - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - gtk_list_store_set (GTK_LIST_STORE (model), - &iter, - NAME_COLUMN, name, - LABEL_COLUMN, label, - ACTIVE_COLUMN, is_default, - SPEAKERS_COLUMN, speakers, - -1); - } - - // XXX find a way to disconnect when removed - g_signal_connect (G_OBJECT (stream), - "control-added", - G_CALLBACK (on_stream_control_added), - dialog); - g_signal_connect (G_OBJECT (stream), - "control-removed", - G_CALLBACK (on_stream_control_removed), - dialog); -} - -static void -update_device_test_visibility (GvcMixerDialog *dialog) -{ - MateMixerDevice *device; - MateMixerStream *stream; - - device = g_object_get_data (G_OBJECT (dialog->priv->hw_profile_combo), "device"); - if (G_UNLIKELY (device == NULL)) { - return; - } - - stream = find_device_test_stream (dialog, device); - - g_object_set (G_OBJECT (dialog->priv->hw_profile_combo), - "show-button", (stream != NULL), - NULL); -} - -static void -on_context_stream_added (MateMixerContext *context, - const gchar *name, - GvcMixerDialog *dialog) -{ - MateMixerStream *stream; - MateMixerDirection direction; - GtkWidget *bar; - - stream = mate_mixer_context_get_stream (context, name); - if (G_UNLIKELY (stream == NULL)) - return; - - direction = mate_mixer_stream_get_direction (stream); - - /* If the newly added stream belongs to the currently selected device and - * the test button is hidden, this stream may be the one to allow the - * sound test and therefore we may need to enable the button */ - if (dialog->priv->hw_profile_combo != NULL && direction == MATE_MIXER_DIRECTION_OUTPUT) { - MateMixerDevice *device1; - MateMixerDevice *device2; - - device1 = mate_mixer_stream_get_device (stream); - device2 = g_object_get_data (G_OBJECT (dialog->priv->hw_profile_combo), - "device"); - - if (device1 == device2) { - gboolean show_button; - - g_object_get (G_OBJECT (dialog->priv->hw_profile_combo), - "show-button", &show_button, - NULL); - - if (show_button == FALSE) - update_device_test_visibility (dialog); - } - } - - bar = g_hash_table_lookup (dialog->priv->bars, name); - if (G_UNLIKELY (bar != NULL)) - return; - - add_stream (dialog, stream); -} - -static void -remove_stream (GvcMixerDialog *dialog, const gchar *name) -{ - GtkWidget *bar; - GtkTreeIter iter; - GtkTreeModel *model; - - bar = g_hash_table_lookup (dialog->priv->bars, name); - - if (bar != NULL) { - g_debug ("Removing stream %s from bar %s", - name, - gvc_channel_bar_get_name (GVC_CHANNEL_BAR (bar))); - - bar_set_stream (dialog, bar, NULL); - } - - /* Remove from any models */ - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview)); - if (find_tree_item_by_name (GTK_TREE_MODEL (model), - name, - NAME_COLUMN, - &iter) == TRUE) - gtk_list_store_remove (GTK_LIST_STORE (model), &iter); - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview)); - if (find_tree_item_by_name (GTK_TREE_MODEL (model), - name, - NAME_COLUMN, - &iter) == TRUE) - gtk_list_store_remove (GTK_LIST_STORE (model), &iter); -} - -static void -remove_application_control (GvcMixerDialog *dialog, const gchar *name) -{ - GtkWidget *bar; - - bar = g_hash_table_lookup (dialog->priv->bars, name); - if (G_UNLIKELY (bar == NULL)) - return; - - g_debug ("Removing application stream %s", name); - - /* We could call bar_set_stream_control here, but that would pointlessly - * invalidate the channel bar, so just remove it ourselves */ - g_hash_table_remove (dialog->priv->bars, name); - - gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (bar)), bar); - - if (G_UNLIKELY (dialog->priv->num_apps <= 0)) { - g_warn_if_reached (); - dialog->priv->num_apps = 1; - } - - dialog->priv->num_apps--; - - if (dialog->priv->num_apps == 0) - gtk_widget_show (dialog->priv->no_apps_label); -} - -static void -on_context_stream_removed (MateMixerContext *context, - const gchar *name, - GvcMixerDialog *dialog) -{ - if (dialog->priv->hw_profile_combo != NULL) { - gboolean show_button; - - g_object_get (G_OBJECT (dialog->priv->hw_profile_combo), - "show-button", &show_button, - NULL); - - if (show_button == TRUE) - update_device_test_visibility (dialog); - } - - remove_stream (dialog, name); -} - -static void -on_context_stored_control_added (MateMixerContext *context, - const gchar *name, - GvcMixerDialog *dialog) -{ - MateMixerStreamControl *control; - MateMixerStreamControlMediaRole media_role; - - control = MATE_MIXER_STREAM_CONTROL (mate_mixer_context_get_stored_control (context, name)); - if (G_UNLIKELY (control == NULL)) - return; - - media_role = mate_mixer_stream_control_get_media_role (control); - - if (media_role == MATE_MIXER_STREAM_CONTROL_MEDIA_ROLE_EVENT) - add_effects_control (dialog, control); -} - -static void -on_context_stored_control_removed (MateMixerContext *context, - const gchar *name, - GvcMixerDialog *dialog) -{ - GtkWidget *bar; - - bar = g_hash_table_lookup (dialog->priv->bars, name); - - if (bar != NULL) { - /* We only use a stored control in the effects bar */ - if (G_UNLIKELY (bar != dialog->priv->effects_bar)) { - g_warn_if_reached (); - return; - } - - bar_set_stream (dialog, bar, NULL); - } -} - -static gchar * -device_status (MateMixerDevice *device) -{ - guint inputs = 0; - guint outputs = 0; - gchar *inputs_str = NULL; - gchar *outputs_str = NULL; - const GList *streams; - - /* Get number of input and output streams in the device */ - streams = mate_mixer_device_list_streams (device); - while (streams != NULL) { - MateMixerStream *stream = MATE_MIXER_STREAM (streams->data); - MateMixerDirection direction; - - direction = mate_mixer_stream_get_direction (stream); - - if (direction == MATE_MIXER_DIRECTION_INPUT) - inputs++; - else if (direction == MATE_MIXER_DIRECTION_OUTPUT) - outputs++; - - streams = streams->next; - } - - if (inputs == 0 && outputs == 0) { - /* translators: - * The device has been disabled */ - return g_strdup (_("Disabled")); - } - - if (outputs > 0) { - /* translators: - * The number of sound outputs on a particular device */ - outputs_str = g_strdup_printf (ngettext ("%u Output", - "%u Outputs", - outputs), - outputs); - } - - if (inputs > 0) { - /* translators: - * The number of sound inputs on a particular device */ - inputs_str = g_strdup_printf (ngettext ("%u Input", - "%u Inputs", - inputs), - inputs); - } - - if (inputs_str != NULL && outputs_str != NULL) { - gchar *ret = g_strdup_printf ("%s / %s", - outputs_str, - inputs_str); - g_free (outputs_str); - g_free (inputs_str); - return ret; - } - - if (inputs_str != NULL) - return inputs_str; - - return outputs_str; -} - -static void -update_device_info (GvcMixerDialog *dialog, MateMixerDevice *device) -{ - GtkTreeModel *model = NULL; - GtkTreeIter iter; - const gchar *label; - const gchar *profile_label = NULL; - gchar *status; - MateMixerSwitch *profile_switch; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview)); - - if (find_tree_item_by_name (model, - mate_mixer_device_get_name (device), - HW_NAME_COLUMN, - &iter) == FALSE) - return; - - label = mate_mixer_device_get_label (device); - - profile_switch = find_device_profile_switch (device); - if (profile_switch != NULL) { - MateMixerSwitchOption *active; - - active = mate_mixer_switch_get_active_option (profile_switch); - if (G_LIKELY (active != NULL)) - profile_label = mate_mixer_switch_option_get_label (active); - } - - status = device_status (device); - - gtk_list_store_set (GTK_LIST_STORE (model), - &iter, - HW_LABEL_COLUMN, label, - HW_PROFILE_COLUMN, profile_label, - HW_STATUS_COLUMN, status, - -1); - g_free (status); -} - -static void -on_device_profile_notify (MateMixerSwitch *swtch, - GParamSpec *pspec, - GvcMixerDialog *dialog) -{ - MateMixerSwitchOption *active; - - g_signal_handlers_block_by_func (G_OBJECT (dialog->priv->hw_profile_combo), - G_CALLBACK (on_combobox_option_changed), - dialog); - - active = mate_mixer_switch_get_active_option (swtch); - if (G_LIKELY (active != NULL)) { - const gchar *name = mate_mixer_switch_option_get_name (active); - - gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->hw_profile_combo), - name); - } - - g_signal_handlers_unblock_by_func (G_OBJECT (dialog->priv->hw_profile_combo), - G_CALLBACK (on_combobox_option_changed), - dialog); - - // XXX find device - // update_device_info (dialog, device); -} - -static void -add_device (GvcMixerDialog *dialog, MateMixerDevice *device) -{ - GtkTreeModel *model; - GtkTreeIter iter; - GIcon *icon; - const gchar *name; - const gchar *label; - gchar *status; - const gchar *profile_label = NULL; - MateMixerSwitch *profile_switch; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview)); - - name = mate_mixer_device_get_name (device); - label = mate_mixer_device_get_label (device); - - if (find_tree_item_by_name (GTK_TREE_MODEL (model), - name, - HW_NAME_COLUMN, - &iter) == FALSE) - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - - icon = g_themed_icon_new_with_default_fallbacks (mate_mixer_device_get_icon (device)); - - profile_switch = find_device_profile_switch (device); - if (profile_switch != NULL) { - MateMixerSwitchOption *active; - - active = mate_mixer_switch_get_active_option (profile_switch); - if (G_LIKELY (active != NULL)) - profile_label = mate_mixer_switch_option_get_label (active); - - g_signal_connect (G_OBJECT (device), - "notify::active-option", - G_CALLBACK (on_device_profile_notify), - dialog); - } - - status = device_status (device); - - gtk_list_store_set (GTK_LIST_STORE (model), - &iter, - HW_NAME_COLUMN, name, - HW_LABEL_COLUMN, label, - HW_ICON_COLUMN, icon, - HW_PROFILE_COLUMN, profile_label, - HW_STATUS_COLUMN, status, - -1); - g_free (status); - -} - -static void -on_context_device_added (MateMixerContext *context, const gchar *name, GvcMixerDialog *dialog) -{ - MateMixerDevice *device; - - device = mate_mixer_context_get_device (context, name); - if (G_UNLIKELY (device == NULL)) - return; - - add_device (dialog, device); -} - -static void -on_context_device_removed (MateMixerContext *context, - const gchar *name, - GvcMixerDialog *dialog) -{ - GtkTreeIter iter; - GtkTreeModel *model; - - /* Remove from the device model */ - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview)); - - if (find_tree_item_by_name (GTK_TREE_MODEL (model), - name, - HW_NAME_COLUMN, - &iter) == TRUE) - gtk_list_store_remove (GTK_LIST_STORE (model), &iter); -} - -static void -make_label_bold (GtkLabel *label) -{ - PangoFontDescription *font_desc; - - font_desc = pango_font_description_new (); - - pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD); - - /* This will only affect the weight of the font, the rest is - * from the current state of the widget, which comes from the - * theme or user prefs, since the font desc only has the - * weight flag turned on. */ -#if GTK_CHECK_VERSION (3, 0, 0) - gtk_widget_override_font (GTK_WIDGET (label), font_desc); -#else - gtk_widget_modify_font (GTK_WIDGET (label), font_desc); -#endif - pango_font_description_free (font_desc); -} - -static void -on_input_radio_toggled (GtkCellRendererToggle *renderer, - gchar *path_str, - GvcMixerDialog *dialog) -{ - GtkTreeModel *model; - GtkTreeIter iter; - GtkTreePath *path; - gboolean toggled = FALSE; - gchar *name = NULL; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview)); - path = gtk_tree_path_new_from_string (path_str); - - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_path_free (path); - - gtk_tree_model_get (model, &iter, - NAME_COLUMN, &name, - ACTIVE_COLUMN, &toggled, - -1); - if (toggled ^ 1) { - MateMixerStream *stream; - MateMixerBackendFlags flags; - - stream = mate_mixer_context_get_stream (dialog->priv->context, name); - if (G_UNLIKELY (stream == NULL)) { - g_warn_if_reached (); - g_free (name); - return; - } - - g_debug ("Default input stream selection changed to %s", name); - - // XXX cache this - flags = mate_mixer_context_get_backend_flags (dialog->priv->context); - - if (flags & MATE_MIXER_BACKEND_CAN_SET_DEFAULT_INPUT_STREAM) - mate_mixer_context_set_default_input_stream (dialog->priv->context, stream); - else - set_input_stream (dialog, stream); - } - g_free (name); -} - -static void -on_output_radio_toggled (GtkCellRendererToggle *renderer, - gchar *path_str, - GvcMixerDialog *dialog) -{ - GtkTreeModel *model; - GtkTreeIter iter; - GtkTreePath *path; - gboolean toggled = FALSE; - gchar *name = NULL; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview)); - path = gtk_tree_path_new_from_string (path_str); - - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_path_free (path); - - gtk_tree_model_get (model, &iter, - NAME_COLUMN, &name, - ACTIVE_COLUMN, &toggled, - -1); - if (toggled ^ 1) { - MateMixerStream *stream; - MateMixerBackendFlags flags; - - stream = mate_mixer_context_get_stream (dialog->priv->context, name); - if (G_UNLIKELY (stream == NULL)) { - g_warn_if_reached (); - g_free (name); - return; - } - - g_debug ("Default output stream selection changed to %s", name); - - // XXX cache this - flags = mate_mixer_context_get_backend_flags (dialog->priv->context); - - if (flags & MATE_MIXER_BACKEND_CAN_SET_DEFAULT_OUTPUT_STREAM) - mate_mixer_context_set_default_output_stream (dialog->priv->context, stream); - else - set_output_stream (dialog, stream); - } - g_free (name); -} - -static void -stream_name_to_text (GtkTreeViewColumn *column, - GtkCellRenderer *cell, - GtkTreeModel *model, - GtkTreeIter *iter, - gpointer user_data) -{ - gchar *label; - gchar *speakers; - - gtk_tree_model_get (model, iter, - LABEL_COLUMN, &label, - SPEAKERS_COLUMN, &speakers, - -1); - - if (speakers != NULL) { - gchar *str = g_strdup_printf ("%s\n<i>%s</i>", - label, - speakers); - - g_object_set (cell, "markup", str, NULL); - g_free (str); - g_free (speakers); - } else { - g_object_set (cell, "text", label, NULL); - } - - g_free (label); -} - -static gint -compare_stream_treeview_items (GtkTreeModel *model, - GtkTreeIter *a, - GtkTreeIter *b, - gpointer user_data) -{ - gchar *desc_a = NULL; - gchar *desc_b = NULL; - gint result; - - gtk_tree_model_get (model, a, - LABEL_COLUMN, &desc_a, - -1); - gtk_tree_model_get (model, b, - LABEL_COLUMN, &desc_b, - -1); - - if (desc_a == NULL) { - g_free (desc_b); - return -1; - } - if (desc_b == NULL) { - g_free (desc_a); - return 1; - } - - result = g_ascii_strcasecmp (desc_a, desc_b); - - g_free (desc_a); - g_free (desc_b); - return result; -} - -static GtkWidget * -create_stream_treeview (GvcMixerDialog *dialog, GCallback on_toggled) -{ - GtkWidget *treeview; - GtkListStore *store; - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - - treeview = gtk_tree_view_new (); - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE); - - store = gtk_list_store_new (NUM_COLUMNS, - G_TYPE_ICON, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_BOOLEAN, - G_TYPE_STRING); - - gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), - GTK_TREE_MODEL (store)); - - renderer = gtk_cell_renderer_toggle_new (); - gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE); - - column = gtk_tree_view_column_new_with_attributes (NULL, - renderer, - "active", ACTIVE_COLUMN, - NULL); - - gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); - - g_signal_connect (G_OBJECT (renderer), - "toggled", - G_CALLBACK (on_toggled), - dialog); - - gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (treeview), -1, - _("Name"), - gtk_cell_renderer_text_new (), - stream_name_to_text, - NULL, NULL); - - /* Keep the list of streams sorted by the name */ - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), - LABEL_COLUMN, - GTK_SORT_ASCENDING); - - gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store), - LABEL_COLUMN, - compare_stream_treeview_items, - NULL, NULL); - return treeview; -} - -static void -on_test_speakers_clicked (GvcComboBox *widget, GvcMixerDialog *dialog) -{ - GtkWidget *d, - *test, - *container; - gchar *title; - MateMixerDevice *device; - MateMixerStream *stream; - - device = g_object_get_data (G_OBJECT (widget), "device"); - if (G_UNLIKELY (device == NULL)) { - g_warn_if_reached (); - return; - } - - stream = find_device_test_stream (dialog, device); - if (G_UNLIKELY (stream == NULL)) { - g_warn_if_reached (); - return; - } - - title = g_strdup_printf (_("Speaker Testing for %s"), - mate_mixer_device_get_label (device)); - - d = gtk_dialog_new_with_buttons (title, - GTK_WINDOW (dialog), - GTK_DIALOG_MODAL | - GTK_DIALOG_DESTROY_WITH_PARENT, - "gtk-close", - GTK_RESPONSE_CLOSE, - NULL); - g_free (title); - - gtk_window_set_resizable (GTK_WINDOW (d), FALSE); - - test = gvc_speaker_test_new (stream); - gtk_widget_show (test); - - container = gtk_dialog_get_content_area (GTK_DIALOG (d)); - gtk_container_add (GTK_CONTAINER (container), test); - - gtk_dialog_run (GTK_DIALOG (d)); - gtk_widget_destroy (d); -} - -static GtkWidget * -create_profile_combo_box (GvcMixerDialog *dialog, - MateMixerSwitch *swtch, - const gchar *name, - const GList *items, - const gchar *active) -{ - GtkWidget *combobox; - - combobox = gvc_combo_box_new (name); - - gvc_combo_box_set_options (GVC_COMBO_BOX (combobox), items); - gvc_combo_box_set_active (GVC_COMBO_BOX (combobox), active); - - gvc_combo_box_set_size_group (GVC_COMBO_BOX (combobox), - dialog->priv->size_group, - FALSE); - - g_object_set (G_OBJECT (combobox), - "button-label", _("Test Speakers"), - NULL); - - g_object_set_data_full (G_OBJECT (combobox), - "switch", - g_object_ref (swtch), - g_object_unref); - - g_signal_connect (G_OBJECT (combobox), - "changed", - G_CALLBACK (on_combobox_option_changed), - dialog); - - g_signal_connect (G_OBJECT (combobox), - "button-clicked", - G_CALLBACK (on_test_speakers_clicked), - dialog); - - return combobox; -} - -static void -on_device_selection_changed (GtkTreeSelection *selection, GvcMixerDialog *dialog) -{ - GtkTreeIter iter; - gchar *name; - MateMixerDevice *device; - MateMixerSwitch *profile_switch; - - g_debug ("Device selection changed"); - - if (dialog->priv->hw_profile_combo != NULL) { - gtk_container_remove (GTK_CONTAINER (dialog->priv->hw_settings_box), - dialog->priv->hw_profile_combo); - - dialog->priv->hw_profile_combo = NULL; - } - - if (gtk_tree_selection_get_selected (selection, NULL, &iter) == FALSE) - return; - - gtk_tree_model_get (gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview)), - &iter, - HW_NAME_COLUMN, &name, - -1); - - device = mate_mixer_context_get_device (dialog->priv->context, name); - if (G_UNLIKELY (device == NULL)) { - g_warn_if_reached (); - g_free (name); - return; - } - g_free (name); - - /* Profile/speaker test combo */ - profile_switch = find_device_profile_switch (device); - if (profile_switch != NULL) { - const GList *options; - const gchar *active_name = NULL; - MateMixerSwitchOption *active; - - options = mate_mixer_switch_list_options (profile_switch); - active = mate_mixer_switch_get_active_option (profile_switch); - if (active != NULL) - active_name = mate_mixer_switch_option_get_name (active); - - dialog->priv->hw_profile_combo = - create_profile_combo_box (dialog, - profile_switch, - _("_Profile:"), - options, - active_name); - - g_object_set_data_full (G_OBJECT (dialog->priv->hw_profile_combo), - "device", - g_object_ref (device), - g_object_unref); - - gtk_box_pack_start (GTK_BOX (dialog->priv->hw_settings_box), - dialog->priv->hw_profile_combo, - TRUE, TRUE, 6); - - /* Enable the speaker test button if the selected device - * is capable of sound output */ - update_device_test_visibility (dialog); - - gtk_widget_show (dialog->priv->hw_profile_combo); - } -} - -static void -on_notebook_switch_page (GtkNotebook *notebook, - GtkWidget *page, - guint page_num, - GvcMixerDialog *dialog) -{ - MateMixerStreamControl *control; - - // XXX because this is called too early in constructor - if (G_UNLIKELY (dialog->priv->input_bar == NULL)) - return; - - control = gvc_channel_bar_get_control (GVC_CHANNEL_BAR (dialog->priv->input_bar)); - if (control == NULL) - return; - - if (page_num == PAGE_INPUT) - mate_mixer_stream_control_set_monitor_enabled (control, TRUE); - else - mate_mixer_stream_control_set_monitor_enabled (control, FALSE); -} - -static void -device_name_to_text (GtkTreeViewColumn *column, - GtkCellRenderer *cell, - GtkTreeModel *model, - GtkTreeIter *iter, - gpointer user_data) -{ - gchar *label = NULL; - gchar *profile = NULL; - gchar *status = NULL; - - gtk_tree_model_get (model, iter, - HW_LABEL_COLUMN, &label, - HW_PROFILE_COLUMN, &profile, - HW_STATUS_COLUMN, &status, - -1); - - if (G_LIKELY (status != NULL)) { - gchar *str; - - if (profile != NULL) - str = g_strdup_printf ("%s\n<i>%s</i>\n<i>%s</i>", - label, - status, - profile); - else - str = g_strdup_printf ("%s\n<i>%s</i>", - label, - status); - - g_object_set (cell, "markup", str, NULL); - g_free (str); - g_free (profile); - g_free (status); - } else - g_object_set (cell, "text", label, NULL); - - g_free (label); -} - -static gint -compare_device_treeview_items (GtkTreeModel *model, - GtkTreeIter *a, - GtkTreeIter *b, - gpointer user_data) -{ - gchar *desc_a = NULL; - gchar *desc_b = NULL; - gint result; - - gtk_tree_model_get (model, a, - HW_LABEL_COLUMN, &desc_a, - -1); - gtk_tree_model_get (model, b, - HW_LABEL_COLUMN, &desc_b, - -1); - - result = g_ascii_strcasecmp (desc_a, desc_b); - - g_free (desc_a); - g_free (desc_b); - return result; -} - -static GtkWidget * -create_device_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_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 (), - device_name_to_text, - NULL, NULL); - - /* Keep the list of streams sorted by the name */ - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), - HW_LABEL_COLUMN, - GTK_SORT_ASCENDING); - - gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store), - HW_LABEL_COLUMN, - compare_device_treeview_items, - NULL, NULL); - return treeview; -} - -static void -dialog_accel_cb (GtkAccelGroup *accelgroup, - GObject *object, - guint key, - GdkModifierType mod, - GvcMixerDialog *self) -{ - gint num = -1; - gint i; - - for (i = 0; i < G_N_ELEMENTS (tab_accel_keys); i++) { - if (tab_accel_keys[i] == key) { - num = i; - break; - } - } - - if (num != -1) - gtk_notebook_set_current_page (GTK_NOTEBOOK (self->priv->notebook), num); -} - -static GObject * -gvc_mixer_dialog_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_params) -{ - GObject *object; - GvcMixerDialog *self; - GtkWidget *main_vbox; - GtkWidget *label; - GtkWidget *alignment; - GtkWidget *box; - GtkWidget *sbox; - GtkWidget *ebox; - GtkTreeSelection *selection; - GtkAccelGroup *accel_group; - GClosure *closure; - GtkTreeIter iter; - gint i; - const GList *list; - - object = G_OBJECT_CLASS (gvc_mixer_dialog_parent_class)->constructor (type, - n_construct_properties, - construct_params); - - self = GVC_MIXER_DIALOG (object); - - gtk_dialog_add_button (GTK_DIALOG (self), "gtk-close", GTK_RESPONSE_OK); - - main_vbox = gtk_dialog_get_content_area (GTK_DIALOG (self)); - gtk_box_set_spacing (GTK_BOX (main_vbox), 2); - - gtk_container_set_border_width (GTK_CONTAINER (self), 6); - -#if GTK_CHECK_VERSION (3, 0, 0) - self->priv->output_stream_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); -#else - self->priv->output_stream_box = gtk_hbox_new (FALSE, 12); -#endif - - alignment = gtk_alignment_new (0, 0, 1, 1); - gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 12, 0, 0, 0); - gtk_container_add (GTK_CONTAINER (alignment), self->priv->output_stream_box); - gtk_box_pack_start (GTK_BOX (main_vbox), - alignment, - FALSE, FALSE, 0); - - self->priv->output_bar = create_bar (self, TRUE, TRUE); - gvc_channel_bar_set_name (GVC_CHANNEL_BAR (self->priv->output_bar), - _("_Output volume: ")); - - gtk_widget_show (self->priv->output_bar); - gtk_widget_set_sensitive (self->priv->output_bar, FALSE); - - gtk_box_pack_start (GTK_BOX (self->priv->output_stream_box), - self->priv->output_bar, TRUE, TRUE, 12); - - self->priv->notebook = gtk_notebook_new (); - gtk_box_pack_start (GTK_BOX (main_vbox), - self->priv->notebook, - TRUE, TRUE, 0); - - g_signal_connect (G_OBJECT (self->priv->notebook), - "switch-page", - G_CALLBACK (on_notebook_switch_page), - self); - - gtk_container_set_border_width (GTK_CONTAINER (self->priv->notebook), 5); - - /* Set up accels (borrowed from Empathy) */ - accel_group = gtk_accel_group_new (); - gtk_window_add_accel_group (GTK_WINDOW (self), accel_group); - - for (i = 0; i < G_N_ELEMENTS (tab_accel_keys); i++) { - closure = g_cclosure_new (G_CALLBACK (dialog_accel_cb), - self, - NULL); - gtk_accel_group_connect (accel_group, - tab_accel_keys[i], - GDK_MOD1_MASK, - 0, - closure); - } - - g_object_unref (accel_group); - - /* Create notebook pages */ -#if GTK_CHECK_VERSION (3, 0, 0) - self->priv->sound_effects_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); -#else - self->priv->sound_effects_box = gtk_vbox_new (FALSE, 6); -#endif - gtk_container_set_border_width (GTK_CONTAINER (self->priv->sound_effects_box), 12); - - label = gtk_label_new (_("Sound Effects")); - gtk_notebook_append_page (GTK_NOTEBOOK (self->priv->notebook), - self->priv->sound_effects_box, - label); - - self->priv->effects_bar = create_bar (self, TRUE, TRUE); - gtk_box_pack_start (GTK_BOX (self->priv->sound_effects_box), - self->priv->effects_bar, FALSE, FALSE, 0); - - gvc_channel_bar_set_show_marks (GVC_CHANNEL_BAR (self->priv->effects_bar), FALSE); - gvc_channel_bar_set_extended (GVC_CHANNEL_BAR (self->priv->effects_bar), FALSE); - - gvc_channel_bar_set_name (GVC_CHANNEL_BAR (self->priv->effects_bar), - _("_Alert volume: ")); - - gtk_widget_show (self->priv->effects_bar); - gtk_widget_set_sensitive (self->priv->effects_bar, FALSE); - - self->priv->sound_theme_chooser = gvc_sound_theme_chooser_new (); - - gtk_box_pack_start (GTK_BOX (self->priv->sound_effects_box), - self->priv->sound_theme_chooser, - TRUE, TRUE, 6); - -#if GTK_CHECK_VERSION (3, 0, 0) - self->priv->hw_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); -#else - self->priv->hw_box = gtk_vbox_new (FALSE, 12); -#endif - 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 (_("C_hoose a device to configure:")); - label = gtk_frame_get_label_widget (GTK_FRAME (box)); - make_label_bold (GTK_LABEL (label)); - gtk_label_set_use_underline (GTK_LABEL (label), TRUE); - 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_device_treeview (self, - G_CALLBACK (on_device_selection_changed)); - gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->priv->hw_treeview); - - 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)); - make_label_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, FALSE, TRUE, 12); - -#if GTK_CHECK_VERSION (3, 0, 0) - self->priv->hw_settings_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); -#else - self->priv->hw_settings_box = gtk_vbox_new (FALSE, 12); -#endif - - gtk_container_add (GTK_CONTAINER (box), self->priv->hw_settings_box); - -#if GTK_CHECK_VERSION (3, 0, 0) - self->priv->input_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); -#else - self->priv->input_box = gtk_vbox_new (FALSE, 12); -#endif - - gtk_container_set_border_width (GTK_CONTAINER (self->priv->input_box), 12); - - label = gtk_label_new (_("Input")); - gtk_notebook_append_page (GTK_NOTEBOOK (self->priv->notebook), - self->priv->input_box, - label); - - self->priv->input_bar = create_bar (self, TRUE, TRUE); - - gvc_channel_bar_set_name (GVC_CHANNEL_BAR (self->priv->input_bar), - _("_Input volume: ")); - - gvc_channel_bar_set_low_icon_name (GVC_CHANNEL_BAR (self->priv->input_bar), - "audio-input-microphone-low"); - gvc_channel_bar_set_high_icon_name (GVC_CHANNEL_BAR (self->priv->input_bar), - "audio-input-microphone-high"); - - gtk_widget_show (self->priv->input_bar); - gtk_widget_set_sensitive (self->priv->input_bar, FALSE); - - alignment = gtk_alignment_new (0, 0, 1, 1); - gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 0, 0); - gtk_container_add (GTK_CONTAINER (alignment), self->priv->input_bar); - gtk_box_pack_start (GTK_BOX (self->priv->input_box), - alignment, - FALSE, FALSE, 0); - -#if GTK_CHECK_VERSION (3, 0, 0) - box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); - sbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); - ebox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); -#else - box = gtk_hbox_new (FALSE, 6); - sbox = gtk_hbox_new (FALSE, 6); - ebox = gtk_hbox_new (FALSE, 6); -#endif - - gtk_box_pack_start (GTK_BOX (self->priv->input_box), - box, - FALSE, FALSE, 6); - gtk_box_pack_start (GTK_BOX (box), - sbox, - FALSE, FALSE, 0); - - label = gtk_label_new (_("Input level:")); - gtk_box_pack_start (GTK_BOX (sbox), - label, - FALSE, FALSE, 0); - gtk_size_group_add_widget (self->priv->size_group, sbox); - - self->priv->input_level_bar = gvc_level_bar_new (); - gvc_level_bar_set_orientation (GVC_LEVEL_BAR (self->priv->input_level_bar), - GTK_ORIENTATION_HORIZONTAL); - gvc_level_bar_set_scale (GVC_LEVEL_BAR (self->priv->input_level_bar), - GVC_LEVEL_SCALE_LINEAR); - gtk_box_pack_start (GTK_BOX (box), - self->priv->input_level_bar, - TRUE, TRUE, 6); - - gtk_box_pack_start (GTK_BOX (box), - ebox, - FALSE, FALSE, 0); - gtk_size_group_add_widget (self->priv->size_group, ebox); - -#if GTK_CHECK_VERSION (3, 0, 0) - self->priv->input_settings_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); -#else - self->priv->input_settings_box = gtk_hbox_new (FALSE, 6); -#endif - gtk_box_pack_start (GTK_BOX (self->priv->input_box), - self->priv->input_settings_box, - FALSE, FALSE, 0); - - box = gtk_frame_new (_("C_hoose a device for sound input:")); - label = gtk_frame_get_label_widget (GTK_FRAME (box)); - make_label_bold (GTK_LABEL (label)); - gtk_label_set_use_underline (GTK_LABEL (label), TRUE); - gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE); - gtk_box_pack_start (GTK_BOX (self->priv->input_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->input_treeview = - create_stream_treeview (self, G_CALLBACK (on_input_radio_toggled)); - - gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->priv->input_treeview); - - 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->input_treeview); - gtk_container_add (GTK_CONTAINER (alignment), box); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->input_treeview)); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); - - /* Output page */ - self->priv->output_box = gtk_vbox_new (FALSE, 12); - gtk_container_set_border_width (GTK_CONTAINER (self->priv->output_box), 12); - label = gtk_label_new (_("Output")); - gtk_notebook_append_page (GTK_NOTEBOOK (self->priv->notebook), - self->priv->output_box, - label); - - box = gtk_frame_new (_("C_hoose a device for sound output:")); - label = gtk_frame_get_label_widget (GTK_FRAME (box)); - make_label_bold (GTK_LABEL (label)); - gtk_label_set_use_underline (GTK_LABEL (label), TRUE); - gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE); - gtk_box_pack_start (GTK_BOX (self->priv->output_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->output_treeview = create_stream_treeview (self, - G_CALLBACK (on_output_radio_toggled)); - gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->priv->output_treeview); - - 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->output_treeview); - gtk_container_add (GTK_CONTAINER (alignment), box); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->output_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)); - make_label_bold (GTK_LABEL (label)); - gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE); - gtk_box_pack_start (GTK_BOX (self->priv->output_box), box, FALSE, FALSE, 12); - self->priv->output_settings_box = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (box), self->priv->output_settings_box); - - self->priv->output_settings_frame = box; - - /* Applications */ - self->priv->applications_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (self->priv->applications_window), - GTK_POLICY_NEVER, - GTK_POLICY_AUTOMATIC); - - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (self->priv->applications_window), - GTK_SHADOW_IN); - -#if GTK_CHECK_VERSION (3, 0, 0) - self->priv->applications_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); -#else - self->priv->applications_box = gtk_vbox_new (FALSE, 12); -#endif - gtk_container_set_border_width (GTK_CONTAINER (self->priv->applications_box), 12); - -#if GTK_CHECK_VERSION (3, 8, 0) - gtk_container_add (GTK_CONTAINER (self->priv->applications_window), - self->priv->applications_box); -#else - gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (self->priv->applications_window), - self->priv->applications_box); -#endif - - label = gtk_label_new (_("Applications")); - gtk_notebook_append_page (GTK_NOTEBOOK (self->priv->notebook), - self->priv->applications_window, - label); - - self->priv->no_apps_label = gtk_label_new (_("No application is currently playing or recording audio.")); - gtk_box_pack_start (GTK_BOX (self->priv->applications_box), - self->priv->no_apps_label, - TRUE, TRUE, 0); - - gtk_widget_show_all (main_vbox); - - list = mate_mixer_context_list_streams (self->priv->context); - while (list != NULL) { - add_stream (self, MATE_MIXER_STREAM (list->data)); - list = list->next; - } - - list = mate_mixer_context_list_devices (self->priv->context); - while (list != NULL) { - add_device (self, MATE_MIXER_DEVICE (list->data)); - list = list->next; - } - - /* Find an event role stream */ - list = mate_mixer_context_list_stored_controls (self->priv->context); - while (list != NULL) { - MateMixerStreamControl *control = MATE_MIXER_STREAM_CONTROL (list->data); - MateMixerStreamControlMediaRole media_role; - - media_role = mate_mixer_stream_control_get_media_role (control); - - if (media_role == MATE_MIXER_STREAM_CONTROL_MEDIA_ROLE_EVENT) { - add_effects_control (self, control); - break; - } - list = list->next; - } - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->hw_treeview)); - - /* Select the first device in the list */ - // XXX handle no devices - if (gtk_tree_selection_get_selected (selection, NULL, NULL) == FALSE) { - GtkTreeModel *model = - gtk_tree_view_get_model (GTK_TREE_VIEW (self->priv->hw_treeview)); - - if (gtk_tree_model_get_iter_first (model, &iter)) - gtk_tree_selection_select_iter (selection, &iter); - } - - return object; -} - -static MateMixerContext * -gvc_mixer_dialog_get_context (GvcMixerDialog *dialog) -{ - return dialog->priv->context; -} - -static void -gvc_mixer_dialog_set_context (GvcMixerDialog *dialog, MateMixerContext *context) -{ - dialog->priv->context = g_object_ref (context); - - g_signal_connect (G_OBJECT (dialog->priv->context), - "stream-added", - G_CALLBACK (on_context_stream_added), - dialog); - g_signal_connect (G_OBJECT (dialog->priv->context), - "stream-removed", - G_CALLBACK (on_context_stream_removed), - dialog); - - g_signal_connect (G_OBJECT (dialog->priv->context), - "device-added", - G_CALLBACK (on_context_device_added), - dialog); - g_signal_connect (G_OBJECT (dialog->priv->context), - "device-removed", - G_CALLBACK (on_context_device_removed), - dialog); - - g_signal_connect (G_OBJECT (dialog->priv->context), - "notify::default-input-stream", - G_CALLBACK (on_context_default_input_stream_notify), - dialog); - g_signal_connect (G_OBJECT (dialog->priv->context), - "notify::default-output-stream", - G_CALLBACK (on_context_default_output_stream_notify), - dialog); - - g_signal_connect (G_OBJECT (dialog->priv->context), - "stored-control-added", - G_CALLBACK (on_context_stored_control_added), - dialog); - g_signal_connect (G_OBJECT (dialog->priv->context), - "stored-control-removed", - G_CALLBACK (on_context_stored_control_removed), - dialog); - - g_object_notify (G_OBJECT (dialog), "context"); -} - -static void -gvc_mixer_dialog_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GvcMixerDialog *self = GVC_MIXER_DIALOG (object); - - switch (prop_id) { - case PROP_CONTEXT: - gvc_mixer_dialog_set_context (self, g_value_get_object (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gvc_mixer_dialog_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GvcMixerDialog *self = GVC_MIXER_DIALOG (object); - - switch (prop_id) { - case PROP_CONTEXT: - g_value_set_object (value, gvc_mixer_dialog_get_context (self)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gvc_mixer_dialog_dispose (GObject *object) -{ - GvcMixerDialog *dialog = GVC_MIXER_DIALOG (object); - - if (dialog->priv->context != NULL) { - g_signal_handlers_disconnect_by_data (G_OBJECT (dialog->priv->context), - dialog); - - g_clear_object (&dialog->priv->context); - } - - G_OBJECT_CLASS (gvc_mixer_dialog_parent_class)->dispose (object); -} - -static void -gvc_mixer_dialog_class_init (GvcMixerDialogClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructor = gvc_mixer_dialog_constructor; - object_class->dispose = gvc_mixer_dialog_dispose; - object_class->finalize = gvc_mixer_dialog_finalize; - object_class->set_property = gvc_mixer_dialog_set_property; - object_class->get_property = gvc_mixer_dialog_get_property; - - g_object_class_install_property (object_class, - PROP_CONTEXT, - g_param_spec_object ("context", - "Context", - "MateMixer context", - MATE_MIXER_TYPE_CONTEXT, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_type_class_add_private (klass, sizeof (GvcMixerDialogPrivate)); -} - -static void -gvc_mixer_dialog_init (GvcMixerDialog *dialog) -{ - dialog->priv = GVC_MIXER_DIALOG_GET_PRIVATE (dialog); - - dialog->priv->bars = g_hash_table_new (g_str_hash, g_str_equal); - dialog->priv->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); -} - -static void -gvc_mixer_dialog_finalize (GObject *object) -{ - GvcMixerDialog *dialog; - - dialog = GVC_MIXER_DIALOG (object); - - g_hash_table_destroy (dialog->priv->bars); - - G_OBJECT_CLASS (gvc_mixer_dialog_parent_class)->finalize (object); -} - -GvcMixerDialog * -gvc_mixer_dialog_new (MateMixerContext *context) -{ - return g_object_new (GVC_TYPE_MIXER_DIALOG, - "icon-name", "multimedia-volume-control", - "title", _("Sound Preferences"), - "context", context, - NULL); -} - -gboolean -gvc_mixer_dialog_set_page (GvcMixerDialog *self, const gchar *page) -{ - guint num = 0; - - g_return_val_if_fail (GVC_IS_MIXER_DIALOG (self), FALSE); - - if (page != NULL) { - if (g_str_equal (page, "effects")) - num = PAGE_EFFECTS; - else if (g_str_equal (page, "hardware")) - num = PAGE_HARDWARE; - else if (g_str_equal (page, "input")) - num = PAGE_INPUT; - else if (g_str_equal (page, "output")) - num = PAGE_OUTPUT; - else if (g_str_equal (page, "applications")) - num = PAGE_APPLICATIONS; - } - - gtk_notebook_set_current_page (GTK_NOTEBOOK (self->priv->notebook), num); - - return TRUE; -} |