summaryrefslogtreecommitdiff
path: root/mate-volume-control/src/gvc-mixer-dialog.c
diff options
context:
space:
mode:
Diffstat (limited to 'mate-volume-control/src/gvc-mixer-dialog.c')
-rw-r--r--mate-volume-control/src/gvc-mixer-dialog.c1889
1 files changed, 1062 insertions, 827 deletions
diff --git a/mate-volume-control/src/gvc-mixer-dialog.c b/mate-volume-control/src/gvc-mixer-dialog.c
index e46ca1a..9b524fe 100644
--- a/mate-volume-control/src/gvc-mixer-dialog.c
+++ b/mate-volume-control/src/gvc-mixer-dialog.c
@@ -1,6 +1,7 @@
/* -*- 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
@@ -22,11 +23,11 @@
#include <glib.h>
#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
-#if GTK_CHECK_VERSION (3, 0, 0)
-#include <gdk/gdkkeysyms-compat.h>
-#endif
+#include <libmatemixer/matemixer.h>
#include "gvc-channel-bar.h"
#include "gvc-balance-bar.h"
@@ -57,9 +58,10 @@ struct _GvcMixerDialogPrivate
GtkWidget *input_box;
GtkWidget *output_box;
GtkWidget *applications_box;
- GtkWidget *applications_scrolled_window;
+ 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;
@@ -70,7 +72,6 @@ struct _GvcMixerDialogPrivate
GtkWidget *input_settings_box;
GtkWidget *sound_theme_chooser;
GtkSizeGroup *size_group;
- GtkSizeGroup *apps_size_group;
gdouble last_input_peak;
guint num_apps;
};
@@ -79,7 +80,6 @@ enum {
ICON_COLUMN,
NAME_COLUMN,
DESCRIPTION_COLUMN,
- DEVICE_COLUMN,
ACTIVE_COLUMN,
SPEAKERS_COLUMN,
NUM_COLUMNS
@@ -91,212 +91,292 @@ enum {
HW_DESCRIPTION_COLUMN,
HW_STATUS_COLUMN,
HW_PROFILE_COLUMN,
- HW_PROFILE_HUMAN_COLUMN,
- HW_SENSITIVE_COLUMN,
HW_NUM_COLUMNS
};
enum {
- PAGE_EVENTS,
+ PAGE_EFFECTS,
PAGE_HARDWARE,
PAGE_INPUT,
PAGE_OUTPUT,
PAGE_APPLICATIONS
};
-enum
-{
+enum {
PROP_0,
- PROP_MIXER_CONTROL
+ PROP_CONTROL
};
-static void gvc_mixer_dialog_class_init (GvcMixerDialogClass *klass);
-static void gvc_mixer_dialog_init (GvcMixerDialog *mixer_dialog);
-static void gvc_mixer_dialog_finalize (GObject *object);
+static const guint tab_accel_keys[] = {
+ GDK_KEY_1, GDK_KEY_2, GDK_KEY_3, GDK_KEY_4, GDK_KEY_5
+};
-static void bar_set_stream (GvcMixerDialog *dialog,
- GtkWidget *bar,
- MateMixerStream *stream);
+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 on_adjustment_value_changed (GtkAdjustment *adjustment,
- GvcMixerDialog *dialog);
+static void bar_set_stream (GvcMixerDialog *dialog,
+ GtkWidget *bar,
+ MateMixerStream *stream);
G_DEFINE_TYPE (GvcMixerDialog, gvc_mixer_dialog, GTK_TYPE_DIALOG)
-static void
-update_default_input (GvcMixerDialog *dialog)
+static gboolean
+find_tree_item_by_name (GtkTreeModel *model,
+ const gchar *name,
+ guint column,
+ GtkTreeIter *iter)
{
- GtkTreeModel *model;
- GtkTreeIter iter;
- gboolean ret;
+ gboolean found = FALSE;
- 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 = FALSE;
- MateMixerStream *stream;
- gchar *name;
+ if (!gtk_tree_model_get_iter_first (model, iter))
+ return FALSE;
- gtk_tree_model_get (model, &iter,
- NAME_COLUMN, &name,
- ACTIVE_COLUMN, &toggled,
- -1);
+ do {
+ gchar *n;
- stream = mate_mixer_control_get_stream (dialog->priv->control, name);
- if (stream == NULL) {
- g_warning ("Unable to find stream for id: %s", name);
- g_free (name);
- continue;
- }
+ gtk_tree_model_get (model, iter, column, &n, -1);
- if (stream == mate_mixer_control_get_default_input_stream (dialog->priv->control))
- is_default = TRUE;
+ if (!g_strcmp0 (name, n))
+ found = TRUE;
- gtk_list_store_set (GTK_LIST_STORE (model),
- &iter,
- ACTIVE_COLUMN, is_default,
- -1);
+ g_free (n);
+ } while (!found && gtk_tree_model_iter_next (model, iter));
- g_free (name);
- } while (gtk_tree_model_iter_next (model, &iter));
+ return found;
}
static void
-update_description (GvcMixerDialog *dialog,
- guint column,
- const gchar *value,
- MateMixerStream *stream)
+update_default_item (GvcMixerDialog *dialog,
+ GtkTreeModel *model,
+ MateMixerStream *stream)
{
- GtkTreeModel *model;
- GtkTreeIter iter;
- MateMixerStreamFlags flags;
- const gchar *name;
-
- flags = mate_mixer_stream_get_flags (stream);
+ GtkTreeIter iter;
+ const gchar *name = NULL;
- if (flags & MATE_MIXER_STREAM_INPUT)
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
- else if (flags & MATE_MIXER_STREAM_OUTPUT)
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
- else
- g_assert_not_reached ();
+ if (gtk_tree_model_get_iter_first (model, &iter) == FALSE)
+ return;
- gtk_tree_model_get_iter_first (model, &iter);
+ /* 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);
- name = mate_mixer_stream_get_name (stream);
do {
- const gchar *current_name;
-
- gtk_tree_model_get (model, &iter, NAME_COLUMN, &current_name, -1);
- if (!g_strcmp0 (name, current_name))
- continue;
+ gchar *n;
+ gtk_tree_model_get (model, &iter,
+ NAME_COLUMN, &n,
+ -1);
gtk_list_store_set (GTK_LIST_STORE (model),
&iter,
- column, value,
+ ACTIVE_COLUMN, !g_strcmp0 (name, n),
-1);
- break;
+ g_free (n);
} while (gtk_tree_model_iter_next (model, &iter));
}
static void
-port_selection_changed (GvcComboBox *combo,
- const gchar *port,
- GvcMixerDialog *dialog)
+on_combo_box_port_changed (GvcComboBox *combo,
+ const gchar *name,
+ GvcMixerDialog *dialog)
{
MateMixerStream *stream;
+ MateMixerPort *port = NULL;
+ GList *ports;
stream = g_object_get_data (G_OBJECT (combo), "stream");
- if (stream == NULL) {
- g_warning ("Could not find stream for port combo box");
+ if (G_UNLIKELY (stream == NULL)) {
+ g_warn_if_reached ();
+ return;
+ }
+
+ ports = (GList *) mate_mixer_stream_list_ports (stream);
+ while (ports) {
+ port = MATE_MIXER_PORT (ports->data);
+
+ if (!g_strcmp0 (mate_mixer_port_get_name (port), name))
+ break;
+
+ port = NULL;
+ ports = ports->next;
+ }
+
+ if (G_UNLIKELY (port == NULL)) {
+ g_warn_if_reached ();
return;
}
+ g_debug ("Stream port changed to %s for stream %s",
+ name,
+ mate_mixer_stream_get_name (stream));
+
mate_mixer_stream_set_active_port (stream, port);
}
static void
+on_combo_box_profile_changed (GvcComboBox *combo,
+ const gchar *name,
+ GvcMixerDialog *dialog)
+{
+ MateMixerDevice *device;
+ MateMixerDeviceProfile *profile = NULL;
+ GList *profiles;
+
+ device = g_object_get_data (G_OBJECT (combo), "device");
+ if (G_UNLIKELY (device == NULL)) {
+ g_warn_if_reached ();
+ return;
+ }
+
+ profiles = (GList *) mate_mixer_device_list_profiles (device);
+ while (profiles) {
+ profile = MATE_MIXER_DEVICE_PROFILE (profiles->data);
+
+ if (!g_strcmp0 (mate_mixer_device_profile_get_name (profile), name))
+ break;
+
+ profile = NULL;
+ profiles = profiles->next;
+ }
+
+ if (G_UNLIKELY (profile == NULL)) {
+ g_warn_if_reached ();
+ return;
+ }
+
+ g_debug ("Device profile changed to %s for device %s",
+ name,
+ mate_mixer_device_get_name (device));
+
+ mate_mixer_device_set_active_profile (device, profile);
+}
+
+static GtkWidget *
+create_port_combo_box (GvcMixerDialog *dialog,
+ MateMixerStream *stream,
+ const gchar *name,
+ const GList *items,
+ const gchar *active)
+{
+ GtkWidget *combobox;
+
+ combobox = gvc_combo_box_new (name);
+
+ gvc_combo_box_set_ports (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),
+ "stream",
+ g_object_ref (stream),
+ g_object_unref);
+
+ g_signal_connect (G_OBJECT (combobox),
+ "changed",
+ G_CALLBACK (on_combo_box_port_changed),
+ dialog);
+
+ return combobox;
+}
+
+static void
update_output_settings (GvcMixerDialog *dialog)
{
MateMixerStream *stream;
MateMixerStreamFlags flags;
const GList *ports;
+ 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;
}
stream = mate_mixer_control_get_default_output_stream (dialog->priv->control);
if (stream == NULL) {
- g_warning ("Default sink stream not found");
+ g_debug ("There is no default output stream - output settings disabled");
+ gtk_widget_hide (dialog->priv->output_settings_frame);
return;
}
flags = mate_mixer_stream_get_flags (stream);
- gvc_channel_bar_set_base_volume (GVC_CHANNEL_BAR (dialog->priv->output_bar),
- mate_mixer_stream_get_base_volume (stream));
- gvc_channel_bar_set_is_amplified (GVC_CHANNEL_BAR (dialog->priv->output_bar),
- flags & MATE_MIXER_STREAM_HAS_DECIBEL_VOLUME);
+ /* Enable balance bar if stream feature is available */
+ if (flags & MATE_MIXER_STREAM_CAN_BALANCE) {
+ dialog->priv->output_balance_bar =
+ gvc_balance_bar_new (stream, BALANCE_TYPE_RL);
- dialog->priv->output_balance_bar = gvc_balance_bar_new (stream, BALANCE_TYPE_RL);
- if (dialog->priv->size_group != NULL) {
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;
}
- 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);
+ /* Enable fade bar if stream feature is available */
if (flags & MATE_MIXER_STREAM_CAN_FADE) {
- dialog->priv->output_fade_bar = gvc_balance_bar_new (stream, BALANCE_TYPE_FR);
- if (dialog->priv->size_group != NULL) {
- gvc_balance_bar_set_size_group (GVC_BALANCE_BAR (dialog->priv->output_fade_bar),
- dialog->priv->size_group,
- TRUE);
- }
+ dialog->priv->output_fade_bar =
+ gvc_balance_bar_new (stream, 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;
}
- if (mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_LFE)) {
- dialog->priv->output_lfe_bar = gvc_balance_bar_new (stream, BALANCE_TYPE_LFE);
- if (dialog->priv->size_group != NULL) {
- gvc_balance_bar_set_size_group (GVC_BALANCE_BAR (dialog->priv->output_lfe_bar),
- dialog->priv->size_group,
- TRUE);
- }
+ /* Enable subwoofer volume bar if subwoofer is available */
+ if (mate_mixer_stream_has_channel_position (stream, MATE_MIXER_CHANNEL_LFE)) {
+ dialog->priv->output_lfe_bar =
+ gvc_balance_bar_new (stream, 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;
}
ports = mate_mixer_stream_list_ports (stream);
@@ -304,180 +384,149 @@ update_output_settings (GvcMixerDialog *dialog)
MateMixerPort *port;
port = mate_mixer_stream_get_active_port (stream);
+ if (G_UNLIKELY (port == NULL)) {
+ /* Select the first port if none is selected at the moment */
+ port = MATE_MIXER_PORT (ports->data);
+ mate_mixer_stream_set_active_port (stream, port);
+ }
- 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),
- mate_mixer_port_get_name (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_port_combo =
+ create_port_combo_box (dialog,
+ stream,
+ _("Co_nnector:"),
+ ports,
+ mate_mixer_port_get_name (port));
gtk_box_pack_start (GTK_BOX (dialog->priv->output_settings_box),
dialog->priv->output_port_combo,
TRUE, FALSE, 6);
- gvc_combo_box_set_size_group (GVC_COMBO_BOX (dialog->priv->output_port_combo), dialog->priv->size_group, FALSE);
-
gtk_widget_show (dialog->priv->output_port_combo);
+ has_settings = TRUE;
}
- /* FIXME: We could make this into a "No settings" label instead */
- gtk_widget_set_sensitive (dialog->priv->output_balance_bar, flags & MATE_MIXER_STREAM_CAN_BALANCE);
+ if (has_settings == TRUE)
+ gtk_widget_show (dialog->priv->output_settings_frame);
+ else
+ gtk_widget_hide (dialog->priv->output_settings_frame);
}
static void
-update_default_output (GvcMixerDialog *dialog)
+on_control_default_output_notify (MateMixerControl *control,
+ GParamSpec *pspec,
+ 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 = FALSE;
- gchar *name;
- MateMixerStream *stream;
+ GtkTreeModel *model;
+ MateMixerStream *stream;
- gtk_tree_model_get (model, &iter,
- NAME_COLUMN, &name,
- ACTIVE_COLUMN, &toggled,
- -1);
+ stream = mate_mixer_control_get_default_output_stream (control);
+ if (stream != NULL) {
+ GList *streams;
- stream = mate_mixer_control_get_stream (dialog->priv->control, name);
- if (stream == NULL) {
- g_warning ("Unable to find stream for id: %s", name);
- g_free (name);
- continue;
- }
+ streams = (GList *) mate_mixer_control_list_cached_streams (dialog->priv->control);
- if (stream == mate_mixer_control_get_default_output_stream (dialog->priv->control))
- is_default = TRUE;
+ /* Move all cached stream to the newly selected default stream */
+ while (streams) {
+ MateMixerStream *parent;
+ MateMixerClientStream *client = MATE_MIXER_CLIENT_STREAM (streams->data);
- gtk_list_store_set (GTK_LIST_STORE (model),
- &iter,
- ACTIVE_COLUMN, is_default,
- -1);
- g_free (name);
- } while (gtk_tree_model_iter_next (model, &iter));
-}
+ parent = mate_mixer_client_stream_get_parent (client);
-static void
-on_control_default_output_notify (MateMixerControl *control,
- GParamSpec *pspec,
- GvcMixerDialog *dialog)
-{
- MateMixerStream *stream;
+ if (parent != stream) {
+ MateMixerStreamFlags flags;
- g_debug ("Default output stream has changed");
+ flags = mate_mixer_stream_get_flags (MATE_MIXER_STREAM (client));
- stream = mate_mixer_control_get_default_output_stream (control);
+ if (flags & MATE_MIXER_STREAM_OUTPUT)
+ mate_mixer_client_stream_set_parent (client, stream);
+ }
+ streams = streams->next;
+ }
+ }
bar_set_stream (dialog, dialog->priv->output_bar, stream);
- update_output_settings (dialog);
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
+ update_default_item (dialog, model, stream);
- update_default_output (dialog);
+ update_output_settings (dialog);
}
-
#define DECAY_STEP .15
static void
-update_input_peak (GvcMixerDialog *dialog, gdouble v)
+on_stream_monitor_value (MateMixerStream *stream,
+ gdouble value,
+ GvcMixerDialog *dialog)
{
GtkAdjustment *adj;
if (dialog->priv->last_input_peak >= DECAY_STEP) {
- if (v < dialog->priv->last_input_peak - DECAY_STEP) {
- v = 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 = v;
+ dialog->priv->last_input_peak = value;
adj = gvc_level_bar_get_peak_adjustment (GVC_LEVEL_BAR (dialog->priv->input_level_bar));
- if (v >= 0) {
- gtk_adjustment_set_value (adj, v);
- } else {
+ if (value >= 0)
+ gtk_adjustment_set_value (adj, value);
+ else
gtk_adjustment_set_value (adj, 0.0);
- }
-}
-
-static void
-on_stream_monitor_value (MateMixerStream *stream,
- gdouble value,
- GvcMixerDialog *dialog)
-{
- g_debug ("Monitor %.2f", value);
- update_input_peak (dialog, value);
}
static void
update_input_settings (GvcMixerDialog *dialog)
{
- MateMixerStream *stream;
+ MateMixerStream *stream;
MateMixerStreamFlags flags;
- const GList *ports;
+ const GList *ports;
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;
}
stream = mate_mixer_control_get_default_input_stream (dialog->priv->control);
if (stream == NULL) {
- g_debug ("Default source stream not found");
+ g_debug ("There is no default input stream");
return;
}
- mate_mixer_stream_monitor_set_name (stream, _("Peak detect"));
-
- g_signal_connect (G_OBJECT (stream),
- "monitor-value",
- G_CALLBACK (on_stream_monitor_value),
- dialog);
-
flags = mate_mixer_stream_get_flags (stream);
- gvc_channel_bar_set_base_volume (GVC_CHANNEL_BAR (dialog->priv->input_bar),
- mate_mixer_stream_get_base_volume (stream));
+ /* Enable level bar only if supported by the stream */
+ if (flags & MATE_MIXER_STREAM_HAS_MONITOR) {
+ mate_mixer_stream_monitor_set_name (stream, _("Peak detect"));
- // XXX probably wrong
- gvc_channel_bar_set_is_amplified (GVC_CHANNEL_BAR (dialog->priv->input_bar),
- flags & MATE_MIXER_STREAM_HAS_DECIBEL_VOLUME);
+ g_signal_connect (G_OBJECT (stream),
+ "monitor-value",
+ G_CALLBACK (on_stream_monitor_value),
+ dialog);
+ }
ports = mate_mixer_stream_list_ports (stream);
if (ports != NULL) {
MateMixerPort *port;
port = mate_mixer_stream_get_active_port (stream);
+ if (G_UNLIKELY (port == NULL)) {
+ /* Select the first port if none is selected at the moment */
+ port = MATE_MIXER_PORT (ports->data);
+ mate_mixer_stream_set_active_port (stream, port);
+ }
- 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),
- mate_mixer_port_get_name (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);
-
- gvc_combo_box_set_size_group (GVC_COMBO_BOX (dialog->priv->input_port_combo),
- dialog->priv->size_group,
- FALSE);
+ dialog->priv->input_port_combo =
+ create_port_combo_box (dialog,
+ stream,
+ _("Co_nnector:"),
+ ports,
+ mate_mixer_port_get_name (port));
gtk_box_pack_start (GTK_BOX (dialog->priv->input_settings_box),
dialog->priv->input_port_combo,
@@ -492,361 +541,332 @@ on_control_default_input_notify (MateMixerControl *control,
GParamSpec *pspec,
GvcMixerDialog *dialog)
{
+ GtkTreeModel *model;
MateMixerStream *stream;
MateMixerStream *current;
- GtkAdjustment *adj;
- stream = mate_mixer_control_get_default_input_stream (control);
+ g_debug ("Default input stream has changed");
- current = g_object_get_data (G_OBJECT (dialog->priv->input_bar), "gvc-mixer-dialog-stream");
- if (current != NULL)
+ current = gvc_channel_bar_get_stream (GVC_CHANNEL_BAR (dialog->priv->input_bar));
+ if (current != NULL) {
+ /* Make sure to disable monitoring of the removed stream */
g_signal_handlers_disconnect_by_func (G_OBJECT (current),
- on_stream_monitor_value,
+ G_CALLBACK (on_stream_monitor_value),
dialog);
- if (gtk_notebook_get_current_page (GTK_NOTEBOOK (dialog->priv->notebook)) == PAGE_INPUT) {
- if (current != NULL)
- mate_mixer_stream_monitor_stop (current);
- if (stream != NULL)
- mate_mixer_stream_monitor_start (stream);
+ mate_mixer_stream_monitor_stop (current);
}
- // g_debug ("GvcMixerDialog: default source changed: %u", id);
-
- // XXX is the default input reffed/unreffed anywhere?
-
- /* 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);
+ stream = mate_mixer_control_get_default_input_stream (control);
+ if (stream != NULL) {
+ GList *streams;
+ guint page = gtk_notebook_get_current_page (GTK_NOTEBOOK (dialog->priv->notebook));
- update_default_input (dialog);
-}
+ streams = (GList *) mate_mixer_control_list_cached_streams (dialog->priv->control);
-static void
-on_adjustment_value_changed (GtkAdjustment *adjustment,
- GvcMixerDialog *dialog)
-{
- MateMixerStream *stream;
+ /* Move all cached stream to the newly selected default stream */
+ while (streams) {
+ MateMixerStream *parent;
+ MateMixerClientStream *client = MATE_MIXER_CLIENT_STREAM (streams->data);
- stream = g_object_get_data (G_OBJECT (adjustment), "gvc-mixer-dialog-stream");
- if (stream != NULL) {
- GObject *bar;
- gdouble volume, rounded;
- char *name;
+ parent = mate_mixer_client_stream_get_parent (client);
- volume = gtk_adjustment_get_value (adjustment);
- rounded = round (volume);
+ if (parent != stream) {
+ MateMixerStreamFlags flags;
- bar = g_object_get_data (G_OBJECT (adjustment), "gvc-mixer-dialog-bar");
- g_object_get (bar, "name", &name, NULL);
- g_debug ("Setting stream volume %lf (rounded: %lf) for bar '%s'", volume, rounded, name);
- g_free (name);
+ flags = mate_mixer_stream_get_flags (MATE_MIXER_STREAM (client));
- /* FIXME would need to do that in the balance bar really... */
- /* Make sure we do not unmute muted streams, there's a button for that */
- if (volume == 0.0)
- mate_mixer_stream_set_mute (stream, TRUE);
+ if (flags & MATE_MIXER_STREAM_INPUT)
+ mate_mixer_client_stream_set_parent (client, stream);
+ }
+ streams = streams->next;
+ }
- mate_mixer_stream_set_volume (stream, rounded);
+ if (page == PAGE_INPUT)
+ mate_mixer_stream_monitor_start (stream);
}
-}
-
-static void
-on_bar_is_muted_notify (GObject *object,
- GParamSpec *pspec,
- GvcMixerDialog *dialog)
-{
- gboolean is_muted;
- MateMixerStream *stream;
- is_muted = gvc_channel_bar_get_is_muted (GVC_CHANNEL_BAR (object));
+ bar_set_stream (dialog, dialog->priv->input_bar, stream);
- stream = g_object_get_data (object, "gvc-mixer-dialog-stream");
- if (stream != NULL) {
- mate_mixer_stream_set_mute (stream, is_muted);
- } else {
- char *name;
- g_object_get (object, "name", &name, NULL);
- g_warning ("Unable to find stream for bar '%s'", name);
- g_free (name);
- }
-}
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
+ update_default_item (dialog, model, stream);
-static GtkWidget *
-lookup_bar_for_stream (GvcMixerDialog *dialog, MateMixerStream *stream)
-{
- return g_hash_table_lookup (dialog->priv->bars, mate_mixer_stream_get_name (stream));
+ update_input_settings (dialog);
}
-static GtkWidget *
-lookup_combo_box_for_stream (GvcMixerDialog *dialog,
- MateMixerStream *stream)
+static GvcComboBox *
+find_combo_box_by_stream (GvcMixerDialog *dialog, MateMixerStream *stream)
{
MateMixerStream *combo_stream;
- const gchar *name;
-
- name = mate_mixer_stream_get_name (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 (!g_strcmp0 (name, mate_mixer_stream_get_name (combo_stream)))
- return dialog->priv->output_port_combo;
- }
+ if (combo_stream == stream)
+ return GVC_COMBO_BOX (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 (!g_strcmp0 (name, mate_mixer_stream_get_name (combo_stream)))
- return dialog->priv->input_port_combo;
- }
+ if (combo_stream == stream)
+ return GVC_COMBO_BOX (dialog->priv->input_port_combo);
}
-
return NULL;
}
static void
on_stream_description_notify (MateMixerStream *stream,
- GParamSpec *pspec,
- GvcMixerDialog *dialog)
+ GParamSpec *pspec,
+ GvcMixerDialog *dialog)
{
- update_description (dialog, NAME_COLUMN,
- mate_mixer_stream_get_description (stream),
- stream);
-}
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ MateMixerStreamFlags flags;
-static void
-on_stream_port_notify (GObject *object,
- GParamSpec *pspec,
- GvcMixerDialog *dialog)
-{
- GvcComboBox *combo;
- MateMixerPort *port;
+ flags = mate_mixer_stream_get_flags (stream);
- combo = GVC_COMBO_BOX (lookup_combo_box_for_stream (dialog, MATE_MIXER_STREAM (object)));
- if (combo == NULL)
- return;
+ if (flags & MATE_MIXER_STREAM_INPUT)
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
+ else
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
- g_signal_handlers_block_by_func (G_OBJECT (combo),
- port_selection_changed,
- dialog);
+ if (find_tree_item_by_name (model,
+ mate_mixer_stream_get_name (stream),
+ NAME_COLUMN,
+ &iter) == TRUE) {
+ const gchar *description;
- g_object_get (object, "active-port", &port, NULL);
- // XXX is this correct?
- if (port) {
- gvc_combo_box_set_active (GVC_COMBO_BOX (combo),
- mate_mixer_port_get_name (port));
+ description = mate_mixer_stream_get_description (stream);
+ gtk_list_store_set (GTK_LIST_STORE (model),
+ &iter,
+ DESCRIPTION_COLUMN, description,
+ -1);
}
-
- g_signal_handlers_unblock_by_func (G_OBJECT (combo),
- port_selection_changed,
- dialog);
}
static void
-on_stream_volume_notify (GObject *object,
- GParamSpec *pspec,
- GvcMixerDialog *dialog)
+on_stream_port_notify (MateMixerStream *stream,
+ GParamSpec *pspec,
+ GvcMixerDialog *dialog)
{
- MateMixerStream *stream;
- GtkWidget *bar;
- GtkAdjustment *adj;
-
- stream = MATE_MIXER_STREAM (object);
-
- bar = lookup_bar_for_stream (dialog, stream);
+ GvcComboBox *combobox;
+ MateMixerPort *port;
- if (bar == NULL) {
- g_warning ("Unable to find bar for stream %s in on_stream_volume_notify()",
- mate_mixer_stream_get_name (stream));
+ combobox = find_combo_box_by_stream (dialog, stream);
+ if (G_UNLIKELY (combobox == NULL)) {
+ g_warn_if_reached ();
return;
}
- adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (bar)));
+ g_debug ("Stream %s port has changed",
+ mate_mixer_stream_get_name (stream));
- g_signal_handlers_block_by_func (adj,
- on_adjustment_value_changed,
+ g_signal_handlers_block_by_func (G_OBJECT (combobox),
+ on_combo_box_port_changed,
dialog);
- gtk_adjustment_set_value (adj,
- mate_mixer_stream_get_volume (stream));
+ port = mate_mixer_stream_get_active_port (stream);
+ if (G_LIKELY (port != NULL)) {
+ const gchar *name = mate_mixer_port_get_name (port);
+
+ g_debug ("The current port is %s", name);
- g_signal_handlers_unblock_by_func (adj,
- on_adjustment_value_changed,
+ gvc_combo_box_set_active (GVC_COMBO_BOX (combobox), name);
+ }
+
+ g_signal_handlers_unblock_by_func (G_OBJECT (combobox),
+ on_combo_box_port_changed,
dialog);
}
static void
-on_stream_mute_notify (GObject *object,
- GParamSpec *pspec,
- GvcMixerDialog *dialog)
+on_stream_mute_notify (MateMixerStream *stream,
+ GParamSpec *pspec,
+ GvcMixerDialog *dialog)
{
- MateMixerStream *stream;
- GtkWidget *bar;
- gboolean is_muted;
-
- stream = MATE_MIXER_STREAM (object);
- bar = lookup_bar_for_stream (dialog, stream);
-
- if (bar == NULL) {
- g_warning ("Unable to find bar for stream %s in on_stream_is_muted_notify()",
- mate_mixer_stream_get_name (stream));
- return;
- }
+ MateMixerStream *input;
- is_muted = mate_mixer_stream_get_mute (stream);
- gvc_channel_bar_set_is_muted (GVC_CHANNEL_BAR (bar), is_muted);
+ input = mate_mixer_control_get_default_input_stream (dialog->priv->control);
- if (stream == mate_mixer_control_get_default_output_stream (dialog->priv->control)) {
- gtk_widget_set_sensitive (dialog->priv->applications_box,
- !is_muted);
+ /* Stop monitoring the input stream when it gets muted */
+ if (stream == input) {
+ if (mate_mixer_stream_get_mute (stream))
+ mate_mixer_stream_monitor_stop (stream);
+ else
+ mate_mixer_stream_monitor_start (stream);
}
-
-}
-
-static void
-save_bar_for_stream (GvcMixerDialog *dialog,
- MateMixerStream *stream,
- GtkWidget *bar)
-{
- g_hash_table_insert (dialog->priv->bars,
- (gpointer) mate_mixer_stream_get_name (stream),
- bar);
}
static GtkWidget *
-create_bar (GvcMixerDialog *dialog,
- GtkSizeGroup *size_group,
- gboolean symmetric)
+create_bar (GvcMixerDialog *dialog, gboolean use_size_group, gboolean symmetric)
{
GtkWidget *bar;
- bar = gvc_channel_bar_new ();
- gtk_widget_set_sensitive (bar, FALSE);
- if (size_group != NULL) {
+ bar = gvc_channel_bar_new (NULL);
+
+ if (use_size_group == TRUE)
gvc_channel_bar_set_size_group (GVC_CHANNEL_BAR (bar),
- size_group,
+ dialog->priv->size_group,
symmetric);
- }
- gvc_channel_bar_set_orientation (GVC_CHANNEL_BAR (bar),
- GTK_ORIENTATION_HORIZONTAL);
- gvc_channel_bar_set_show_mute (GVC_CHANNEL_BAR (bar),
- TRUE);
- g_signal_connect (bar,
- "notify::is-muted",
- G_CALLBACK (on_bar_is_muted_notify),
- dialog);
+
+ 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)
+bar_set_stream (GvcMixerDialog *dialog,
+ GtkWidget *bar,
+ MateMixerStream *stream)
{
- GtkAdjustment *adj;
- MateMixerStream *old_stream;
+ MateMixerStream *previous;
- old_stream = g_object_get_data (G_OBJECT (bar), "gvc-mixer-dialog-stream");
- if (old_stream != NULL) {
- char *name;
+ previous = gvc_channel_bar_get_stream (GVC_CHANNEL_BAR (bar));
+ if (previous != NULL) {
+ const gchar *name = mate_mixer_stream_get_name (previous);
- g_object_get (bar, "name", &name, NULL);
- g_debug ("Disconnecting old stream '%s' from bar '%s'",
- mate_mixer_stream_get_name (old_stream), name);
- g_free (name);
+ g_debug ("Disconnecting old stream %s", name);
+
+ g_signal_handlers_disconnect_by_func (previous,
+ on_stream_mute_notify,
+ dialog);
+ g_signal_handlers_disconnect_by_func (previous,
+ on_stream_port_notify,
+ dialog);
- g_signal_handlers_disconnect_by_func (old_stream, on_stream_mute_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);
+ if (mate_mixer_stream_get_flags (previous) & MATE_MIXER_STREAM_INPUT)
+ mate_mixer_stream_monitor_stop (previous);
g_hash_table_remove (dialog->priv->bars, name);
}
- gtk_widget_set_sensitive (bar, (stream != NULL));
-
- adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (bar)));
-
- // XXX already done in notify
- g_signal_handlers_disconnect_by_func (adj, on_adjustment_value_changed, dialog);
-
- g_object_set_data (G_OBJECT (bar), "gvc-mixer-dialog-stream", stream);
- g_object_set_data (G_OBJECT (adj), "gvc-mixer-dialog-stream", stream);
- g_object_set_data (G_OBJECT (adj), "gvc-mixer-dialog-bar", bar);
+ gvc_channel_bar_set_stream (GVC_CHANNEL_BAR (bar), stream);
if (stream != NULL) {
- gboolean is_muted;
+ const gchar *name = mate_mixer_stream_get_name (stream);
- is_muted = mate_mixer_stream_get_mute (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, mate_mixer_stream_get_volume (stream));
+ g_debug ("Connecting new stream %s", name);
g_signal_connect (stream,
"notify::mute",
G_CALLBACK (on_stream_mute_notify),
dialog);
g_signal_connect (stream,
- "notify::volume",
- G_CALLBACK (on_stream_volume_notify),
- dialog);
- g_signal_connect (stream,
"notify::active-port",
G_CALLBACK (on_stream_port_notify),
dialog);
- g_signal_connect (adj,
- "value-changed",
- G_CALLBACK (on_adjustment_value_changed),
- dialog);
+
+ g_hash_table_insert (dialog->priv->bars, (gpointer) name, bar);
}
+
+ gtk_widget_set_sensitive (GTK_WIDGET (bar), (stream != NULL));
}
static void
add_stream (GvcMixerDialog *dialog, MateMixerStream *stream)
{
- GtkWidget *bar = NULL;
- gboolean is_default = FALSE;
- MateMixerClientStream *client = NULL;
- MateMixerStreamFlags flags;
+ GtkWidget *bar = NULL;
+ MateMixerStreamFlags flags;
flags = mate_mixer_stream_get_flags (stream);
- if (flags & MATE_MIXER_STREAM_EVENT)
- return;
- if (flags & MATE_MIXER_STREAM_APPLICATION) {
- const gchar *app_id;
+ if (MATE_MIXER_IS_CLIENT_STREAM (stream)) {
+ MateMixerClientStream *client ;
+ MateMixerClientStreamFlags client_flags;
+ MateMixerClientStreamRole client_role;
+ const gchar *name;
+ const gchar *icon;
- client = MATE_MIXER_CLIENT_STREAM (stream);
- app_id = mate_mixer_client_stream_get_app_id (client);
+ client = MATE_MIXER_CLIENT_STREAM (stream);
+ client_flags = mate_mixer_client_stream_get_flags (client);
+ client_role = mate_mixer_client_stream_get_role (client);
- /* These applications are not displayed on the Applications tab */
- if (!g_strcmp0 (app_id, "org.mate.VolumeControl") ||
- !g_strcmp0 (app_id, "org.gnome.VolumeControl") ||
- !g_strcmp0 (app_id, "org.PulseAudio.pavucontrol"))
- return;
- }
+ /* We use a cached event stream for the effects volume slider,
+ * because regular streams are only created when an event sound
+ * is played and then immediately destroyed.
+ * The cached event stream should exist all the time. */
+ if (client_flags & MATE_MIXER_CLIENT_STREAM_CACHED &&
+ client_role == MATE_MIXER_CLIENT_STREAM_ROLE_EVENT) {
+ g_debug ("Found cached event role stream %s",
+ mate_mixer_stream_get_name (stream));
+
+ bar = dialog->priv->effects_bar;
+ }
- if (client == NULL) {
+ /* Add stream to the applications page, but make sure the stream
+ * qualifies for the inclusion */
+ if (client_flags & MATE_MIXER_CLIENT_STREAM_APPLICATION) {
+ const gchar *app_id;
+
+ /* Skip streams with roles we don't care about */
+ if (client_role == MATE_MIXER_CLIENT_STREAM_ROLE_EVENT ||
+ client_role == MATE_MIXER_CLIENT_STREAM_ROLE_TEST ||
+ client_role == MATE_MIXER_CLIENT_STREAM_ROLE_ABSTRACT ||
+ client_role == MATE_MIXER_CLIENT_STREAM_ROLE_FILTER)
+ return;
+
+ app_id = mate_mixer_client_stream_get_app_id (client);
+
+ /* 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;
+
+ name = mate_mixer_client_stream_get_app_name (client);
+ if (name == NULL)
+ name = mate_mixer_stream_get_description (stream);
+ if (name == NULL)
+ name = mate_mixer_stream_get_name (stream);
+ if (G_UNLIKELY (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 */
+ if (flags & MATE_MIXER_STREAM_INPUT)
+ g_object_set (G_OBJECT (bar),
+ "low-icon-name", "audio-input-microphone-low",
+ "high-icon-name", "audio-input-microphone-high",
+ NULL);
+
+ icon = mate_mixer_client_stream_get_app_icon (client);
+ if (icon == NULL) {
+ if (flags & MATE_MIXER_STREAM_INPUT)
+ icon = "audio-input-microphone";
+ else
+ icon = "applications-multimedia";
+ }
+
+ gvc_channel_bar_set_name (GVC_CHANNEL_BAR (bar), name);
+ gvc_channel_bar_set_icon_name (GVC_CHANNEL_BAR (bar), icon);
+
+ gtk_box_pack_start (GTK_BOX (dialog->priv->applications_box),
+ bar,
+ FALSE, FALSE, 12);
+
+ gtk_widget_hide (dialog->priv->no_apps_label);
+ dialog->priv->num_apps++;
+ }
+ } else {
GtkTreeModel *model = NULL;
GtkTreeIter iter;
MateMixerStream *input;
MateMixerStream *output;
const gchar *speakers = NULL;
- GtkAdjustment *adj;
+ gboolean is_default = FALSE;
input = mate_mixer_control_get_default_input_stream (dialog->priv->control);
output = mate_mixer_control_get_default_output_stream (dialog->priv->control);
@@ -854,28 +874,17 @@ add_stream (GvcMixerDialog *dialog, MateMixerStream *stream)
if (flags & MATE_MIXER_STREAM_INPUT) {
if (stream == input) {
bar = dialog->priv->input_bar;
- adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (bar)));
- g_signal_handlers_disconnect_by_func (G_OBJECT (adj),
- on_adjustment_value_changed,
- dialog);
update_input_settings (dialog);
is_default = TRUE;
}
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
-
- } else if (flags & MATE_MIXER_STREAM_OUTPUT) {
+ }
+ else if (flags & MATE_MIXER_STREAM_OUTPUT) {
if (stream == output) {
bar = dialog->priv->output_bar;
- adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (bar)));
-
- gtk_widget_set_sensitive (dialog->priv->applications_box,
- mate_mixer_stream_get_mute (stream) == FALSE);
- g_signal_handlers_disconnect_by_func (G_OBJECT (adj),
- on_adjustment_value_changed,
- dialog);
update_output_settings (dialog);
is_default = TRUE;
}
@@ -885,23 +894,8 @@ add_stream (GvcMixerDialog *dialog, MateMixerStream *stream)
}
if (model != NULL) {
- MateMixerDevice *device;
- const gchar *name,
- *description;
- const gchar *device_name = NULL;
- const gchar *icon = NULL;
-
- device = mate_mixer_stream_get_device (stream);
- if (G_LIKELY (device != NULL)) {
- device_name = mate_mixer_device_get_description (device);
- if (device_name == NULL)
- device_name = mate_mixer_device_get_name (device);
-
- icon = mate_mixer_device_get_icon (device);
- }
-
- if (icon == NULL)
- icon = "audio-card";
+ const gchar *name;
+ const gchar *description;
name = mate_mixer_stream_get_name (stream);
description = mate_mixer_stream_get_description (stream);
@@ -911,7 +905,6 @@ add_stream (GvcMixerDialog *dialog, MateMixerStream *stream)
&iter,
NAME_COLUMN, name,
DESCRIPTION_COLUMN, description,
- DEVICE_COLUMN, device_name,
ACTIVE_COLUMN, is_default,
SPEAKERS_COLUMN, speakers,
-1);
@@ -921,48 +914,6 @@ add_stream (GvcMixerDialog *dialog, MateMixerStream *stream)
G_CALLBACK (on_stream_description_notify),
dialog);
}
- } else {
- const gchar *name;
- const gchar *icon;
-
- bar = create_bar (dialog, dialog->priv->apps_size_group, FALSE);
-
- // FIXME:
- // 1) We should ideally provide application name on the first line and
- // description on a second line in italics
- // 2) We should watch for name changes as it may include for example
- // the name of the current song
- name = mate_mixer_client_stream_get_app_name (client);
- if (name == NULL)
- name = mate_mixer_stream_get_description (stream);
- if (name == NULL)
- name = mate_mixer_stream_get_name (stream);
-
- if (name == NULL || strchr (name, '_') == NULL) {
- gvc_channel_bar_set_name (GVC_CHANNEL_BAR (bar), name);
- } else {
- char **tokens, *escaped;
-
- // XXX why is this here?
- tokens = g_strsplit (name, "_", -1);
- escaped = g_strjoinv ("__", tokens);
- g_strfreev (tokens);
- gvc_channel_bar_set_name (GVC_CHANNEL_BAR (bar), escaped);
- g_free (escaped);
- }
-
- icon = mate_mixer_client_stream_get_app_icon (client);
- if (icon == NULL) {
- /* If there is no name of the application icon, set a default */
- icon = "applications-multimedia";
- }
-
- gvc_channel_bar_set_icon_name (GVC_CHANNEL_BAR (bar), icon);
-
- gtk_box_pack_start (GTK_BOX (dialog->priv->applications_box), bar, FALSE, FALSE, 12);
- gtk_widget_hide (dialog->priv->no_apps_label);
-
- dialog->priv->num_apps++;
}
if (bar != NULL) {
@@ -980,80 +931,61 @@ on_control_stream_added (MateMixerControl *control,
GtkWidget *bar;
bar = g_hash_table_lookup (dialog->priv->bars, name);
- if (bar != NULL) {
- g_debug ("Ignoring already known stream %s", name);
+ if (G_UNLIKELY (bar != NULL))
return;
- }
stream = mate_mixer_control_get_stream (control, name);
- if (G_LIKELY (stream != NULL))
- add_stream (dialog, stream);
-}
-
-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));
+ if (G_UNLIKELY (stream == NULL))
+ return;
- return found;
+ add_stream (dialog, stream);
}
static void
remove_stream (GvcMixerDialog *dialog, const gchar *name)
{
GtkWidget *bar;
- gboolean found;
GtkTreeIter iter;
GtkTreeModel *model;
- /* remove bars for applications and reset fixed bars */
+ /* Remove bars for applications and reset fixed bars */
bar = g_hash_table_lookup (dialog->priv->bars, name);
- if (bar == dialog->priv->output_bar
- || bar == dialog->priv->input_bar
- || bar == dialog->priv->effects_bar) { // XXX effects bad? verify this!
- char *bar_name;
- g_object_get (bar, "name", &bar_name, NULL);
- g_debug ("Removing stream for bar '%s'", bar_name);
- g_free (bar_name);
+
+ if (bar == dialog->priv->input_bar || bar == dialog->priv->output_bar) {
+ g_debug ("Removing stream %s from bar %s",
+ name,
+ gvc_channel_bar_get_name (GVC_CHANNEL_BAR (bar)));
+
bar_set_stream (dialog, bar, NULL);
} else if (bar != NULL) {
+ g_debug ("Removing application stream %s", name);
+
g_hash_table_remove (dialog->priv->bars, name);
- 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);
+ 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;
}
+
+ if (--dialog->priv->num_apps == 0)
+ gtk_widget_show (dialog->priv->no_apps_label);
}
- /* remove from any models */
+ /* Remove from any models */
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
- found = find_tree_item_by_name (GTK_TREE_MODEL (model), name, NAME_COLUMN, &iter);
- if (found) {
+ 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));
- found = find_tree_item_by_name (GTK_TREE_MODEL (model), name, NAME_COLUMN, &iter);
- if (found) {
+ 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
@@ -1064,8 +996,28 @@ on_control_stream_removed (MateMixerControl *control,
remove_stream (dialog, name);
}
+static void
+on_control_cached_stream_removed (MateMixerControl *control,
+ const gchar *name,
+ GvcMixerDialog *dialog)
+{
+ GtkWidget *bar;
+
+ bar = g_hash_table_lookup (dialog->priv->bars, name);
+
+ if (bar != NULL) {
+ /* We only use a cached stream 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 *
-card_profile_status (MateMixerDeviceProfile *profile)
+device_profile_status (MateMixerDeviceProfile *profile)
{
guint inputs;
guint outputs;
@@ -1099,7 +1051,7 @@ card_profile_status (MateMixerDeviceProfile *profile)
inputs);
}
- if (inputs_str == NULL && outputs_str == NULL) {
+ if (inputs_str != NULL && outputs_str != NULL) {
gchar *ret = g_strdup_printf ("%s / %s",
outputs_str,
inputs_str);
@@ -1115,92 +1067,129 @@ card_profile_status (MateMixerDeviceProfile *profile)
}
static void
-add_device (GvcMixerDialog *dialog, MateMixerDevice *device)
+update_device_info (GvcMixerDialog *dialog, MateMixerDevice *device)
{
- GtkTreeModel *model;
- GtkTreeIter iter;
- GtkTreeSelection *selection;
+ GtkTreeModel *model = NULL;
+ GtkTreeIter iter;
MateMixerDeviceProfile *profile;
- GIcon *icon;
- const gchar *name;
- const gchar *profile_name;
- gchar *profile_status;
+ const gchar *description;
+ const gchar *profile_description = NULL;
+ gchar *profile_status = NULL;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview));
- name = mate_mixer_device_get_name (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);
- profile = mate_mixer_device_get_active_profile (device);
- g_assert (profile != NULL);
- icon = g_themed_icon_new_with_default_fallbacks (mate_mixer_device_get_icon (device));
+ if (find_tree_item_by_name (model,
+ mate_mixer_device_get_name (device),
+ HW_NAME_COLUMN,
+ &iter) == FALSE)
+ return;
- //FIXME we need the status (default for a profile?) here
+ description = mate_mixer_device_get_description (device);
- profile_name = mate_mixer_device_profile_get_name (profile);
- profile_status = card_profile_status (profile);
+ profile = mate_mixer_device_get_active_profile (device);
+ if (profile != NULL) {
+ profile_description = mate_mixer_device_profile_get_description (profile);
+ profile_status = device_profile_status (profile);
+ }
gtk_list_store_set (GTK_LIST_STORE (model),
&iter,
- HW_NAME_COLUMN, mate_mixer_device_get_name (device),
- HW_DESCRIPTION_COLUMN, mate_mixer_device_get_description (device),
- HW_ICON_COLUMN, icon,
- HW_PROFILE_COLUMN, profile_name,
- HW_PROFILE_HUMAN_COLUMN, mate_mixer_device_profile_get_description (profile),
+ HW_DESCRIPTION_COLUMN, description,
+ HW_PROFILE_COLUMN, profile_description,
HW_STATUS_COLUMN, profile_status,
- HW_SENSITIVE_COLUMN, g_strcmp0 (profile_name, "off") != 0,
-1);
g_free (profile_status);
+}
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->hw_treeview));
+static void
+on_device_profile_notify (MateMixerDevice *device,
+ GParamSpec *pspec,
+ GvcMixerDialog *dialog)
+{
+ MateMixerDeviceProfile *profile;
- if (gtk_tree_selection_get_selected (selection, NULL, NULL) == FALSE) {
- /* Select the currently added item if nothing is selected now */
- gtk_tree_selection_select_iter (selection, &iter);
- } else if (dialog->priv->hw_profile_combo != NULL) {
- MateMixerDevice *selected;
+ g_debug ("Device profile has changed");
- /* Set the current profile if it changed for the selected card */
- selected = g_object_get_data (G_OBJECT (dialog->priv->hw_profile_combo), "device");
+ g_signal_handlers_block_by_func (G_OBJECT (dialog->priv->hw_profile_combo),
+ G_CALLBACK (on_combo_box_profile_changed),
+ dialog);
- if (!g_strcmp0 (mate_mixer_device_get_name (device),
- mate_mixer_device_get_name (selected))) {
- gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->hw_profile_combo),
- profile_name);
+ profile = mate_mixer_device_get_active_profile (device);
+ if (G_LIKELY (profile != NULL)) {
+ const gchar *name = mate_mixer_device_profile_get_name (profile);
- g_object_set (G_OBJECT (dialog->priv->hw_profile_combo),
- "show-button",
- mate_mixer_device_profile_get_num_output_streams (profile) >= 1,
- NULL);
- }
+ g_debug ("The current profile is %s", name);
+
+ 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_combo_box_profile_changed),
+ dialog);
+
+ update_device_info (dialog, device);
}
static void
-on_control_device_added (MateMixerControl *control, const gchar *name, GvcMixerDialog *dialog)
+add_device (GvcMixerDialog *dialog, MateMixerDevice *device)
{
- MateMixerDevice *device;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ MateMixerDeviceProfile *profile;
+ GIcon *icon;
+ const gchar *name;
+ const gchar *description;
+ const gchar *profile_description = NULL;
+ gchar *profile_status = NULL;
- device = mate_mixer_control_get_device (control, name);
- if (device != NULL)
- add_device (dialog, device);
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview));
+
+ name = mate_mixer_device_get_name (device);
+ description = mate_mixer_device_get_description (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 = mate_mixer_device_get_active_profile (device);
+ if (profile != NULL) {
+ profile_description = mate_mixer_device_profile_get_description (profile);
+ profile_status = device_profile_status (profile);
+ }
+
+ gtk_list_store_set (GTK_LIST_STORE (model),
+ &iter,
+ HW_NAME_COLUMN, name,
+ HW_DESCRIPTION_COLUMN, description,
+ HW_ICON_COLUMN, icon,
+ HW_PROFILE_COLUMN, profile_description,
+ HW_STATUS_COLUMN, profile_status,
+ -1);
+
+ g_free (profile_status);
+
+ g_signal_connect (device,
+ "notify::active-profile",
+ G_CALLBACK (on_device_profile_notify),
+ dialog);
}
static void
-remove_card (GvcMixerDialog *dialog, const gchar *name)
+on_control_device_added (MateMixerControl *control, const gchar *name, GvcMixerDialog *dialog)
{
- gboolean found;
- GtkTreeIter iter;
- GtkTreeModel *model;
+ MateMixerDevice *device;
- /* remove from any models */
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview));
- found = find_tree_item_by_name (GTK_TREE_MODEL (model), name, HW_NAME_COLUMN, &iter);
- if (found) {
- gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
- }
+ device = mate_mixer_control_get_device (control, name);
+ if (G_UNLIKELY (device == NULL))
+ return;
+
+ add_device (dialog, device);
}
static void
@@ -1208,43 +1197,54 @@ on_control_device_removed (MateMixerControl *control,
const gchar *name,
GvcMixerDialog *dialog)
{
- remove_card (dialog, name);
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+
+ /* Remove from any models */
+ 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
-_gtk_label_make_bold (GtkLabel *label)
+make_label_bold (GtkLabel *label)
{
PangoFontDescription *font_desc;
font_desc = pango_font_description_new ();
- pango_font_description_set_weight (font_desc,
- PANGO_WEIGHT_BOLD);
+ 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.
- */
+ * 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,
- char *path_str,
+ gchar *path_str,
GvcMixerDialog *dialog)
{
GtkTreeModel *model;
GtkTreeIter iter;
GtkTreePath *path;
- gboolean toggled;
- gchar *name;
+ 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);
- path = gtk_tree_path_new_from_string (path_str);
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_path_free (path);
@@ -1252,34 +1252,36 @@ on_input_radio_toggled (GtkCellRendererToggle *renderer,
NAME_COLUMN, &name,
ACTIVE_COLUMN, &toggled,
-1);
-
if (toggled ^ 1) {
MateMixerStream *stream;
- g_debug ("Default input selected: %s", name);
stream = mate_mixer_control_get_stream (dialog->priv->control, name);
+ if (G_UNLIKELY (stream == NULL)) {
+ g_warn_if_reached ();
+ g_free (name);
+ return;
+ }
- if (stream != NULL)
- mate_mixer_control_set_default_input_stream (dialog->priv->control,
- stream);
+ g_debug ("Default input stream selection changed to %s", name);
+ mate_mixer_control_set_default_input_stream (dialog->priv->control, stream);
}
g_free (name);
}
static void
on_output_radio_toggled (GtkCellRendererToggle *renderer,
- char *path_str,
+ gchar *path_str,
GvcMixerDialog *dialog)
{
GtkTreeModel *model;
GtkTreeIter iter;
GtkTreePath *path;
- gboolean toggled;
- gchar *name;
+ 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);
- path = gtk_tree_path_new_from_string (path_str);
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_path_free (path);
@@ -1287,44 +1289,74 @@ on_output_radio_toggled (GtkCellRendererToggle *renderer,
NAME_COLUMN, &name,
ACTIVE_COLUMN, &toggled,
-1);
-
if (toggled ^ 1) {
MateMixerStream *stream;
- g_debug ("Default output selected: %s", name);
stream = mate_mixer_control_get_stream (dialog->priv->control, name);
- if (stream != NULL)
- mate_mixer_control_set_default_output_stream (dialog->priv->control,
- stream);
+ if (G_UNLIKELY (stream == NULL)) {
+ g_warn_if_reached ();
+ g_free (name);
+ return;
+ }
+
+ g_debug ("Default output stream selection changed to %s", name);
+ mate_mixer_control_set_default_output_stream (dialog->priv->control, stream);
}
g_free (name);
}
static void
-name_to_text (GtkTreeViewColumn *column,
- GtkCellRenderer *cell,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer user_data)
+stream_name_to_text (GtkTreeViewColumn *column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data)
{
- char *description, *mapping;
+ gchar *description;
+ gchar *speakers;
gtk_tree_model_get (model, iter,
DESCRIPTION_COLUMN, &description,
- SPEAKERS_COLUMN, &mapping,
+ SPEAKERS_COLUMN, &speakers,
-1);
- if (mapping == NULL) {
- g_object_set (cell, "text", description, NULL);
- } else {
- gchar *str = g_strdup_printf ("%s\n<i>%s</i>", description, mapping);
+ if (speakers != NULL) {
+ gchar *str = g_strdup_printf ("%s\n<i>%s</i>",
+ description,
+ speakers);
g_object_set (cell, "markup", str, NULL);
g_free (str);
+ g_free (speakers);
+ } else {
+ g_object_set (cell, "text", description, NULL);
}
g_free (description);
- g_free (mapping);
+}
+
+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,
+ DESCRIPTION_COLUMN, &desc_a,
+ -1);
+ gtk_tree_model_get (model, b,
+ DESCRIPTION_COLUMN, &desc_b,
+ -1);
+
+ result = g_ascii_strcasecmp (desc_a, desc_b);
+
+ g_free (desc_a);
+ g_free (desc_b);
+ return result;
}
static GtkWidget *
@@ -1342,7 +1374,6 @@ create_stream_treeview (GvcMixerDialog *dialog, GCallback on_toggled)
G_TYPE_ICON,
G_TYPE_STRING,
G_TYPE_STRING,
- G_TYPE_STRING,
G_TYPE_BOOLEAN,
G_TYPE_STRING);
@@ -1356,9 +1387,10 @@ create_stream_treeview (GvcMixerDialog *dialog, GCallback on_toggled)
renderer,
"active", ACTIVE_COLUMN,
NULL);
+
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
- g_signal_connect (renderer,
+ g_signal_connect (G_OBJECT (renderer),
"toggled",
G_CALLBACK (on_toggled),
dialog);
@@ -1366,48 +1398,66 @@ create_stream_treeview (GvcMixerDialog *dialog, GCallback on_toggled)
gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (treeview), -1,
_("Name"),
gtk_cell_renderer_text_new (),
- name_to_text, NULL, NULL);
+ stream_name_to_text,
+ NULL, NULL);
-#if 0
- renderer = gtk_cell_renderer_text_new ();
- column = gtk_tree_view_column_new_with_attributes (_("Device"),
- renderer,
- "text", DEVICE_COLUMN,
- NULL);
- gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
-#endif
+ /* Keep the list of streams sorted by the name */
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
+ DESCRIPTION_COLUMN,
+ GTK_SORT_ASCENDING);
+
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store),
+ DESCRIPTION_COLUMN,
+ compare_stream_treeview_items,
+ NULL, NULL);
return treeview;
}
-static void
-on_profile_changed (GvcComboBox *widget, const gchar *profile, gpointer user_data)
+static MateMixerStream *
+find_device_test_stream (GvcMixerDialog *dialog, MateMixerDevice *device)
{
- MateMixerDevice *device;
+ GList *streams;
- device = g_object_get_data (G_OBJECT (widget), "device");
- if (device == NULL) {
- g_warning ("Could not find card for combobox");
- return;
- }
+ streams = (GList *) mate_mixer_control_list_streams (dialog->priv->control);
+ while (streams) {
+ MateMixerStream *stream;
- g_debug ("Profile changed to %s for device %s",
- profile,
- mate_mixer_device_get_name (device));
+ stream = MATE_MIXER_STREAM (streams->data);
- mate_mixer_device_set_active_profile (device, profile);
+ if (mate_mixer_stream_get_device (stream) == device &&
+ mate_mixer_stream_get_num_channels (stream) >= 1) {
+ MateMixerStreamFlags flags;
+
+ flags = mate_mixer_stream_get_flags (stream);
+
+ if ((flags & (MATE_MIXER_STREAM_OUTPUT |
+ MATE_MIXER_STREAM_CLIENT)) == MATE_MIXER_STREAM_OUTPUT)
+ return stream;
+ }
+ streams = streams->next;
+ }
+ return FALSE;
}
static void
-on_test_speakers_clicked (GvcComboBox *widget, gpointer user_data)
+on_test_speakers_clicked (GvcComboBox *widget, GvcMixerDialog *dialog)
{
- GvcMixerDialog *dialog = GVC_MIXER_DIALOG (user_data);
- MateMixerDevice *device;
- GtkWidget *d, *speaker_test, *container;
- char *title;
+ GtkWidget *d,
+ *test,
+ *container;
+ gchar *title;
+ MateMixerDevice *device;
+ MateMixerStream *stream;
device = g_object_get_data (G_OBJECT (widget), "device");
- if (device == NULL) {
- g_warning ("Could not find card for combobox");
+ 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;
}
@@ -1418,92 +1468,139 @@ on_test_speakers_clicked (GvcComboBox *widget, gpointer user_data)
GTK_WINDOW (dialog),
GTK_DIALOG_MODAL |
GTK_DIALOG_DESTROY_WITH_PARENT,
+ "gtk-close",
+ GTK_RESPONSE_CLOSE,
NULL);
g_free (title);
- speaker_test = gvc_speaker_test_new (dialog->priv->control, device);
- gtk_widget_show (speaker_test);
+ 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), speaker_test);
+ 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,
+ MateMixerDevice *device,
+ const gchar *name,
+ const GList *items,
+ const gchar *active)
+{
+ GtkWidget *combobox;
+
+ combobox = gvc_combo_box_new (name);
+
+ gvc_combo_box_set_profiles (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),
+ "device",
+ g_object_ref (device),
+ g_object_unref);
+
+ g_signal_connect (G_OBJECT (combobox),
+ "changed",
+ G_CALLBACK (on_combo_box_profile_changed),
+ dialog);
+
+ return combobox;
+}
+
static void
-on_card_selection_changed (GtkTreeSelection *selection,
- gpointer user_data)
+on_device_selection_changed (GtkTreeSelection *selection, GvcMixerDialog *dialog)
{
- GvcMixerDialog *dialog = GVC_MIXER_DIALOG (user_data);
- GtkTreeModel *model;
GtkTreeIter iter;
- const GList *profiles;
- gchar *name;
- MateMixerDevice *device;
- MateMixerDeviceProfile *profile;
+ gchar *name;
+ MateMixerDevice *device;
+ MateMixerBackendType backend;
- g_debug ("Card selection changed");
+ 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;
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview));
- gtk_tree_model_get (model, &iter,
+ 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_control_get_device (dialog->priv->control, name);
- if (device == NULL) {
- g_warning ("Unable to find card for id: %s", name);
+ if (G_UNLIKELY (device == NULL)) {
+ g_warn_if_reached ();
g_free (name);
return;
}
g_free (name);
- profile = mate_mixer_device_get_active_profile (device);
- profiles = mate_mixer_device_list_profiles (device);
-
- dialog->priv->hw_profile_combo = gvc_combo_box_new (_("_Profile:"));
-
- g_object_set (G_OBJECT (dialog->priv->hw_profile_combo),
- "button-label",
- _("Test Speakers"),
- NULL);
+ backend = mate_mixer_control_get_backend_type (dialog->priv->control);
+
+ /* Speaker test is only possible on PulseAudio and profile changing is
+ * not supported on other backends by libmatemixer, so avoid displaying
+ * the combo box on other backends */
+ if (backend == MATE_MIXER_BACKEND_PULSEAUDIO) {
+ const GList *profiles;
+ const gchar *profile_name = NULL;
+ MateMixerStream *stream = NULL;
+
+ profiles = mate_mixer_device_list_profiles (device);
+ if (profiles != NULL) {
+ MateMixerDeviceProfile *profile;
+
+ profile = mate_mixer_device_get_active_profile (device);
+ if (G_UNLIKELY (profile == NULL)) {
+ /* Select the first profile if none is selected */
+ profile = MATE_MIXER_DEVICE_PROFILE (profiles->data);
+ mate_mixer_device_set_active_profile (device, profile);
+ }
- gvc_combo_box_set_profiles (GVC_COMBO_BOX (dialog->priv->hw_profile_combo),
- profiles);
- gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->hw_profile_combo),
- mate_mixer_device_profile_get_name (profile));
+ profile_name = mate_mixer_device_profile_get_name (profile);
+ }
- gtk_box_pack_start (GTK_BOX (dialog->priv->hw_settings_box),
- dialog->priv->hw_profile_combo,
- TRUE, TRUE, 6);
+ dialog->priv->hw_profile_combo =
+ create_profile_combo_box (dialog,
+ device,
+ _("_Profile:"),
+ profiles,
+ profile_name);
- g_object_set (G_OBJECT (dialog->priv->hw_profile_combo),
- "show-button",
- mate_mixer_device_profile_get_num_output_streams (profile) >= 1,
- NULL);
+ gtk_box_pack_start (GTK_BOX (dialog->priv->hw_settings_box),
+ dialog->priv->hw_profile_combo,
+ TRUE, TRUE, 6);
- gtk_widget_show (dialog->priv->hw_profile_combo);
+ /* Enable the speaker test button if the selected device
+ * is capable of sound output */
+ stream = find_device_test_stream (dialog, device);
+ if (stream != NULL) {
+ g_object_set (G_OBJECT (dialog->priv->hw_profile_combo),
+ "show-button", TRUE,
+ "button-label", _("Test Speakers"),
+ NULL);
- g_object_set_data (G_OBJECT (dialog->priv->hw_profile_combo),
- "device",
- g_object_ref (device));
+ g_signal_connect (G_OBJECT (dialog->priv->hw_profile_combo),
+ "button-clicked",
+ G_CALLBACK (on_test_speakers_clicked),
+ dialog);
+ }
- g_signal_connect (G_OBJECT (dialog->priv->hw_profile_combo),
- "changed",
- G_CALLBACK (on_profile_changed),
- dialog);
- g_signal_connect (G_OBJECT (dialog->priv->hw_profile_combo),
- "button-clicked",
- G_CALLBACK (on_test_speakers_clicked),
- dialog);
+ gtk_widget_show (dialog->priv->hw_profile_combo);
+ }
}
static void
@@ -1525,36 +1622,71 @@ on_notebook_switch_page (GtkNotebook *notebook,
}
static void
-card_to_text (GtkTreeViewColumn *column,
- GtkCellRenderer *cell,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer user_data)
+device_name_to_text (GtkTreeViewColumn *column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data)
{
- gchar *description, *status, *profile, *str;
- gboolean sensitive;
+ gchar *description = NULL;
+ gchar *profile = NULL;
+ gchar *profile_status = NULL;
gtk_tree_model_get (model, iter,
HW_DESCRIPTION_COLUMN, &description,
- HW_STATUS_COLUMN, &status,
- HW_PROFILE_HUMAN_COLUMN, &profile,
- HW_SENSITIVE_COLUMN, &sensitive,
+ HW_PROFILE_COLUMN, &profile,
+ HW_STATUS_COLUMN, &profile_status,
-1);
- str = g_strdup_printf ("%s\n<i>%s</i>\n<i>%s</i>", description, status, profile);
- g_object_set (cell,
- "markup", str,
- "sensitive", sensitive,
- NULL);
- g_free (str);
+ if (profile != NULL) {
+ gchar *str;
+
+ if (G_LIKELY (profile_status != NULL))
+ str = g_strdup_printf ("%s\n<i>%s</i>\n<i>%s</i>",
+ description,
+ profile_status,
+ profile);
+ else
+ str = g_strdup_printf ("%s\n<i>%s</i>",
+ description,
+ profile);
+
+ g_object_set (cell, "markup", str, NULL);
+ g_free (str);
+ g_free (profile);
+ g_free (profile_status);
+ } else
+ g_object_set (cell, "text", description, NULL);
g_free (description);
- g_free (status);
- g_free (profile);
+}
+
+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_DESCRIPTION_COLUMN, &desc_a,
+ -1);
+ gtk_tree_model_get (model, b,
+ HW_DESCRIPTION_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_cards_treeview (GvcMixerDialog *dialog, GCallback on_changed)
+create_device_treeview (GvcMixerDialog *dialog, GCallback on_changed)
{
GtkWidget *treeview;
GtkListStore *store;
@@ -1576,37 +1708,41 @@ create_cards_treeview (GvcMixerDialog *dialog, GCallback on_changed)
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_STRING,
- 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_pixbuf_new ();
- g_object_set (G_OBJECT (renderer), "stock-size", GTK_ICON_SIZE_DIALOG, NULL);
+ 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,
- "sensitive", HW_SENSITIVE_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,
+ 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_DESCRIPTION_COLUMN,
+ GTK_SORT_ASCENDING);
+
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store),
+ HW_DESCRIPTION_COLUMN,
+ compare_device_treeview_items,
+ NULL, NULL);
return treeview;
}
-static const guint tab_accel_keys[] = {
- GDK_1, GDK_2, GDK_3, GDK_4, GDK_5
-};
-
static void
dialog_accel_cb (GtkAccelGroup *accelgroup,
GObject *object,
@@ -1641,17 +1777,19 @@ gvc_mixer_dialog_constructor (GType type,
GtkWidget *box;
GtkWidget *sbox;
GtkWidget *ebox;
- GList *list;
GtkTreeSelection *selection;
GtkAccelGroup *accel_group;
GClosure *closure;
- gint i;
+ GtkTreeIter iter;
+ gint i;
+ 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));
@@ -1659,17 +1797,25 @@ gvc_mixer_dialog_constructor (GType type,
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, self->priv->size_group, TRUE);
+
+ 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_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);
@@ -1678,6 +1824,11 @@ gvc_mixer_dialog_constructor (GType type,
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) */
@@ -1685,9 +1836,9 @@ gvc_mixer_dialog_constructor (GType type,
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);
+ closure = g_cclosure_new (G_CALLBACK (dialog_accel_cb),
+ self,
+ NULL);
gtk_accel_group_connect (accel_group,
tab_accel_keys[i],
GDK_MOD1_MASK,
@@ -1697,29 +1848,44 @@ gvc_mixer_dialog_constructor (GType type,
g_object_unref (accel_group);
- /* Effects page */
+ /* 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, self->priv->size_group, TRUE);
+ 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_set_sensitive (self->priv->effects_bar, FALSE);
- gtk_box_pack_start (GTK_BOX (self->priv->sound_effects_box),
- self->priv->effects_bar, FALSE, FALSE, 0);
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);
- /* Hardware page */
+#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,
@@ -1727,7 +1893,7 @@ gvc_mixer_dialog_constructor (GType type,
box = gtk_frame_new (_("C_hoose a device to configure:"));
label = gtk_frame_get_label_widget (GTK_FRAME (box));
- _gtk_label_make_bold (GTK_LABEL (label));
+ 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);
@@ -1736,8 +1902,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->hw_treeview = create_cards_treeview (self,
- G_CALLBACK (on_card_selection_changed));
+ 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);
@@ -1754,21 +1920,32 @@ gvc_mixer_dialog_constructor (GType type,
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));
+ 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);
- /* Input page */
+#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, self->priv->size_group, TRUE);
+ 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),
@@ -1776,6 +1953,7 @@ gvc_mixer_dialog_constructor (GType type,
gvc_channel_bar_set_high_icon_name (GVC_CHANNEL_BAR (self->priv->input_bar),
"audio-input-microphone-high");
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);
@@ -1783,12 +1961,19 @@ gvc_mixer_dialog_constructor (GType type,
alignment,
FALSE, FALSE, 0);
- box = gtk_hbox_new (FALSE, 6);
+#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);
-
- sbox = gtk_hbox_new (FALSE, 6);
gtk_box_pack_start (GTK_BOX (box),
sbox,
FALSE, FALSE, 0);
@@ -1808,20 +1993,23 @@ gvc_mixer_dialog_constructor (GType type,
self->priv->input_level_bar,
TRUE, TRUE, 6);
- ebox = gtk_hbox_new (FALSE, 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));
- _gtk_label_make_bold (GTK_LABEL (label));
+ 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);
@@ -1830,8 +2018,9 @@ 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_radio_toggled));
+ 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);
@@ -1856,7 +2045,7 @@ gvc_mixer_dialog_constructor (GType type,
box = gtk_frame_new (_("C_hoose a device for sound output:"));
label = gtk_frame_get_label_widget (GTK_FRAME (box));
- _gtk_label_make_bold (GTK_LABEL (label));
+ 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);
@@ -1883,26 +2072,43 @@ gvc_mixer_dialog_constructor (GType type,
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));
+ 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_scrolled_window = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (self->priv->applications_scrolled_window),
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (self->priv->applications_scrolled_window),
+ 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);
- gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (self->priv->applications_scrolled_window),
+
+#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_scrolled_window,
+ 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,
@@ -1910,6 +2116,8 @@ gvc_mixer_dialog_constructor (GType type,
gtk_widget_show_all (main_vbox);
+ // XXX subscribe to cached stream stuff, in case event stream is not found
+
list = (GList *) mate_mixer_control_list_streams (self->priv->control);
while (list) {
add_stream (self, MATE_MIXER_STREAM (list->data));
@@ -1922,10 +2130,30 @@ gvc_mixer_dialog_constructor (GType type,
list = list->next;
}
- g_signal_connect (G_OBJECT (self->priv->notebook),
- "switch-page",
- G_CALLBACK (on_notebook_switch_page),
- self);
+ /* Find an event role stream */
+ list = (GList *) mate_mixer_control_list_cached_streams (self->priv->control);
+ while (list) {
+ MateMixerClientStreamRole role;
+
+ role = mate_mixer_client_stream_get_role (MATE_MIXER_CLIENT_STREAM (list->data));
+
+ if (role == MATE_MIXER_CLIENT_STREAM_ROLE_EVENT)
+ add_stream (self, MATE_MIXER_STREAM (list->data));
+
+ 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;
}
@@ -1948,28 +2176,36 @@ gvc_mixer_dialog_set_control (GvcMixerDialog *dialog, MateMixerControl *control)
dialog->priv->control = g_object_ref (control);
- g_signal_connect (dialog->priv->control,
+ g_signal_connect (G_OBJECT (dialog->priv->control),
"stream-added",
G_CALLBACK (on_control_stream_added),
dialog);
- g_signal_connect (dialog->priv->control,
+ g_signal_connect (G_OBJECT (dialog->priv->control),
+ "cached-stream-added",
+ G_CALLBACK (on_control_stream_added),
+ dialog);
+ g_signal_connect (G_OBJECT (dialog->priv->control),
"stream-removed",
G_CALLBACK (on_control_stream_removed),
dialog);
- g_signal_connect (dialog->priv->control,
+ g_signal_connect (G_OBJECT (dialog->priv->control),
+ "cached-stream-removed",
+ G_CALLBACK (on_control_cached_stream_removed),
+ dialog);
+ g_signal_connect (G_OBJECT (dialog->priv->control),
"device-added",
G_CALLBACK (on_control_device_added),
dialog);
- g_signal_connect (dialog->priv->control,
+ g_signal_connect (G_OBJECT (dialog->priv->control),
"device-removed",
G_CALLBACK (on_control_device_removed),
dialog);
- g_signal_connect (dialog->priv->control,
+ g_signal_connect (G_OBJECT (dialog->priv->control),
"notify::default-output",
G_CALLBACK (on_control_default_output_notify),
dialog);
- g_signal_connect (dialog->priv->control,
+ g_signal_connect (G_OBJECT (dialog->priv->control),
"notify::default-input",
G_CALLBACK (on_control_default_input_notify),
dialog);
@@ -1986,7 +2222,7 @@ gvc_mixer_dialog_set_property (GObject *object,
GvcMixerDialog *self = GVC_MIXER_DIALOG (object);
switch (prop_id) {
- case PROP_MIXER_CONTROL:
+ case PROP_CONTROL:
gvc_mixer_dialog_set_control (self, g_value_get_object (value));
break;
default:
@@ -2004,7 +2240,7 @@ gvc_mixer_dialog_get_property (GObject *object,
GvcMixerDialog *self = GVC_MIXER_DIALOG (object);
switch (prop_id) {
- case PROP_MIXER_CONTROL:
+ case PROP_CONTROL:
g_value_set_object (value, gvc_mixer_dialog_get_control (self));
break;
default:
@@ -2050,7 +2286,7 @@ gvc_mixer_dialog_class_init (GvcMixerDialogClass *klass)
object_class->get_property = gvc_mixer_dialog_get_property;
g_object_class_install_property (object_class,
- PROP_MIXER_CONTROL,
+ PROP_CONTROL,
g_param_spec_object ("control",
"Control",
"MateMixer control",
@@ -2068,7 +2304,6 @@ gvc_mixer_dialog_init (GvcMixerDialog *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);
- dialog->priv->apps_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
}
static void
@@ -2102,7 +2337,7 @@ gvc_mixer_dialog_set_page (GvcMixerDialog *self, const gchar *page)
if (page != NULL) {
if (g_str_equal (page, "effects"))
- num = PAGE_EVENTS;
+ num = PAGE_EFFECTS;
else if (g_str_equal (page, "hardware"))
num = PAGE_HARDWARE;
else if (g_str_equal (page, "input"))