From cf427cb4ccfc269252c1f7744b4c730ef0bb7a4e Mon Sep 17 00:00:00 2001 From: Michal Ratajsky Date: Sat, 5 Jul 2014 01:41:22 +0200 Subject: Initial port of the dialog --- configure.ac | 2 +- mate-volume-control/src/Makefile.am | 2 + mate-volume-control/src/applet-main.c | 3 +- mate-volume-control/src/dialog-main.c | 175 ++- mate-volume-control/src/gvc-balance-bar.c | 248 ++-- mate-volume-control/src/gvc-balance-bar.h | 26 +- mate-volume-control/src/gvc-channel-bar.c | 15 +- mate-volume-control/src/gvc-channel-bar.h | 1 + mate-volume-control/src/gvc-combo-box.c | 35 +- mate-volume-control/src/gvc-mixer-dialog.c | 1543 +++++++++++----------- mate-volume-control/src/gvc-mixer-dialog.h | 23 +- mate-volume-control/src/gvc-stream-status-icon.c | 25 +- mate-volume-control/src/mvc-helpers.c | 155 +++ mate-volume-control/src/mvc-helpers.h | 36 + 14 files changed, 1234 insertions(+), 1055 deletions(-) create mode 100644 mate-volume-control/src/mvc-helpers.c create mode 100644 mate-volume-control/src/mvc-helpers.h diff --git a/configure.ac b/configure.ac index 588b06d..e718962 100644 --- a/configure.ac +++ b/configure.ac @@ -47,7 +47,7 @@ GLIB_REQUIRED_VERSION=2.18.2 GIO_REQUIRED_VERSION=2.25.0 PA_REQUIRED_VERSION=0.9.16 CANBERRA_REQUIRED_VERSION=0.13 -MATE_DESKTOP_REQUIRED_VERSION=1.7.3 +MATE_DESKTOP_REQUIRED_VERSION=1.9.1 MATE_PANEL_REQUIRED_VERSION=1.7.0 dnl======================================================================= diff --git a/mate-volume-control/src/Makefile.am b/mate-volume-control/src/Makefile.am index afc91b5..939814d 100644 --- a/mate-volume-control/src/Makefile.am +++ b/mate-volume-control/src/Makefile.am @@ -39,6 +39,8 @@ libmatevolumecontrol_la_SOURCES = \ gvc-mixer-control.c \ gvc-channel-bar.h \ gvc-channel-bar.c \ + mvc-helpers.c \ + mvc-helpers.h \ $(NULL) mate_volume_control_applet_LDADD = \ diff --git a/mate-volume-control/src/applet-main.c b/mate-volume-control/src/applet-main.c index 767d2e1..34151ba 100644 --- a/mate-volume-control/src/applet-main.c +++ b/mate-volume-control/src/applet-main.c @@ -38,7 +38,7 @@ main (int argc, char **argv) GError *error = NULL; GvcApplet *applet; UniqueApp *app = NULL; - GOptionEntry entries[] = { + GOptionEntry entries[] = { { "version", 'v', 0, G_OPTION_ARG_NONE, &show_version, N_("Version of this application"), NULL }, { NULL } }; @@ -81,6 +81,7 @@ main (int argc, char **argv) g_object_unref (applet); g_object_unref (app); + mate_mixer_deinit (); return 0; diff --git a/mate-volume-control/src/dialog-main.c b/mate-volume-control/src/dialog-main.c index 8b85924..f1d5bf4 100644 --- a/mate-volume-control/src/dialog-main.c +++ b/mate-volume-control/src/dialog-main.c @@ -20,43 +20,53 @@ #include "config.h" +#include #include #include #include -#include #include #include #include "gvc-mixer-dialog.h" -#define DIALOG_POPUP_TIMEOUT 3 +#define DIALOG_POPUP_TIMEOUT 1 -static gboolean show_version = FALSE; -static gchar* page = NULL; +static guint popup_id = 0; +static gboolean show_version = FALSE; -static guint popup_id = 0; -static GtkWidget *dialog = NULL; -static GtkWidget *warning_dialog = NULL; +static gchar *page = NULL; +static GtkWidget *app_dialog = NULL; +static GtkWidget *warning_dialog = NULL; static void on_dialog_response (GtkDialog *dialog, guint response_id, gpointer data) { + gboolean destroy = GPOINTER_TO_INT (data); + + if (destroy) + gtk_widget_destroy (GTK_WIDGET (dialog)); + gtk_main_quit (); } static void on_dialog_close (GtkDialog *dialog, gpointer data) { + gboolean destroy = GPOINTER_TO_INT (data); + + if (destroy) + gtk_widget_destroy (GTK_WIDGET (dialog)); + gtk_main_quit (); } static UniqueResponse -message_received_cb (UniqueApp *app, - int command, - UniqueMessageData *message_data, - guint time_, - gpointer user_data) +on_app_message_received (UniqueApp *app, + int command, + UniqueMessageData *message_data, + guint time_, + gpointer user_data) { gtk_window_present (GTK_WINDOW (user_data)); @@ -64,84 +74,113 @@ message_received_cb (UniqueApp *app, } static void -on_control_ready (GvcMixerControl *control, UniqueApp *app) +remove_warning_dialog (void) { if (popup_id != 0) { g_source_remove (popup_id); popup_id = 0; } - if (warning_dialog != NULL) { - gtk_widget_destroy (warning_dialog); - warning_dialog = NULL; - } - if (dialog) + g_clear_pointer (&warning_dialog, gtk_widget_destroy); +} + +static void +control_ready (MateMixerControl *control, UniqueApp *app) +{ + /* The dialog might be already created, e.g. when reconnected + * to a sound server */ + if (app_dialog != NULL) return; - dialog = GTK_WIDGET (gvc_mixer_dialog_new (control)); - g_signal_connect (dialog, + app_dialog = GTK_WIDGET (gvc_mixer_dialog_new (control)); + g_signal_connect (app_dialog, "response", G_CALLBACK (on_dialog_response), - NULL); - g_signal_connect (dialog, + GINT_TO_POINTER (FALSE)); + g_signal_connect (app_dialog, "close", G_CALLBACK (on_dialog_close), - NULL); + GINT_TO_POINTER (FALSE)); - gvc_mixer_dialog_set_page (GVC_MIXER_DIALOG (dialog), page); + gvc_mixer_dialog_set_page (GVC_MIXER_DIALOG (app_dialog), page); g_signal_connect (app, "message-received", - G_CALLBACK (message_received_cb), dialog); + G_CALLBACK (on_app_message_received), app_dialog); - gtk_widget_show (dialog); + gtk_widget_show (app_dialog); } static void -warning_dialog_answered (GtkDialog *d, - gpointer data) +on_control_state_notify (MateMixerControl *control, UniqueApp *app) { - gtk_widget_destroy (warning_dialog); - gtk_main_quit (); + MateMixerState state = mate_mixer_control_get_state (control); + gboolean failed = FALSE; + + if (state == MATE_MIXER_STATE_READY) { + remove_warning_dialog (); + + if (mate_mixer_control_get_backend_type (control) != MATE_MIXER_BACKEND_NULL) + control_ready (control, app); + else + failed = TRUE; + } + else if (state == MATE_MIXER_STATE_FAILED) { + remove_warning_dialog (); + failed = TRUE; + } + + if (failed) { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (GTK_WINDOW (app_dialog), + 0, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + _("Sound system is not available")); + + g_signal_connect (dialog, + "response", + G_CALLBACK (on_dialog_response), + GINT_TO_POINTER (TRUE)); + g_signal_connect (dialog, + "close", + G_CALLBACK (on_dialog_close), + GINT_TO_POINTER (TRUE)); + + gtk_widget_show (dialog); + } } static gboolean dialog_popup_timeout (gpointer data) { - warning_dialog = gtk_message_dialog_new (GTK_WINDOW(dialog), + warning_dialog = gtk_message_dialog_new (GTK_WINDOW (app_dialog), 0, GTK_MESSAGE_INFO, GTK_BUTTONS_CANCEL, _("Waiting for sound system to respond")); - g_signal_connect (warning_dialog, "response", - G_CALLBACK (warning_dialog_answered), NULL); - g_signal_connect (warning_dialog, "close", - G_CALLBACK (warning_dialog_answered), NULL); + g_signal_connect (warning_dialog, + "response", + G_CALLBACK (on_dialog_response), + GINT_TO_POINTER (TRUE)); + g_signal_connect (warning_dialog, + "close", + G_CALLBACK (on_dialog_close), + GINT_TO_POINTER (TRUE)); gtk_widget_show (warning_dialog); return FALSE; } -static void -on_control_connecting (GvcMixerControl *control, - UniqueApp *app) -{ - if (popup_id != 0) - return; - - popup_id = g_timeout_add_seconds (DIALOG_POPUP_TIMEOUT, - dialog_popup_timeout, - NULL); -} - int main (int argc, char **argv) { - GError *error = NULL; - GvcMixerControl *control; - UniqueApp *app; - GOptionEntry entries[] = { + GError *error = NULL; + MateMixerControl *control; + UniqueApp *app; + GOptionEntry entries[] = { { "page", 'p', 0, G_OPTION_ARG_STRING, &page, N_("Startup page"), "effects|hardware|input|output|applications" }, { "version", 'v', 0, G_OPTION_ARG_NONE, &show_version, N_("Version of this application"), NULL }, { NULL } @@ -175,27 +214,37 @@ main (int argc, char **argv) return 1; } - gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), - ICON_DATA_DIR); - - gtk_window_set_default_icon_name ("multimedia-volume-control"); + control = mate_mixer_control_new (); - control = gvc_mixer_control_new ("MATE Volume Control Dialog"); + mate_mixer_control_set_app_name (control, _("Volume Control")); + mate_mixer_control_set_app_id (control, GVC_DIALOG_DBUS_NAME); + mate_mixer_control_set_app_version (control, VERSION); + mate_mixer_control_set_app_icon (control, "multimedia-volume-control"); g_signal_connect (control, - "connecting", - G_CALLBACK (on_control_connecting), - app); - g_signal_connect (control, - "ready", - G_CALLBACK (on_control_ready), + "notify::state", + G_CALLBACK (on_control_state_notify), app); - gvc_mixer_control_open (control); + mate_mixer_control_open (control); + + /* */ + if (mate_mixer_control_get_state (control) == MATE_MIXER_STATE_CONNECTING) + popup_id = g_timeout_add_seconds (DIALOG_POPUP_TIMEOUT, + dialog_popup_timeout, + NULL); + + gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), + ICON_DATA_DIR); + + gtk_window_set_default_icon_name ("multimedia-volume-control"); gtk_main (); g_object_unref (control); + g_object_unref (app); + + mate_mixer_deinit (); return 0; } diff --git a/mate-volume-control/src/gvc-balance-bar.c b/mate-volume-control/src/gvc-balance-bar.c index b4bedf9..0730b67 100644 --- a/mate-volume-control/src/gvc-balance-bar.c +++ b/mate-volume-control/src/gvc-balance-bar.c @@ -20,47 +20,48 @@ #include "config.h" -#include -#include -#include - #include #include #include + #include +#include #include "gvc-balance-bar.h" #define SCALE_SIZE 128 -#define ADJUSTMENT_MAX_NORMAL 65536.0 /* PA_VOLUME_NORM */ +#define ADJUSTMENT_MAX_NORMAL 65536.0 /* PA_VOLUME_NORM */ // XXX #define GVC_BALANCE_BAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_BALANCE_BAR, GvcBalanceBarPrivate)) -struct GvcBalanceBarPrivate +struct _GvcBalanceBarPrivate { - GvcChannelMap *channel_map; - GvcBalanceType btype; - GtkWidget *scale_box; - GtkWidget *start_box; - GtkWidget *end_box; - GtkWidget *label; - GtkWidget *scale; - GtkAdjustment *adjustment; - GtkSizeGroup *size_group; - gboolean symmetric; - gboolean click_lock; + MateMixerStream *stream; + GvcBalanceType btype; + GtkWidget *scale_box; + GtkWidget *start_box; + GtkWidget *end_box; + GtkWidget *label; + GtkWidget *scale; + GtkAdjustment *adjustment; + GtkSizeGroup *size_group; + gboolean symmetric; + gboolean click_lock; }; enum { PROP_0, - PROP_CHANNEL_MAP, + PROP_STREAM, PROP_BALANCE_TYPE, + N_PROPERTIES }; +static GParamSpec *properties[N_PROPERTIES] = { NULL, }; + static void gvc_balance_bar_class_init (GvcBalanceBarClass *klass); static void gvc_balance_bar_init (GvcBalanceBar *balance_bar); -static void gvc_balance_bar_finalize (GObject *object); +static void gvc_balance_bar_dispose (GObject *object); static gboolean on_scale_button_press_event (GtkWidget *widget, GdkEventButton *event, @@ -143,9 +144,6 @@ _scale_box_new (GvcBalanceBar *bar) bar->priv->end_box = ebox = gtk_hbox_new (FALSE, 6); gtk_box_pack_start (GTK_BOX (box), ebox, FALSE, FALSE, 0); -#if !GTK_CHECK_VERSION (3, 0, 0) - gtk_range_set_update_policy (GTK_RANGE (priv->scale), GTK_UPDATE_CONTINUOUS); -#endif ca_gtk_widget_disable_sounds (bar->priv->scale, FALSE); gtk_widget_add_events (bar->priv->scale, GDK_SCROLL_MASK); @@ -209,64 +207,83 @@ btype_to_string (guint btype) } static void -update_level_from_map (GvcBalanceBar *bar, - GvcChannelMap *map) +update_balance_value (GvcBalanceBar *bar) { - const gdouble *volumes; - gdouble val; - - g_debug ("Volume changed (for %s bar)", btype_to_string (bar->priv->btype)); + gdouble value = 0; - volumes = gvc_channel_map_get_volume (map); switch (bar->priv->btype) { case BALANCE_TYPE_RL: - val = volumes[BALANCE]; + value = mate_mixer_stream_get_balance (bar->priv->stream); break; case BALANCE_TYPE_FR: - val = volumes[FADE]; + value = mate_mixer_stream_get_fade (bar->priv->stream); break; case BALANCE_TYPE_LFE: - val = volumes[LFE]; + value = mate_mixer_stream_get_position_volume (bar->priv->stream, + MATE_MIXER_CHANNEL_LFE); break; default: g_assert_not_reached (); } - gtk_adjustment_set_value (bar->priv->adjustment, val); + g_debug ("%s value changed to %.1f", btype_to_string (bar->priv->btype), value); + + gtk_adjustment_set_value (bar->priv->adjustment, value); } static void -on_channel_map_volume_changed (GvcChannelMap *map, - gboolean set, - GvcBalanceBar *bar) +on_balance_value_changed (MateMixerStream *stream, + GParamSpec *pspec, + GvcBalanceBar *bar) { - update_level_from_map (bar, map); + update_balance_value (bar); } static void -gvc_balance_bar_set_channel_map (GvcBalanceBar *bar, - GvcChannelMap *map) +gvc_balance_bar_set_stream (GvcBalanceBar *bar, MateMixerStream *stream) { g_return_if_fail (GVC_BALANCE_BAR (bar)); + g_return_if_fail (MATE_MIXER_IS_STREAM (stream)); - if (bar->priv->channel_map != NULL) { - g_signal_handlers_disconnect_by_func (G_OBJECT (bar->priv->channel_map), - on_channel_map_volume_changed, bar); - g_object_unref (bar->priv->channel_map); + if (bar->priv->stream != NULL) { + g_signal_handlers_disconnect_by_func (G_OBJECT (bar->priv->stream), + on_balance_value_changed, + bar); + g_object_unref (bar->priv->stream); } - bar->priv->channel_map = g_object_ref (map); - update_level_from_map (bar, map); + bar->priv->stream = g_object_ref (stream); - g_signal_connect (G_OBJECT (map), "volume-changed", - G_CALLBACK (on_channel_map_volume_changed), bar); + switch (bar->priv->btype) { + case BALANCE_TYPE_RL: + g_signal_connect (G_OBJECT (stream), + "notify::balance", + G_CALLBACK (on_balance_value_changed), + bar); + break; + case BALANCE_TYPE_FR: + g_signal_connect (G_OBJECT (stream), + "notify::fade", + G_CALLBACK (on_balance_value_changed), + bar); + break; + case BALANCE_TYPE_LFE: + g_signal_connect (G_OBJECT (stream), + "notify::volume", + G_CALLBACK (on_balance_value_changed), + bar); + break; + default: + g_assert_not_reached (); + } + + update_balance_value (bar); - g_object_notify (G_OBJECT (bar), "channel-map"); + g_object_notify (G_OBJECT (bar), "stream"); } static void -gvc_balance_bar_set_balance_type (GvcBalanceBar *bar, - GvcBalanceType btype) +gvc_balance_bar_set_balance_type (GvcBalanceBar *bar, GvcBalanceType btype) { GtkWidget *frame; @@ -337,8 +354,8 @@ gvc_balance_bar_set_property (GObject *object, GvcBalanceBar *self = GVC_BALANCE_BAR (object); switch (prop_id) { - case PROP_CHANNEL_MAP: - gvc_balance_bar_set_channel_map (self, g_value_get_object (value)); + case PROP_STREAM: + gvc_balance_bar_set_stream (self, g_value_get_object (value)); break; case PROP_BALANCE_TYPE: gvc_balance_bar_set_balance_type (self, g_value_get_int (value)); @@ -358,8 +375,8 @@ gvc_balance_bar_get_property (GObject *object, GvcBalanceBar *self = GVC_BALANCE_BAR (object); switch (prop_id) { - case PROP_CHANNEL_MAP: - g_value_set_object (value, self->priv->channel_map); + case PROP_STREAM: + g_value_set_object (value, self->priv->stream); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -367,38 +384,32 @@ gvc_balance_bar_get_property (GObject *object, } } -static GObject * -gvc_balance_bar_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_params) -{ - return G_OBJECT_CLASS (gvc_balance_bar_parent_class)->constructor (type, n_construct_properties, construct_params); -} - static void gvc_balance_bar_class_init (GvcBalanceBarClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->constructor = gvc_balance_bar_constructor; - object_class->finalize = gvc_balance_bar_finalize; + object_class->dispose = gvc_balance_bar_dispose; object_class->set_property = gvc_balance_bar_set_property; object_class->get_property = gvc_balance_bar_get_property; - g_object_class_install_property (object_class, - PROP_CHANNEL_MAP, - g_param_spec_object ("channel-map", - "channel map", - "The channel map", - GVC_TYPE_CHANNEL_MAP, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_BALANCE_TYPE, - g_param_spec_int ("balance-type", - "balance type", - "Whether the balance is right-left or front-rear", - BALANCE_TYPE_RL, NUM_BALANCE_TYPES - 1, BALANCE_TYPE_RL, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); + properties[PROP_STREAM] = + g_param_spec_object ("stream", + "Stream", + "Libmatemixer stream", + MATE_MIXER_TYPE_STREAM, + G_PARAM_READWRITE); + + properties[PROP_BALANCE_TYPE] = + g_param_spec_int ("balance-type", + "balance type", + "Whether the balance is right-left or front-rear", + BALANCE_TYPE_RL, + NUM_BALANCE_TYPES - 1, + BALANCE_TYPE_RL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + + g_object_class_install_properties (object_class, N_PROPERTIES, properties); g_type_class_add_private (klass, sizeof (GvcBalanceBarPrivate)); } @@ -409,8 +420,8 @@ on_scale_button_press_event (GtkWidget *widget, GdkEventButton *event, GvcBalanceBar *bar) { + // XXX this is unused bar->priv->click_lock = TRUE; - return FALSE; } @@ -419,8 +430,8 @@ on_scale_button_release_event (GtkWidget *widget, GdkEventButton *event, GvcBalanceBar *bar) { + // XXX this is unused bar->priv->click_lock = FALSE; - return FALSE; } @@ -458,61 +469,36 @@ on_scale_scroll_event (GtkWidget *widget, value = value - 0.01; } } - gtk_adjustment_set_value (bar->priv->adjustment, value); + gtk_adjustment_set_value (bar->priv->adjustment, value); return TRUE; } -/* FIXME remove when we depend on a newer PA */ -static pa_cvolume * -gvc_pa_cvolume_set_position (pa_cvolume *cv, const pa_channel_map *map, pa_channel_position_t t, pa_volume_t v) { - unsigned c; - gboolean good = FALSE; - - g_assert(cv); - g_assert(map); - - g_return_val_if_fail(pa_cvolume_compatible_with_channel_map(cv, map), NULL); - g_return_val_if_fail(t < PA_CHANNEL_POSITION_MAX, NULL); - - for (c = 0; c < map->channels; c++) - if (map->map[c] == t) { - cv->values[c] = v; - good = TRUE; - } - - return good ? cv : NULL; -} - static void -on_adjustment_value_changed (GtkAdjustment *adjustment, - GvcBalanceBar *bar) +on_adjustment_value_changed (GtkAdjustment *adjustment, GvcBalanceBar *bar) { - gdouble val; - pa_cvolume cv; - const pa_channel_map *pa_map; + gdouble value; - if (bar->priv->channel_map == NULL) + if (bar->priv->stream == NULL) return; - cv = *gvc_channel_map_get_cvolume (bar->priv->channel_map); - val = gtk_adjustment_get_value (adjustment); - - pa_map = gvc_channel_map_get_pa_channel_map (bar->priv->channel_map); + value = gtk_adjustment_get_value (adjustment); switch (bar->priv->btype) { case BALANCE_TYPE_RL: - pa_cvolume_set_balance (&cv, pa_map, val); + mate_mixer_stream_set_balance (bar->priv->stream, value); break; case BALANCE_TYPE_FR: - pa_cvolume_set_fade (&cv, pa_map, val); + mate_mixer_stream_set_fade (bar->priv->stream, value); break; case BALANCE_TYPE_LFE: - gvc_pa_cvolume_set_position (&cv, pa_map, PA_CHANNEL_POSITION_LFE, val); + mate_mixer_stream_set_position_volume (bar->priv->stream, + MATE_MIXER_CHANNEL_LFE, + value); break; + default: + g_assert_not_reached (); } - - gvc_channel_map_volume_changed (bar->priv->channel_map, &cv, TRUE); } static void @@ -522,33 +508,27 @@ gvc_balance_bar_init (GvcBalanceBar *bar) } static void -gvc_balance_bar_finalize (GObject *object) +gvc_balance_bar_dispose (GObject *object) { GvcBalanceBar *bar; - g_return_if_fail (object != NULL); - g_return_if_fail (GVC_IS_BALANCE_BAR (object)); - bar = GVC_BALANCE_BAR (object); - g_return_if_fail (bar->priv != NULL); - - if (bar->priv->channel_map != NULL) { - g_signal_handlers_disconnect_by_func (G_OBJECT (bar->priv->channel_map), - on_channel_map_volume_changed, bar); - g_object_unref (bar->priv->channel_map); + if (bar->priv->stream != NULL) { + g_signal_handlers_disconnect_by_func (G_OBJECT (bar->priv->stream), + on_balance_value_changed, + bar); + g_clear_object (&bar->priv->stream); } - G_OBJECT_CLASS (gvc_balance_bar_parent_class)->finalize (object); + G_OBJECT_CLASS (gvc_balance_bar_parent_class)->dispose (object); } GtkWidget * -gvc_balance_bar_new (const GvcChannelMap *channel_map, GvcBalanceType btype) +gvc_balance_bar_new (MateMixerStream *stream, GvcBalanceType btype) { - GObject *bar; - bar = g_object_new (GVC_TYPE_BALANCE_BAR, - "channel-map", channel_map, + return g_object_new (GVC_TYPE_BALANCE_BAR, "balance-type", btype, + "stream", stream, NULL); - return GTK_WIDGET (bar); } diff --git a/mate-volume-control/src/gvc-balance-bar.h b/mate-volume-control/src/gvc-balance-bar.h index bb3b8f7..02149d0 100644 --- a/mate-volume-control/src/gvc-balance-bar.h +++ b/mate-volume-control/src/gvc-balance-bar.h @@ -21,9 +21,11 @@ #ifndef __GVC_BALANCE_BAR_H #define __GVC_BALANCE_BAR_H +#include #include +#include -#include "gvc-channel-map.h" +#include G_BEGIN_DECLS @@ -42,9 +44,11 @@ typedef enum { #define NUM_BALANCE_TYPES BALANCE_TYPE_LFE + 1 -typedef struct GvcBalanceBarPrivate GvcBalanceBarPrivate; +typedef struct _GvcBalanceBar GvcBalanceBar; +typedef struct _GvcBalanceBarClass GvcBalanceBarClass; +typedef struct _GvcBalanceBarPrivate GvcBalanceBarPrivate; -typedef struct +struct _GvcBalanceBar { #if GTK_CHECK_VERSION (3, 0, 0) GtkBox parent; @@ -52,25 +56,25 @@ typedef struct GtkHBox parent; #endif GvcBalanceBarPrivate *priv; -} GvcBalanceBar; +}; -typedef struct +struct _GvcBalanceBarClass { #if GTK_CHECK_VERSION (3, 0, 0) GtkBoxClass parent_class; #else GtkHBoxClass parent_class; #endif -} GvcBalanceBarClass; +}; GType gvc_balance_bar_get_type (void); -GtkWidget * gvc_balance_bar_new (const GvcChannelMap *map, - GvcBalanceType btype); +GtkWidget * gvc_balance_bar_new (MateMixerStream *stream, + GvcBalanceType btype); -void gvc_balance_bar_set_size_group (GvcBalanceBar *bar, - GtkSizeGroup *group, - gboolean symmetric); +void gvc_balance_bar_set_size_group (GvcBalanceBar *bar, + GtkSizeGroup *group, + gboolean symmetric); G_END_DECLS diff --git a/mate-volume-control/src/gvc-channel-bar.c b/mate-volume-control/src/gvc-channel-bar.c index 3d21119..b1bf894 100644 --- a/mate-volume-control/src/gvc-channel-bar.c +++ b/mate-volume-control/src/gvc-channel-bar.c @@ -20,15 +20,10 @@ #include "config.h" -#include -#include -#include - -#include - #include #include #include + #include #include "gvc-channel-bar.h" @@ -634,8 +629,7 @@ gvc_channel_bar_set_is_amplified (GvcChannelBar *bar, gboolean amplified) } void -gvc_channel_bar_set_base_volume (GvcChannelBar *bar, - pa_volume_t base_volume) +gvc_channel_bar_set_base_volume (GvcChannelBar *bar, guint base_volume) { g_return_if_fail (GVC_IS_CHANNEL_BAR (bar)); @@ -929,8 +923,5 @@ gvc_channel_bar_finalize (GObject *object) GtkWidget * gvc_channel_bar_new (void) { - GObject *bar; - bar = g_object_new (GVC_TYPE_CHANNEL_BAR, - NULL); - return GTK_WIDGET (bar); + return g_object_new (GVC_TYPE_CHANNEL_BAR, NULL); } diff --git a/mate-volume-control/src/gvc-channel-bar.h b/mate-volume-control/src/gvc-channel-bar.h index b398756..d31da50 100644 --- a/mate-volume-control/src/gvc-channel-bar.h +++ b/mate-volume-control/src/gvc-channel-bar.h @@ -21,6 +21,7 @@ #ifndef __GVC_CHANNEL_BAR_H #define __GVC_CHANNEL_BAR_H +#include #include G_BEGIN_DECLS diff --git a/mate-volume-control/src/gvc-combo-box.c b/mate-volume-control/src/gvc-combo-box.c index 6576efa..6004632 100644 --- a/mate-volume-control/src/gvc-combo-box.c +++ b/mate-volume-control/src/gvc-combo-box.c @@ -20,18 +20,14 @@ #include "config.h" -#include -#include -#include - #include #include #include + #include +#include #include "gvc-combo-box.h" -#include "gvc-mixer-stream.h" -#include "gvc-mixer-card.h" #define GVC_COMBO_BOX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_COMBO_BOX, GvcComboBoxPrivate)) @@ -156,7 +152,7 @@ gvc_combo_box_get_property (GObject *object, static void gvc_combo_box_class_init (GvcComboBoxClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gvc_combo_box_finalize; object_class->set_property = gvc_combo_box_set_property; @@ -213,21 +209,20 @@ gvc_combo_box_set_profiles (GvcComboBox *combo_box, g_return_if_fail (combo_box->priv->set_called == FALSE); for (l = profiles; l != NULL; l = l->next) { - GvcMixerCardProfile *p = l->data; + MateMixerDeviceProfile *p = MATE_MIXER_DEVICE_PROFILE (l->data); gtk_list_store_insert_with_values (GTK_LIST_STORE (combo_box->priv->model), NULL, G_MAXINT, - COL_NAME, p->profile, - COL_HUMAN_NAME, p->human_profile, + COL_NAME, mate_mixer_device_profile_get_name (p), + COL_HUMAN_NAME, mate_mixer_device_profile_get_description (p), -1); } combo_box->priv->set_called = TRUE; } void -gvc_combo_box_set_ports (GvcComboBox *combo_box, - const GList *ports) +gvc_combo_box_set_ports (GvcComboBox *combo_box, const GList *ports) { const GList *l; @@ -235,13 +230,13 @@ gvc_combo_box_set_ports (GvcComboBox *combo_box, g_return_if_fail (combo_box->priv->set_called == FALSE); for (l = ports; l != NULL; l = l->next) { - GvcMixerStreamPort *p = l->data; + MateMixerPort *p = MATE_MIXER_PORT (l->data); gtk_list_store_insert_with_values (GTK_LIST_STORE (combo_box->priv->model), NULL, G_MAXINT, - COL_NAME, p->port, - COL_HUMAN_NAME, p->human_port, + COL_NAME, mate_mixer_port_get_name (p), + COL_HUMAN_NAME, mate_mixer_port_get_description (p), -1); } combo_box->priv->set_called = TRUE; @@ -305,7 +300,6 @@ gvc_combo_box_init (GvcComboBox *combo_box) GtkWidget *ebox; GtkCellRenderer *renderer; - combo_box->priv = GVC_COMBO_BOX_GET_PRIVATE (combo_box); combo_box->priv->model = GTK_TREE_MODEL (gtk_list_store_new (NUM_COLS, @@ -389,10 +383,7 @@ gvc_combo_box_finalize (GObject *object) GtkWidget * gvc_combo_box_new (const char *label) { - GObject *combo_box; - combo_box = g_object_new (GVC_TYPE_COMBO_BOX, - "label", label, - NULL); - return GTK_WIDGET (combo_box); + return g_object_new (GVC_TYPE_COMBO_BOX, + "label", label, + NULL); } - diff --git a/mate-volume-control/src/gvc-mixer-dialog.c b/mate-volume-control/src/gvc-mixer-dialog.c index 58840b1..a29bdc9 100644 --- a/mate-volume-control/src/gvc-mixer-dialog.c +++ b/mate-volume-control/src/gvc-mixer-dialog.c @@ -20,11 +20,6 @@ #include "config.h" -#include -#include -#include -#include - #include #include #include @@ -36,73 +31,63 @@ #include "gvc-channel-bar.h" #include "gvc-balance-bar.h" #include "gvc-combo-box.h" -#include "gvc-mixer-control.h" -#include "gvc-mixer-card.h" -#include "gvc-mixer-sink.h" -#include "gvc-mixer-source.h" -#include "gvc-mixer-source-output.h" #include "gvc-mixer-dialog.h" #include "gvc-sound-theme-chooser.h" #include "gvc-level-bar.h" #include "gvc-speaker-test.h" - -#define SCALE_SIZE 128 +#include "mvc-helpers.h" #define GVC_MIXER_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_DIALOG, GvcMixerDialogPrivate)) -struct GvcMixerDialogPrivate +struct _GvcMixerDialogPrivate { - GvcMixerControl *mixer_control; MateMixerControl *control; - 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_scrolled_window; - GtkWidget *no_apps_label; - GtkWidget *output_treeview; - 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; - GtkWidget *click_feedback_button; - GtkWidget *audible_bell_button; - GtkSizeGroup *size_group; - GtkSizeGroup *apps_size_group; - - gdouble last_input_peak; - guint num_apps; + 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_scrolled_window; + GtkWidget *no_apps_label; + GtkWidget *output_treeview; + 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; + GtkSizeGroup *apps_size_group; + gdouble last_input_peak; + guint num_apps; }; enum { NAME_COLUMN, + DESCRIPTION_COLUMN, DEVICE_COLUMN, ACTIVE_COLUMN, - ID_COLUMN, SPEAKERS_COLUMN, NUM_COLUMNS }; enum { - HW_ID_COLUMN, HW_ICON_COLUMN, HW_NAME_COLUMN, + HW_DESCRIPTION_COLUMN, HW_STATUS_COLUMN, HW_PROFILE_COLUMN, HW_PROFILE_HUMAN_COLUMN, @@ -110,6 +95,14 @@ enum { HW_NUM_COLUMNS }; +enum { + PAGE_EVENTS, + PAGE_HARDWARE, + PAGE_INPUT, + PAGE_OUTPUT, + PAGE_APPLICATIONS +}; + enum { PROP_0, @@ -122,7 +115,7 @@ static void gvc_mixer_dialog_finalize (GObject *object); static void bar_set_stream (GvcMixerDialog *dialog, GtkWidget *bar, - GvcMixerStream *stream); + MateMixerStream *stream); static void on_adjustment_value_changed (GtkAdjustment *adjustment, GvcMixerDialog *dialog); @@ -144,59 +137,62 @@ update_default_input (GvcMixerDialog *dialog) } do { gboolean toggled; - gboolean is_default; - guint id; - GvcMixerStream *stream; + gboolean is_default = FALSE; + MateMixerStream *stream; + gchar *name; gtk_tree_model_get (model, &iter, - ID_COLUMN, &id, + NAME_COLUMN, &name, ACTIVE_COLUMN, &toggled, -1); - stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id); + stream = mate_mixer_control_get_stream (dialog->priv->control, name); if (stream == NULL) { - g_warning ("Unable to find stream for id: %u", id); + g_warning ("Unable to find stream for id: %s", name); + g_free (name); continue; } - is_default = FALSE; - if (stream == gvc_mixer_control_get_default_source (dialog->priv->mixer_control)) { + if (stream == mate_mixer_control_get_default_input_stream (dialog->priv->control)) is_default = TRUE; - } 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)); } static void update_description (GvcMixerDialog *dialog, guint column, - const char *value, - GvcMixerStream *stream) + const gchar *value, + MateMixerStream *stream) { GtkTreeModel *model; GtkTreeIter iter; - guint id; + MateMixerStreamFlags flags; + const gchar *name; + + flags = mate_mixer_stream_get_flags (stream); - if (GVC_IS_MIXER_SOURCE (stream)) + if (flags & MATE_MIXER_STREAM_INPUT) model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview)); - else if (GVC_IS_MIXER_SINK (stream)) + 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 (); + gtk_tree_model_get_iter_first (model, &iter); - id = gvc_mixer_stream_get_id (stream); + name = mate_mixer_stream_get_name (stream); do { - guint current_id; + const gchar *current_name; - gtk_tree_model_get (model, &iter, - ID_COLUMN, ¤t_id, - -1); - if (id != current_id) + gtk_tree_model_get (model, &iter, NAME_COLUMN, ¤t_name, -1); + if (!g_strcmp0 (name, current_name)) continue; gtk_list_store_set (GTK_LIST_STORE (model), @@ -208,28 +204,27 @@ update_description (GvcMixerDialog *dialog, } static void -port_selection_changed (GvcComboBox *combo_box, - const char *port, +port_selection_changed (GvcComboBox *combo, + const gchar *port, GvcMixerDialog *dialog) { - GvcMixerStream *stream; + MateMixerStream *stream; - stream = g_object_get_data (G_OBJECT (combo_box), "stream"); + stream = g_object_get_data (G_OBJECT (combo), "stream"); if (stream == NULL) { g_warning ("Could not find stream for port combo box"); return; } - if (gvc_mixer_stream_change_port (stream, port) == FALSE) { - g_warning ("Could not change port for stream"); - } + + mate_mixer_stream_set_active_port (stream, port); } static void update_output_settings (GvcMixerDialog *dialog) { - GvcMixerStream *stream; - const GvcChannelMap *map; - const GList *ports; + MateMixerStream *stream; + MateMixerStreamFlags flags; + const GList *ports; g_debug ("Updating output settings"); if (dialog->priv->output_balance_bar != NULL) { @@ -253,24 +248,20 @@ update_output_settings (GvcMixerDialog *dialog) dialog->priv->output_port_combo = NULL; } - stream = gvc_mixer_control_get_default_sink (dialog->priv->mixer_control); + stream = mate_mixer_control_get_default_output_stream (dialog->priv->control); if (stream == NULL) { g_warning ("Default sink stream not found"); return; } + flags = mate_mixer_stream_get_flags (stream); + gvc_channel_bar_set_base_volume (GVC_CHANNEL_BAR (dialog->priv->output_bar), - gvc_mixer_stream_get_base_volume (stream)); + mate_mixer_stream_get_base_volume (stream)); gvc_channel_bar_set_is_amplified (GVC_CHANNEL_BAR (dialog->priv->output_bar), - gvc_mixer_stream_get_can_decibel (stream)); - - map = gvc_mixer_stream_get_channel_map (stream); - if (map == NULL) { - g_warning ("Default sink stream has no channel map"); - return; - } + flags & MATE_MIXER_STREAM_HAS_DECIBEL_VOLUME); - dialog->priv->output_balance_bar = gvc_balance_bar_new (map, 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, @@ -281,8 +272,8 @@ update_output_settings (GvcMixerDialog *dialog) FALSE, FALSE, 6); gtk_widget_show (dialog->priv->output_balance_bar); - if (gvc_channel_map_can_fade (map)) { - dialog->priv->output_fade_bar = gvc_balance_bar_new (map, BALANCE_TYPE_FR); + 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, @@ -294,8 +285,8 @@ update_output_settings (GvcMixerDialog *dialog) gtk_widget_show (dialog->priv->output_fade_bar); } - if (gvc_channel_map_has_lfe (map)) { - dialog->priv->output_lfe_bar = gvc_balance_bar_new (map, BALANCE_TYPE_LFE); + 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, @@ -307,15 +298,19 @@ update_output_settings (GvcMixerDialog *dialog) gtk_widget_show (dialog->priv->output_lfe_bar); } - ports = gvc_mixer_stream_get_ports (stream); + ports = mate_mixer_stream_list_ports (stream); if (ports != NULL) { - const GvcMixerStreamPort *port; - port = gvc_mixer_stream_get_port (stream); + MateMixerPort *port; + + port = mate_mixer_stream_get_active_port (stream); dialog->priv->output_port_combo = gvc_combo_box_new (_("Co_nnector:")); gvc_combo_box_set_ports (GVC_COMBO_BOX (dialog->priv->output_port_combo), ports); - gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->output_port_combo), port->port); + + 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); @@ -330,7 +325,7 @@ update_output_settings (GvcMixerDialog *dialog) } /* FIXME: We could make this into a "No settings" label instead */ - gtk_widget_set_sensitive (dialog->priv->output_balance_bar, gvc_channel_map_can_balance (map)); + gtk_widget_set_sensitive (dialog->priv->output_balance_bar, flags & MATE_MIXER_STREAM_CAN_BALANCE); } static void @@ -343,47 +338,44 @@ update_default_output (GvcMixerDialog *dialog) gtk_tree_model_get_iter_first (model, &iter); do { gboolean toggled; - gboolean is_default; - guint id; - GvcMixerStream *stream; + gboolean is_default = FALSE; + gchar *name; + MateMixerStream *stream; gtk_tree_model_get (model, &iter, - ID_COLUMN, &id, + NAME_COLUMN, &name, ACTIVE_COLUMN, &toggled, -1); - stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id); + stream = mate_mixer_control_get_stream (dialog->priv->control, name); if (stream == NULL) { - g_warning ("Unable to find stream for id: %u", id); + g_warning ("Unable to find stream for id: %s", name); + g_free (name); continue; } - is_default = FALSE; - if (stream == gvc_mixer_control_get_default_sink (dialog->priv->mixer_control)) { + if (stream == mate_mixer_control_get_default_output_stream (dialog->priv->control)) is_default = TRUE; - } 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)); } static void -on_mixer_control_default_sink_changed (GvcMixerControl *control, - guint id, - GvcMixerDialog *dialog) +on_control_default_output_notify (MateMixerControl *control, + GParamSpec *pspec, + GvcMixerDialog *dialog) { - GvcMixerStream *stream; + MateMixerStream *stream; - g_debug ("GvcMixerDialog: default sink changed: %u", id); + g_debug ("Default output stream has changed"); + + stream = mate_mixer_control_get_default_output_stream (control); - if (id == PA_INVALID_INDEX) - stream = NULL; - else - stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, - id); bar_set_stream (dialog, dialog->priv->output_bar, stream); update_output_settings (dialog); @@ -395,8 +387,7 @@ on_mixer_control_default_sink_changed (GvcMixerControl *control, #define DECAY_STEP .15 static void -update_input_peak (GvcMixerDialog *dialog, - gdouble v) +update_input_peak (GvcMixerDialog *dialog, gdouble v) { GtkAdjustment *adj; @@ -416,19 +407,12 @@ update_input_peak (GvcMixerDialog *dialog, } } -static void -update_input_meter (GvcMixerDialog *dialog, - uint32_t source_index, - uint32_t sink_input_idx, - double v) -{ - update_input_peak (dialog, v); -} - static void on_monitor_suspended_callback (pa_stream *s, void *userdata) { + // XXX + /* GvcMixerDialog *dialog; dialog = userdata; @@ -440,209 +424,122 @@ on_monitor_suspended_callback (pa_stream *s, PA_INVALID_INDEX, -1); } + */ } static void -on_monitor_read_callback (pa_stream *s, - size_t length, - void *userdata) -{ - GvcMixerDialog *dialog; - const void *data; - double v; - - dialog = userdata; - - if (pa_stream_peek (s, &data, &length) < 0) { - g_warning ("Failed to read data from stream"); - return; - } - - assert (length > 0); - assert (length % sizeof (float) == 0); - - v = ((const float *) data)[length / sizeof (float) -1]; - - pa_stream_drop (s); - - if (v < 0) { - v = 0; - } - if (v > 1) { - v = 1; - } - - update_input_meter (dialog, - pa_stream_get_device_index (s), - pa_stream_get_monitor_stream (s), - v); -} - -static void -create_monitor_stream_for_source (GvcMixerDialog *dialog, - GvcMixerStream *stream) -{ - pa_stream *s; - char t[16]; - pa_buffer_attr attr; - pa_sample_spec ss; - pa_context *context; - int res; - pa_proplist *proplist; - gboolean has_monitor; - - if (stream == NULL) { - return; - } - has_monitor = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (stream), "has-monitor")); - if (has_monitor != FALSE) { - return; - } - - g_debug ("Create monitor for %u", - gvc_mixer_stream_get_index (stream)); - - context = gvc_mixer_control_get_pa_context (dialog->priv->mixer_control); - - if (pa_context_get_server_protocol_version (context) < 13) { - return; - } - - ss.channels = 1; - ss.format = PA_SAMPLE_FLOAT32; - ss.rate = 25; - - memset (&attr, 0, sizeof (attr)); - attr.fragsize = sizeof (float); - attr.maxlength = (uint32_t) -1; - - snprintf (t, sizeof (t), "%u", gvc_mixer_stream_get_index (stream)); - - proplist = pa_proplist_new (); - pa_proplist_sets (proplist, PA_PROP_APPLICATION_ID, "org.mate.VolumeControl"); - s = pa_stream_new_with_proplist (context, _("Peak detect"), &ss, NULL, proplist); - pa_proplist_free (proplist); - if (s == NULL) { - g_warning ("Failed to create monitoring stream"); - return; - } - - pa_stream_set_read_callback (s, on_monitor_read_callback, dialog); - pa_stream_set_suspended_callback (s, on_monitor_suspended_callback, dialog); - - res = pa_stream_connect_record (s, - t, - &attr, - (pa_stream_flags_t) (PA_STREAM_DONT_MOVE - |PA_STREAM_PEAK_DETECT - |PA_STREAM_ADJUST_LATENCY)); - if (res < 0) { - g_warning ("Failed to connect monitoring stream"); - pa_stream_unref (s); - } else { - g_object_set_data (G_OBJECT (stream), "has-monitor", GINT_TO_POINTER (TRUE)); - g_object_set_data (G_OBJECT (dialog->priv->input_level_bar), "pa_stream", s); - g_object_set_data (G_OBJECT (dialog->priv->input_level_bar), "stream", stream); - } -} - -static void -stop_monitor_stream_for_source (GvcMixerDialog *dialog) +on_stream_monitor_value (MateMixerStream *stream, + gdouble value, + GvcMixerDialog *dialog) { - pa_stream *s; - pa_context *context; - int res; - GvcMixerStream *stream; - - s = g_object_get_data (G_OBJECT (dialog->priv->input_level_bar), "pa_stream"); - if (s == NULL) - return; - stream = g_object_get_data (G_OBJECT (dialog->priv->input_level_bar), "stream"); - g_assert (stream != NULL); - - g_debug ("Stopping monitor for %u", pa_stream_get_index (s)); - - context = gvc_mixer_control_get_pa_context (dialog->priv->mixer_control); - - if (pa_context_get_server_protocol_version (context) < 13) { - return; - } - - res = pa_stream_disconnect (s); - if (res == 0) - g_object_set_data (G_OBJECT (stream), "has-monitor", GINT_TO_POINTER (FALSE)); - g_object_set_data (G_OBJECT (dialog->priv->input_level_bar), "pa_stream", NULL); - g_object_set_data (G_OBJECT (dialog->priv->input_level_bar), "stream", NULL); + g_debug ("Monitor %.2f", value); + update_input_peak (dialog, value); } static void update_input_settings (GvcMixerDialog *dialog) { - const GList *ports; - GvcMixerStream *stream; + MateMixerStream *stream; + MateMixerStreamFlags flags; + const GList *ports; g_debug ("Updating input settings"); - stop_monitor_stream_for_source (dialog); - 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 = gvc_mixer_control_get_default_source (dialog->priv->mixer_control); + stream = mate_mixer_control_get_default_input_stream (dialog->priv->control); if (stream == NULL) { g_debug ("Default source stream not found"); 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), - gvc_mixer_stream_get_base_volume (stream)); + mate_mixer_stream_get_base_volume (stream)); + + // XXX probably wrong gvc_channel_bar_set_is_amplified (GVC_CHANNEL_BAR (dialog->priv->input_bar), - gvc_mixer_stream_get_can_decibel (stream)); + flags & MATE_MIXER_STREAM_HAS_DECIBEL_VOLUME); - ports = gvc_mixer_stream_get_ports (stream); + ports = mate_mixer_stream_list_ports (stream); if (ports != NULL) { - const GvcMixerStreamPort *port; - port = gvc_mixer_stream_get_port (stream); + MateMixerPort *port; + + port = mate_mixer_stream_get_active_port (stream); dialog->priv->input_port_combo = gvc_combo_box_new (_("Co_nnector:")); gvc_combo_box_set_ports (GVC_COMBO_BOX (dialog->priv->input_port_combo), ports); - gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->input_port_combo), port->port); - g_object_set_data (G_OBJECT (dialog->priv->input_port_combo), "stream", stream); - g_signal_connect (G_OBJECT (dialog->priv->input_port_combo), "changed", - G_CALLBACK (port_selection_changed), dialog); + 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); - gvc_combo_box_set_size_group (GVC_COMBO_BOX (dialog->priv->input_port_combo), dialog->priv->size_group, FALSE); gtk_box_pack_start (GTK_BOX (dialog->priv->input_settings_box), dialog->priv->input_port_combo, TRUE, TRUE, 0); + gtk_widget_show (dialog->priv->input_port_combo); } - - create_monitor_stream_for_source (dialog, stream); } static void -on_mixer_control_default_source_changed (GvcMixerControl *control, - guint id, - GvcMixerDialog *dialog) +on_control_default_input_notify (MateMixerControl *control, + GParamSpec *pspec, + GvcMixerDialog *dialog) { - GvcMixerStream *stream; + MateMixerStream *stream; + MateMixerStream *current; GtkAdjustment *adj; - g_debug ("GvcMixerDialog: default source changed: %u", id); + stream = mate_mixer_control_get_default_input_stream (control); - if (id == PA_INVALID_INDEX) - stream = NULL; - else - stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id); + current = g_object_get_data (G_OBJECT (dialog->priv->input_bar), "gvc-mixer-dialog-stream"); + if (current != NULL) + g_signal_handlers_disconnect_by_func (G_OBJECT (current), + 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); + } + + // 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); + + 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); @@ -655,88 +552,11 @@ on_mixer_control_default_source_changed (GvcMixerControl *control, update_default_input (dialog); } -static void -gvc_mixer_dialog_set_mixer_control (GvcMixerDialog *dialog, - GvcMixerControl *control) -{ - g_return_if_fail (GVC_MIXER_DIALOG (dialog)); - g_return_if_fail (GVC_IS_MIXER_CONTROL (control)); - - g_object_ref (control); - - if (dialog->priv->mixer_control != NULL) { - g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control, - G_CALLBACK (on_mixer_control_default_sink_changed), - dialog); - g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control, - G_CALLBACK (on_mixer_control_default_source_changed), - dialog); - g_object_unref (dialog->priv->mixer_control); - } - - dialog->priv->mixer_control = control; - - g_signal_connect (dialog->priv->mixer_control, - "default-sink-changed", - G_CALLBACK (on_mixer_control_default_sink_changed), - dialog); - g_signal_connect (dialog->priv->mixer_control, - "default-source-changed", - G_CALLBACK (on_mixer_control_default_source_changed), - dialog); - - g_object_notify (G_OBJECT (dialog), "mixer-control"); -} - -static GvcMixerControl * -gvc_mixer_dialog_get_mixer_control (GvcMixerDialog *dialog) -{ - g_return_val_if_fail (GVC_IS_MIXER_DIALOG (dialog), NULL); - - return dialog->priv->mixer_control; -} - -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_MIXER_CONTROL: - gvc_mixer_dialog_set_mixer_control (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_MIXER_CONTROL: - g_value_set_object (value, gvc_mixer_dialog_get_mixer_control (self)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - static void on_adjustment_value_changed (GtkAdjustment *adjustment, GvcMixerDialog *dialog) { - GvcMixerStream *stream; + MateMixerStream *stream; stream = g_object_get_data (G_OBJECT (adjustment), "gvc-mixer-dialog-stream"); if (stream != NULL) { @@ -755,10 +575,9 @@ on_adjustment_value_changed (GtkAdjustment *adjustment, /* 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) - gvc_mixer_stream_set_is_muted (stream, TRUE); - /* Only push the volume if it's actually changed */ - if (gvc_mixer_stream_set_volume(stream, (pa_volume_t) rounded) != FALSE) - gvc_mixer_stream_push_volume (stream); + mate_mixer_stream_set_mute (stream, TRUE); + + mate_mixer_stream_set_volume (stream, rounded); } } @@ -768,13 +587,13 @@ on_bar_is_muted_notify (GObject *object, GvcMixerDialog *dialog) { gboolean is_muted; - GvcMixerStream *stream; + MateMixerStream *stream; is_muted = gvc_channel_bar_get_is_muted (GVC_CHANNEL_BAR (object)); stream = g_object_get_data (object, "gvc-mixer-dialog-stream"); if (stream != NULL) { - gvc_mixer_stream_change_is_muted (stream, is_muted); + mate_mixer_stream_set_mute (stream, is_muted); } else { char *name; g_object_get (object, "name", &name, NULL); @@ -784,30 +603,25 @@ on_bar_is_muted_notify (GObject *object, } static GtkWidget * -lookup_bar_for_stream (GvcMixerDialog *dialog, - GvcMixerStream *stream) +lookup_bar_for_stream (GvcMixerDialog *dialog, MateMixerStream *stream) { - GtkWidget *bar; - - bar = g_hash_table_lookup (dialog->priv->bars, GUINT_TO_POINTER (gvc_mixer_stream_get_id (stream))); - - return bar; + return g_hash_table_lookup (dialog->priv->bars, mate_mixer_stream_get_name (stream)); } static GtkWidget * lookup_combo_box_for_stream (GvcMixerDialog *dialog, - GvcMixerStream *stream) + MateMixerStream *stream) { - GvcMixerStream *combo_stream; - guint id; + MateMixerStream *combo_stream; + const gchar *name; - id = gvc_mixer_stream_get_id (stream); + 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 (id == gvc_mixer_stream_get_id (combo_stream)) + if (!g_strcmp0 (name, mate_mixer_stream_get_name (combo_stream))) return dialog->priv->output_port_combo; } } @@ -816,7 +630,7 @@ lookup_combo_box_for_stream (GvcMixerDialog *dialog, combo_stream = g_object_get_data (G_OBJECT (dialog->priv->input_port_combo), "stream"); if (combo_stream != NULL) { - if (id == gvc_mixer_stream_get_id (combo_stream)) + if (!g_strcmp0 (name, mate_mixer_stream_get_name (combo_stream))) return dialog->priv->input_port_combo; } } @@ -825,12 +639,12 @@ lookup_combo_box_for_stream (GvcMixerDialog *dialog, } static void -on_stream_description_notify (GvcMixerStream *stream, +on_stream_description_notify (MateMixerStream *stream, GParamSpec *pspec, GvcMixerDialog *dialog) { update_description (dialog, NAME_COLUMN, - gvc_mixer_stream_get_description (stream), + mate_mixer_stream_get_description (stream), stream); } @@ -839,23 +653,27 @@ on_stream_port_notify (GObject *object, GParamSpec *pspec, GvcMixerDialog *dialog) { - GvcComboBox *combo_box; - char *port; + GvcComboBox *combo; + MateMixerPort *port; - combo_box = GVC_COMBO_BOX (lookup_combo_box_for_stream (dialog, GVC_MIXER_STREAM (object))); - if (combo_box == NULL) + combo = GVC_COMBO_BOX (lookup_combo_box_for_stream (dialog, MATE_MIXER_STREAM (object))); + if (combo == NULL) return; - g_signal_handlers_block_by_func (G_OBJECT (combo_box), + g_signal_handlers_block_by_func (G_OBJECT (combo), port_selection_changed, dialog); - g_object_get (object, "port", &port, NULL); - gvc_combo_box_set_active (GVC_COMBO_BOX (combo_box), port); + 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)); + } - g_signal_handlers_unblock_by_func (G_OBJECT (combo_box), - port_selection_changed, - dialog); + g_signal_handlers_unblock_by_func (G_OBJECT (combo), + port_selection_changed, + dialog); } static void @@ -863,17 +681,17 @@ on_stream_volume_notify (GObject *object, GParamSpec *pspec, GvcMixerDialog *dialog) { - GvcMixerStream *stream; + MateMixerStream *stream; GtkWidget *bar; GtkAdjustment *adj; - stream = GVC_MIXER_STREAM (object); + 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_volume_notify()", - gvc_mixer_stream_get_name (stream)); + mate_mixer_stream_get_name (stream)); return; } @@ -884,7 +702,7 @@ on_stream_volume_notify (GObject *object, dialog); gtk_adjustment_set_value (adj, - gvc_mixer_stream_get_volume (stream)); + mate_mixer_stream_get_volume (stream)); g_signal_handlers_unblock_by_func (adj, on_adjustment_value_changed, @@ -892,28 +710,27 @@ on_stream_volume_notify (GObject *object, } static void -on_stream_is_muted_notify (GObject *object, - GParamSpec *pspec, - GvcMixerDialog *dialog) +on_stream_mute_notify (GObject *object, + GParamSpec *pspec, + GvcMixerDialog *dialog) { - GvcMixerStream *stream; + MateMixerStream *stream; GtkWidget *bar; gboolean is_muted; - stream = GVC_MIXER_STREAM (object); + 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()", - gvc_mixer_stream_get_name (stream)); + mate_mixer_stream_get_name (stream)); return; } - is_muted = gvc_mixer_stream_get_is_muted (stream); - gvc_channel_bar_set_is_muted (GVC_CHANNEL_BAR (bar), - is_muted); + is_muted = mate_mixer_stream_get_mute (stream); + gvc_channel_bar_set_is_muted (GVC_CHANNEL_BAR (bar), is_muted); - if (stream == gvc_mixer_control_get_default_sink (dialog->priv->mixer_control)) { + if (stream == mate_mixer_control_get_default_output_stream (dialog->priv->control)) { gtk_widget_set_sensitive (dialog->priv->applications_box, !is_muted); } @@ -921,12 +738,12 @@ on_stream_is_muted_notify (GObject *object, } static void -save_bar_for_stream (GvcMixerDialog *dialog, - GvcMixerStream *stream, - GtkWidget *bar) +save_bar_for_stream (GvcMixerDialog *dialog, + MateMixerStream *stream, + GtkWidget *bar) { g_hash_table_insert (dialog->priv->bars, - GUINT_TO_POINTER (gvc_mixer_stream_get_id (stream)), + (gpointer) mate_mixer_stream_get_name (stream), bar); } @@ -956,14 +773,10 @@ create_bar (GvcMixerDialog *dialog, } static void -bar_set_stream (GvcMixerDialog *dialog, - GtkWidget *bar, - GvcMixerStream *stream) +bar_set_stream (GvcMixerDialog *dialog, GtkWidget *bar, MateMixerStream *stream) { - GtkAdjustment *adj; - GvcMixerStream *old_stream; - - g_assert (bar != NULL); + GtkAdjustment *adj; + MateMixerStream *old_stream; old_stream = g_object_get_data (G_OBJECT (bar), "gvc-mixer-dialog-stream"); if (old_stream != NULL) { @@ -971,19 +784,21 @@ bar_set_stream (GvcMixerDialog *dialog, g_object_get (bar, "name", &name, NULL); g_debug ("Disconnecting old stream '%s' from bar '%s'", - gvc_mixer_stream_get_name (old_stream), name); + mate_mixer_stream_get_name (old_stream), name); g_free (name); - g_signal_handlers_disconnect_by_func (old_stream, on_stream_is_muted_notify, dialog); + g_signal_handlers_disconnect_by_func (old_stream, on_stream_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); - g_hash_table_remove (dialog->priv->bars, GUINT_TO_POINTER (gvc_mixer_stream_get_id (old_stream))); + + 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); @@ -993,24 +808,23 @@ bar_set_stream (GvcMixerDialog *dialog, if (stream != NULL) { gboolean is_muted; - is_muted = gvc_mixer_stream_get_is_muted (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, - gvc_mixer_stream_get_volume (stream)); + gtk_adjustment_set_value (adj, mate_mixer_stream_get_volume (stream)); g_signal_connect (stream, - "notify::is-muted", - G_CALLBACK (on_stream_is_muted_notify), + "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::port", + "notify::active-port", G_CALLBACK (on_stream_port_notify), dialog); g_signal_connect (adj, @@ -1021,57 +835,120 @@ bar_set_stream (GvcMixerDialog *dialog, } static void -add_stream (GvcMixerDialog *dialog, - GvcMixerStream *stream) +add_stream (GvcMixerDialog *dialog, MateMixerStream *stream) { - GtkWidget *bar; - gboolean is_muted; - gboolean is_default; - GtkAdjustment *adj; - const char *id; + GtkWidget *bar = NULL; + gboolean is_default = FALSE; + MateMixerClientStream *client = NULL; + MateMixerStreamFlags flags; - g_assert (stream != NULL); + flags = mate_mixer_stream_get_flags (stream); - if (gvc_mixer_stream_is_event_stream (stream) != FALSE) + if (flags & MATE_MIXER_STREAM_EVENT) return; + if (flags & MATE_MIXER_STREAM_APPLICATION) { + const gchar *app_id; - bar = NULL; - is_default = FALSE; - id = gvc_mixer_stream_get_application_id (stream); + client = MATE_MIXER_CLIENT_STREAM (stream); + app_id = mate_mixer_client_stream_get_app_id (client); - if (stream == gvc_mixer_control_get_default_sink (dialog->priv->mixer_control)) { - bar = dialog->priv->output_bar; - is_muted = gvc_mixer_stream_get_is_muted (stream); - is_default = TRUE; - gtk_widget_set_sensitive (dialog->priv->applications_box, - !is_muted); - adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (bar))); - g_signal_handlers_disconnect_by_func(adj, on_adjustment_value_changed, dialog); - update_output_settings (dialog); - } else if (stream == gvc_mixer_control_get_default_source (dialog->priv->mixer_control)) { - bar = dialog->priv->input_bar; - adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (bar))); - g_signal_handlers_disconnect_by_func(adj, on_adjustment_value_changed, dialog); - update_input_settings (dialog); - is_default = TRUE; - } else if (stream == gvc_mixer_control_get_event_sink_input (dialog->priv->mixer_control)) { - bar = dialog->priv->effects_bar; - g_debug ("Adding effects stream"); - } else if (! GVC_IS_MIXER_SOURCE (stream) - && !GVC_IS_MIXER_SINK (stream) - && !gvc_mixer_stream_is_virtual (stream) - && g_strcmp0 (id, "org.mate.VolumeControl") != 0 - && g_strcmp0 (id, "org.PulseAudio.pavucontrol") != 0) { - const char *name; + /* 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; + } + + if (client == NULL) { + GtkTreeModel *model; + GtkTreeIter iter; + MateMixerStream *input; + MateMixerStream *output; + GtkAdjustment *adj; + + input = mate_mixer_control_get_default_input_stream (dialog->priv->control); + output = mate_mixer_control_get_default_output_stream (dialog->priv->control); + + 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)); + + gtk_list_store_append (GTK_LIST_STORE (model), &iter); + gtk_list_store_set (GTK_LIST_STORE (model), + &iter, + NAME_COLUMN, mate_mixer_stream_get_name (stream), + DESCRIPTION_COLUMN, mate_mixer_stream_get_description (stream), + DEVICE_COLUMN, "", + ACTIVE_COLUMN, is_default, + -1); + g_signal_connect (stream, + "notify::description", + G_CALLBACK (on_stream_description_notify), + dialog); + } 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; + } + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview)); + + gtk_list_store_append (GTK_LIST_STORE (model), &iter); + gtk_list_store_set (GTK_LIST_STORE (model), + &iter, + NAME_COLUMN, mate_mixer_stream_get_name (stream), + DESCRIPTION_COLUMN, mate_mixer_stream_get_description (stream), + DEVICE_COLUMN, "", + ACTIVE_COLUMN, is_default, + SPEAKERS_COLUMN, mvc_channel_map_to_pretty_string (stream), + -1); + g_signal_connect (stream, + "notify::description", + G_CALLBACK (on_stream_description_notify), + dialog); + } + } else { + const gchar *name; + const gchar *icon; bar = create_bar (dialog, dialog->priv->apps_size_group, FALSE); - name = gvc_mixer_stream_get_name (stream); + // 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); @@ -1079,51 +956,18 @@ add_stream (GvcMixerDialog *dialog, g_free (escaped); } - gvc_channel_bar_set_icon_name (GVC_CHANNEL_BAR (bar), - gvc_mixer_stream_get_icon_name (stream)); + 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); - dialog->priv->num_apps++; gtk_widget_hide (dialog->priv->no_apps_label); - } - - if (GVC_IS_MIXER_SOURCE (stream)) { - GtkTreeModel *model; - GtkTreeIter iter; - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview)); - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - gtk_list_store_set (GTK_LIST_STORE (model), - &iter, - NAME_COLUMN, gvc_mixer_stream_get_description (stream), - DEVICE_COLUMN, "", - ACTIVE_COLUMN, is_default, - ID_COLUMN, gvc_mixer_stream_get_id (stream), - -1); - g_signal_connect (stream, - "notify::description", - G_CALLBACK (on_stream_description_notify), - dialog); - } else if (GVC_IS_MIXER_SINK (stream)) { - GtkTreeModel *model; - GtkTreeIter iter; - const GvcChannelMap *map; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview)); - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - map = gvc_mixer_stream_get_channel_map (stream); - gtk_list_store_set (GTK_LIST_STORE (model), - &iter, - NAME_COLUMN, gvc_mixer_stream_get_description (stream), - DEVICE_COLUMN, "", - ACTIVE_COLUMN, is_default, - ID_COLUMN, gvc_mixer_stream_get_id (stream), - SPEAKERS_COLUMN, gvc_channel_map_get_mapping (map), - -1); - g_signal_connect (stream, - "notify::description", - G_CALLBACK (on_stream_description_notify), - dialog); + dialog->priv->num_apps++; } if (bar != NULL) { @@ -1133,56 +977,51 @@ add_stream (GvcMixerDialog *dialog, } static void -on_control_stream_added (GvcMixerControl *control, - guint id, - GvcMixerDialog *dialog) +on_control_stream_added (MateMixerControl *control, + const gchar *name, + GvcMixerDialog *dialog) { - GvcMixerStream *stream; - GtkWidget *bar; + MateMixerStream *stream; + GtkWidget *bar; - bar = g_hash_table_lookup (dialog->priv->bars, GUINT_TO_POINTER (id)); + bar = g_hash_table_lookup (dialog->priv->bars, name); if (bar != NULL) { - g_debug ("GvcMixerDialog: Stream %u already added", id); + g_debug ("Ignoring already known stream %s", name); return; } - stream = gvc_mixer_control_lookup_stream_id (control, id); - if (stream != NULL) { + stream = mate_mixer_control_get_stream (control, name); + if (G_LIKELY (stream != NULL)) add_stream (dialog, stream); - } } static gboolean -find_item_by_id (GtkTreeModel *model, - guint id, - guint column, - GtkTreeIter *iter) +find_tree_item_by_name (GtkTreeModel *model, + const gchar *name, + guint column, + GtkTreeIter *iter) { - gboolean found_item; - - found_item = FALSE; + gboolean found = FALSE; - if (!gtk_tree_model_get_iter_first (model, iter)) { + if (!gtk_tree_model_get_iter_first (model, iter)) return FALSE; - } do { - guint t_id; + gchar *n; - gtk_tree_model_get (model, iter, - column, &t_id, -1); + gtk_tree_model_get (model, iter, column, &n, -1); - if (id == t_id) { - found_item = TRUE; - } - } while (!found_item && gtk_tree_model_iter_next (model, iter)); + if (!g_strcmp0 (name, n)) + found = TRUE; + + g_free (n); + } while (!found && gtk_tree_model_iter_next (model, iter)); - return found_item; + return found; } static void -remove_stream (GvcMixerDialog *dialog, - guint id) +remove_stream (GvcMixerDialog *dialog, const gchar *name) { GtkWidget *bar; gboolean found; @@ -1190,17 +1029,17 @@ remove_stream (GvcMixerDialog *dialog, GtkTreeModel *model; /* remove bars for applications and reset fixed bars */ - bar = g_hash_table_lookup (dialog->priv->bars, GUINT_TO_POINTER (id)); + 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) { - char *name; - g_object_get (bar, "name", &name, NULL); - g_debug ("Removing stream for bar '%s'", name); - g_free (name); + || 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); bar_set_stream (dialog, bar, NULL); } else if (bar != NULL) { - g_hash_table_remove (dialog->priv->bars, GUINT_TO_POINTER (id)); + g_hash_table_remove (dialog->priv->bars, name); gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (bar)), bar); dialog->priv->num_apps--; @@ -1211,12 +1050,12 @@ remove_stream (GvcMixerDialog *dialog, /* remove from any models */ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview)); - found = find_item_by_id (GTK_TREE_MODEL (model), id, ID_COLUMN, &iter); + found = find_tree_item_by_name (GTK_TREE_MODEL (model), name, NAME_COLUMN, &iter); if (found) { gtk_list_store_remove (GTK_LIST_STORE (model), &iter); } model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview)); - found = find_item_by_id (GTK_TREE_MODEL (model), id, ID_COLUMN, &iter); + found = find_tree_item_by_name (GTK_TREE_MODEL (model), name, NAME_COLUMN, &iter); if (found) { gtk_list_store_remove (GTK_LIST_STORE (model), &iter); } @@ -1224,76 +1063,138 @@ remove_stream (GvcMixerDialog *dialog, static void on_control_stream_removed (GvcMixerControl *control, - guint id, + const gchar *name, GvcMixerDialog *dialog) { - remove_stream (dialog, id); + remove_stream (dialog, name); +} + +static gchar * +card_profile_status (MateMixerDeviceProfile *profile) +{ + guint inputs; + guint outputs; + gchar *inputs_str = NULL; + gchar *outputs_str = NULL; + + inputs = mate_mixer_device_profile_get_num_input_streams (profile); + outputs = mate_mixer_device_profile_get_num_output_streams (profile); + + 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 -add_card (GvcMixerDialog *dialog, - GvcMixerCard *card) +add_device (GvcMixerDialog *dialog, MateMixerDevice *device) { GtkTreeModel *model; GtkTreeIter iter; GtkTreeSelection *selection; - GvcMixerCardProfile *profile; + MateMixerDeviceProfile *profile; GIcon *icon; - guint index; + const gchar *name; + const gchar *profile_name; + gchar *profile_status; model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview)); - index = gvc_mixer_card_get_index (card); - if (find_item_by_id (GTK_TREE_MODEL (model), index, HW_ID_COLUMN, &iter) == FALSE) + 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 = gvc_mixer_card_get_profile (card); + + profile = mate_mixer_device_get_active_profile (device); g_assert (profile != NULL); - icon = g_themed_icon_new_with_default_fallbacks (gvc_mixer_card_get_icon_name (card)); + icon = g_themed_icon_new_with_default_fallbacks (mate_mixer_device_get_icon (device)); + //FIXME we need the status (default for a profile?) here + + profile_name = mate_mixer_device_profile_get_name (profile); + profile_status = card_profile_status (profile); + gtk_list_store_set (GTK_LIST_STORE (model), &iter, - HW_NAME_COLUMN, gvc_mixer_card_get_name (card), - HW_ID_COLUMN, index, + 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->profile, - HW_PROFILE_HUMAN_COLUMN, profile->human_profile, - HW_STATUS_COLUMN, profile->status, - HW_SENSITIVE_COLUMN, g_strcmp0 (profile->profile, "off") != 0, + HW_PROFILE_COLUMN, profile_name, + HW_PROFILE_HUMAN_COLUMN, mate_mixer_device_profile_get_description (profile), + 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)); + 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) { - GvcMixerCard *selected; + MateMixerDevice *selected; /* Set the current profile if it changed for the selected card */ - selected = g_object_get_data (G_OBJECT (dialog->priv->hw_profile_combo), "card"); - if (gvc_mixer_card_get_index (selected) == gvc_mixer_card_get_index (card)) { + selected = g_object_get_data (G_OBJECT (dialog->priv->hw_profile_combo), "device"); + + 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->profile); + profile_name); + g_object_set (G_OBJECT (dialog->priv->hw_profile_combo), - "show-button", profile->n_sinks == 1, + "show-button", + mate_mixer_device_profile_get_num_output_streams (profile) >= 1, NULL); } } } static void -on_control_card_added (GvcMixerControl *control, - guint id, - GvcMixerDialog *dialog) +on_control_device_added (MateMixerControl *control, const gchar *name, GvcMixerDialog *dialog) { - GvcMixerCard *card; + MateMixerDevice *device; - card = gvc_mixer_control_lookup_card_id (control, id); - if (card != NULL) { - add_card (dialog, card); - } + device = mate_mixer_control_get_device (control, name); + if (device != NULL) + add_device (dialog, device); } static void -remove_card (GvcMixerDialog *dialog, - guint id) +remove_card (GvcMixerDialog *dialog, const gchar *name) { gboolean found; GtkTreeIter iter; @@ -1301,17 +1202,18 @@ remove_card (GvcMixerDialog *dialog, /* remove from any models */ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview)); - found = find_item_by_id (GTK_TREE_MODEL (model), id, HW_ID_COLUMN, &iter); + 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); } } + static void -on_control_card_removed (GvcMixerControl *control, - guint id, - GvcMixerDialog *dialog) +on_control_device_removed (GvcMixerControl *control, + const gchar *name, + GvcMixerDialog *dialog) { - remove_card (dialog, id); + remove_card (dialog, name); } static void @@ -1343,7 +1245,7 @@ on_input_radio_toggled (GtkCellRendererToggle *renderer, GtkTreeIter iter; GtkTreePath *path; gboolean toggled; - guint id; + gchar *name; model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview)); @@ -1352,23 +1254,21 @@ on_input_radio_toggled (GtkCellRendererToggle *renderer, gtk_tree_path_free (path); gtk_tree_model_get (model, &iter, - ID_COLUMN, &id, + NAME_COLUMN, &name, ACTIVE_COLUMN, &toggled, -1); - toggled ^= 1; - if (toggled) { - GvcMixerStream *stream; + if (toggled ^ 1) { + MateMixerStream *stream; - g_debug ("Default input selected: %u", id); - stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id); - if (stream == NULL) { - g_warning ("Unable to find stream for id: %u", id); - return; - } + g_debug ("Default input selected: %s", name); + stream = mate_mixer_control_get_stream (dialog->priv->control, name); - gvc_mixer_control_set_default_source (dialog->priv->mixer_control, stream); + if (stream != NULL) + mate_mixer_control_set_default_input_stream (dialog->priv->control, + stream); } + g_free (name); } static void @@ -1380,7 +1280,7 @@ on_output_radio_toggled (GtkCellRendererToggle *renderer, GtkTreeIter iter; GtkTreePath *path; gboolean toggled; - guint id; + gchar *name; model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview)); @@ -1389,23 +1289,20 @@ on_output_radio_toggled (GtkCellRendererToggle *renderer, gtk_tree_path_free (path); gtk_tree_model_get (model, &iter, - ID_COLUMN, &id, + NAME_COLUMN, &name, ACTIVE_COLUMN, &toggled, -1); - toggled ^= 1; - if (toggled) { - GvcMixerStream *stream; + if (toggled ^ 1) { + MateMixerStream *stream; - g_debug ("Default output selected: %u", id); - stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id); - if (stream == NULL) { - g_warning ("Unable to find stream for id: %u", id); - return; - } - - gvc_mixer_control_set_default_sink (dialog->priv->mixer_control, 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); } + g_free (name); } static void @@ -1415,31 +1312,28 @@ name_to_text (GtkTreeViewColumn *column, GtkTreeIter *iter, gpointer user_data) { - char *name, *mapping; + char *description, *mapping; - gtk_tree_model_get(model, iter, - NAME_COLUMN, &name, - SPEAKERS_COLUMN, &mapping, - -1); + gtk_tree_model_get (model, iter, + DESCRIPTION_COLUMN, &description, + SPEAKERS_COLUMN, &mapping, + -1); if (mapping == NULL) { - g_object_set (cell, "text", name, NULL); + g_object_set (cell, "text", description, NULL); } else { - char *str; + gchar *str = g_strdup_printf ("%s\n%s", description, mapping); - str = g_strdup_printf ("%s\n%s", - name, mapping); g_object_set (cell, "markup", str, NULL); g_free (str); } - g_free (name); + g_free (description); g_free (mapping); } static GtkWidget * -create_stream_treeview (GvcMixerDialog *dialog, - GCallback on_toggled) +create_stream_treeview (GvcMixerDialog *dialog, GCallback on_toggled) { GtkWidget *treeview; GtkListStore *store; @@ -1450,29 +1344,32 @@ create_stream_treeview (GvcMixerDialog *dialog, gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE); store = gtk_list_store_new (NUM_COLUMNS, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, - G_TYPE_UINT, 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); + 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 (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 (), + _("Name"), + gtk_cell_renderer_text_new (), name_to_text, NULL, NULL); #if 0 @@ -1487,54 +1384,41 @@ create_stream_treeview (GvcMixerDialog *dialog, } static void -on_profile_changed (GvcComboBox *widget, - const char *profile, - gpointer user_data) +on_profile_changed (GvcComboBox *widget, const gchar *profile, gpointer user_data) { - GvcMixerCard *card; + MateMixerDevice *device; - card = g_object_get_data (G_OBJECT (widget), "card"); - if (card == NULL) { + device = g_object_get_data (G_OBJECT (widget), "device"); + if (device == NULL) { g_warning ("Could not find card for combobox"); return; } - g_debug ("Profile changed to %s for card %s", profile, - gvc_mixer_card_get_name (card)); + g_debug ("Profile changed to %s for device %s", + profile, + mate_mixer_device_get_name (device)); - gvc_mixer_card_change_profile (card, profile); + mate_mixer_device_set_active_profile (device, profile); } static void -on_test_speakers_clicked (GvcComboBox *widget, - gpointer user_data) +on_test_speakers_clicked (GvcComboBox *widget, gpointer user_data) { GvcMixerDialog *dialog = GVC_MIXER_DIALOG (user_data); - GvcMixerCard *card; - GvcMixerCardProfile *profile; MateMixerDevice *device; GtkWidget *d, *speaker_test, *container; char *title; - device = mate_mixer_control_list_devices (dialog->priv->control)->data; - - card = g_object_get_data (G_OBJECT (widget), "card"); - if (card == NULL) { + device = g_object_get_data (G_OBJECT (widget), "device"); + if (device == NULL) { g_warning ("Could not find card for combobox"); return; } - profile = gvc_mixer_card_get_profile (card); - g_debug ("XXX Start speaker testing for profile '%s', card %s XXX", - profile->profile, gvc_mixer_card_get_name (card)); - - title = g_strdup_printf (_("Speaker Testing for %s"), gvc_mixer_card_get_name (card)); + title = g_strdup_printf (_("Speaker Testing for %s"), mate_mixer_device_get_name (device)); d = gtk_dialog_new_with_buttons (title, GTK_WINDOW (dialog), GTK_DIALOG_MODAL | -#if !GTK_CHECK_VERSION (2, 21, 8) - GTK_DIALOG_NO_SEPARATOR | -#endif GTK_DIALOG_DESTROY_WITH_PARENT, NULL); g_free (title); @@ -1556,9 +1440,9 @@ on_card_selection_changed (GtkTreeSelection *selection, GtkTreeModel *model; GtkTreeIter iter; const GList *profiles; - guint id; - GvcMixerCard *card; - GvcMixerCardProfile *current_profile; + gchar *name; + MateMixerDevice *device; + MateMixerDeviceProfile *profile; g_debug ("Card selection changed"); @@ -1568,42 +1452,78 @@ on_card_selection_changed (GtkTreeSelection *selection, dialog->priv->hw_profile_combo = NULL; } - if (gtk_tree_selection_get_selected (selection, - NULL, - &iter) == FALSE) { + if (gtk_tree_selection_get_selected (selection, NULL, &iter) == FALSE) return; - } model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview)); gtk_tree_model_get (model, &iter, - HW_ID_COLUMN, &id, + HW_NAME_COLUMN, &name, -1); - card = gvc_mixer_control_lookup_card_id (dialog->priv->mixer_control, id); - if (card == NULL) { - g_warning ("Unable to find card for id: %u", id); + + device = mate_mixer_control_get_device (dialog->priv->control, name); + if (device == NULL) { + g_warning ("Unable to find card for id: %s", name); + g_free (name); return; } + g_free (name); + + profile = mate_mixer_device_get_active_profile (device); + profiles = mate_mixer_device_list_profiles (device); - current_profile = gvc_mixer_card_get_profile (card); - profiles = gvc_mixer_card_get_profiles (card); 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); - 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), current_profile->profile); + + g_object_set (G_OBJECT (dialog->priv->hw_profile_combo), + "button-label", + _("Test Speakers"), + NULL); + + 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)); gtk_box_pack_start (GTK_BOX (dialog->priv->hw_settings_box), dialog->priv->hw_profile_combo, TRUE, TRUE, 6); + g_object_set (G_OBJECT (dialog->priv->hw_profile_combo), - "show-button", current_profile->n_sinks == 1, + "show-button", + mate_mixer_device_profile_get_num_output_streams (profile) >= 1, NULL); + gtk_widget_show (dialog->priv->hw_profile_combo); - g_object_set_data (G_OBJECT (dialog->priv->hw_profile_combo), "card", card); - 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); + 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), + "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); +} + +static void +on_notebook_switch_page (GtkNotebook *notebook, + GtkWidget *page, + guint page_num, + GvcMixerDialog *dialog) +{ + MateMixerStream *stream; + + stream = mate_mixer_control_get_default_input_stream (dialog->priv->control); + if (stream == NULL) + return; + + if (page_num == PAGE_INPUT) + mate_mixer_stream_monitor_start (stream); + else + mate_mixer_stream_monitor_stop (stream); } static void @@ -1613,32 +1533,30 @@ card_to_text (GtkTreeViewColumn *column, GtkTreeIter *iter, gpointer user_data) { - char *name, *status, *profile, *str; + gchar *description, *status, *profile, *str; gboolean sensitive; - gtk_tree_model_get(model, iter, - HW_NAME_COLUMN, &name, - HW_STATUS_COLUMN, &status, - HW_PROFILE_HUMAN_COLUMN, &profile, - HW_SENSITIVE_COLUMN, &sensitive, - -1); + gtk_tree_model_get (model, iter, + HW_DESCRIPTION_COLUMN, &description, + HW_STATUS_COLUMN, &status, + HW_PROFILE_HUMAN_COLUMN, &profile, + HW_SENSITIVE_COLUMN, &sensitive, + -1); - str = g_strdup_printf ("%s\n%s\n%s", - name, status, profile); + str = g_strdup_printf ("%s\n%s\n%s", description, status, profile); g_object_set (cell, "markup", str, "sensitive", sensitive, NULL); g_free (str); - g_free (name); + g_free (description); g_free (status); g_free (profile); } static GtkWidget * -create_cards_treeview (GvcMixerDialog *dialog, - GCallback on_changed) +create_cards_treeview (GvcMixerDialog *dialog, GCallback on_changed) { GtkWidget *treeview; GtkListStore *store; @@ -1650,32 +1568,39 @@ create_cards_treeview (GvcMixerDialog *dialog, 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); + g_signal_connect (G_OBJECT (selection), + "changed", + on_changed, + dialog); store = gtk_list_store_new (HW_NUM_COLUMNS, - G_TYPE_UINT, G_TYPE_ICON, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_BOOLEAN); + 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, "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, NULL, NULL); + _("Name"), + gtk_cell_renderer_text_new (), + card_to_text, + NULL, NULL); return treeview; } @@ -1701,9 +1626,8 @@ dialog_accel_cb (GtkAccelGroup *accelgroup, } } - if (num != -1) { + if (num != -1) gtk_notebook_set_current_page (GTK_NOTEBOOK (self->priv->notebook), num); - } } static GObject * @@ -1719,17 +1643,15 @@ gvc_mixer_dialog_constructor (GType type, GtkWidget *box; GtkWidget *sbox; GtkWidget *ebox; - GSList *streams; - GSList *cards; - GSList *l; - GvcMixerStream *stream; - GvcMixerCard *card; + GList *list; GtkTreeSelection *selection; GtkAccelGroup *accel_group; GClosure *closure; gint i; - object = G_OBJECT_CLASS (gvc_mixer_dialog_parent_class)->constructor (type, n_construct_properties, construct_params); + 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); @@ -1757,6 +1679,7 @@ gvc_mixer_dialog_constructor (GType type, gtk_box_pack_start (GTK_BOX (main_vbox), self->priv->notebook, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (self->priv->notebook), 5); /* Set up accels (borrowed from Empathy) */ @@ -1987,40 +1910,109 @@ gvc_mixer_dialog_constructor (GType type, self->priv->no_apps_label, TRUE, TRUE, 0); - g_signal_connect (self->priv->mixer_control, + gtk_widget_show_all (main_vbox); + + list = (GList *) mate_mixer_control_list_streams (self->priv->control); + while (list) { + add_stream (self, MATE_MIXER_STREAM (list->data)); + list = list->next; + } + + list = (GList *) mate_mixer_control_list_devices (self->priv->control); + while (list) { + add_device (self, MATE_MIXER_DEVICE (list->data)); + list = list->next; + } + + g_signal_connect (G_OBJECT (self->priv->notebook), + "switch-page", + G_CALLBACK (on_notebook_switch_page), + self); + + return object; +} + +static MateMixerControl * +gvc_mixer_dialog_get_control (GvcMixerDialog *dialog) +{ + return dialog->priv->control; +} + +static void +gvc_mixer_dialog_set_control (GvcMixerDialog *dialog, MateMixerControl *control) +{ + MateMixerState state; + + state = mate_mixer_control_get_state (control); + + if (G_UNLIKELY (state != MATE_MIXER_STATE_READY)) + g_warn_if_reached (); + + dialog->priv->control = g_object_ref (control); + + g_signal_connect (dialog->priv->control, "stream-added", G_CALLBACK (on_control_stream_added), - self); - g_signal_connect (self->priv->mixer_control, + dialog); + g_signal_connect (dialog->priv->control, "stream-removed", G_CALLBACK (on_control_stream_removed), - self); - g_signal_connect (self->priv->mixer_control, - "card-added", - G_CALLBACK (on_control_card_added), - self); - g_signal_connect (self->priv->mixer_control, - "card-removed", - G_CALLBACK (on_control_card_removed), - self); + dialog); + g_signal_connect (dialog->priv->control, + "device-added", + G_CALLBACK (on_control_device_added), + dialog); + g_signal_connect (dialog->priv->control, + "device-removed", + G_CALLBACK (on_control_device_removed), + dialog); - gtk_widget_show_all (main_vbox); + g_signal_connect (dialog->priv->control, + "notify::default-output", + G_CALLBACK (on_control_default_output_notify), + dialog); + g_signal_connect (dialog->priv->control, + "notify::default-input", + G_CALLBACK (on_control_default_input_notify), + dialog); - streams = gvc_mixer_control_get_streams (self->priv->mixer_control); - for (l = streams; l != NULL; l = l->next) { - stream = l->data; - add_stream (self, stream); - } - g_slist_free (streams); + g_object_notify (G_OBJECT (dialog), "control"); +} - cards = gvc_mixer_control_get_cards (self->priv->mixer_control); - for (l = cards; l != NULL; l = l->next) { - card = l->data; - add_card (self, card); +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_MIXER_CONTROL: + gvc_mixer_dialog_set_control (self, g_value_get_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; } - g_slist_free (cards); +} - return object; +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_MIXER_CONTROL: + g_value_set_object (value, gvc_mixer_dialog_get_control (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } static void @@ -2028,27 +2020,21 @@ gvc_mixer_dialog_dispose (GObject *object) { GvcMixerDialog *dialog = GVC_MIXER_DIALOG (object); - if (dialog->priv->mixer_control != NULL) { - g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control, + if (dialog->priv->control != NULL) { + g_signal_handlers_disconnect_by_func (dialog->priv->control, on_control_stream_added, dialog); - g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control, + g_signal_handlers_disconnect_by_func (dialog->priv->control, on_control_stream_removed, dialog); - g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control, - on_control_card_added, + g_signal_handlers_disconnect_by_func (dialog->priv->control, + on_control_device_added, dialog); - g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control, - on_control_card_removed, + g_signal_handlers_disconnect_by_func (dialog->priv->control, + on_control_device_removed, dialog); - g_object_unref (dialog->priv->mixer_control); - dialog->priv->mixer_control = NULL; - } - - if (dialog->priv->bars != NULL) { - g_hash_table_destroy (dialog->priv->bars); - dialog->priv->bars = NULL; + g_clear_object (&dialog->priv->control); } G_OBJECT_CLASS (gvc_mixer_dialog_parent_class)->dispose (object); @@ -2057,7 +2043,7 @@ gvc_mixer_dialog_dispose (GObject *object) static void gvc_mixer_dialog_class_init (GvcMixerDialogClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructor = gvc_mixer_dialog_constructor; object_class->dispose = gvc_mixer_dialog_dispose; @@ -2067,88 +2053,67 @@ gvc_mixer_dialog_class_init (GvcMixerDialogClass *klass) g_object_class_install_property (object_class, PROP_MIXER_CONTROL, - g_param_spec_object ("mixer-control", - "mixer control", - "mixer control", - GVC_TYPE_MIXER_CONTROL, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); + g_param_spec_object ("control", + "Control", + "MateMixer control", + MATE_MIXER_TYPE_CONTROL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); 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 (NULL, NULL); + + 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); - - dialog->priv->control = mate_mixer_control_new (); - - mate_mixer_control_open (dialog->priv->control); } static void gvc_mixer_dialog_finalize (GObject *object) { - GvcMixerDialog *mixer_dialog; + GvcMixerDialog *dialog; - g_return_if_fail (object != NULL); - g_return_if_fail (GVC_IS_MIXER_DIALOG (object)); + dialog = GVC_MIXER_DIALOG (object); - mixer_dialog = GVC_MIXER_DIALOG (object); + g_hash_table_destroy (dialog->priv->bars); - g_return_if_fail (mixer_dialog->priv != NULL); G_OBJECT_CLASS (gvc_mixer_dialog_parent_class)->finalize (object); } GvcMixerDialog * -gvc_mixer_dialog_new (GvcMixerControl *control) +gvc_mixer_dialog_new (MateMixerControl *control) { - GObject *dialog; - dialog = g_object_new (GVC_TYPE_MIXER_DIALOG, - "icon-name", "multimedia-volume-control", - "title", _("Sound Preferences"), -#if !GTK_CHECK_VERSION (3, 0, 0) - "has-separator", FALSE, -#endif - "mixer-control", control, - NULL); - return GVC_MIXER_DIALOG (dialog); + return g_object_new (GVC_TYPE_MIXER_DIALOG, + "icon-name", "multimedia-volume-control", + "title", _("Sound Preferences"), + "control", control, + NULL); } -enum { - PAGE_EVENTS, - PAGE_HARDWARE, - PAGE_INPUT, - PAGE_OUTPUT, - PAGE_APPLICATIONS -}; - gboolean -gvc_mixer_dialog_set_page (GvcMixerDialog *self, - const char *page) +gvc_mixer_dialog_set_page (GvcMixerDialog *self, const gchar *page) { - guint num; - - g_return_val_if_fail (self != NULL, FALSE); - - if (page == NULL) - num = 0; - else if (g_str_equal (page, "effects")) - num = PAGE_EVENTS; - 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; - else - num = 0; + 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_EVENTS; + 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); diff --git a/mate-volume-control/src/gvc-mixer-dialog.h b/mate-volume-control/src/gvc-mixer-dialog.h index 6db9ae5..3c67d9f 100644 --- a/mate-volume-control/src/gvc-mixer-dialog.h +++ b/mate-volume-control/src/gvc-mixer-dialog.h @@ -21,7 +21,10 @@ #ifndef __GVC_MIXER_DIALOG_H #define __GVC_MIXER_DIALOG_H +#include #include +#include + #include "gvc-mixer-control.h" G_BEGIN_DECLS @@ -35,23 +38,27 @@ G_BEGIN_DECLS #define GVC_IS_MIXER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_DIALOG)) #define GVC_MIXER_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_DIALOG, GvcMixerDialogClass)) -typedef struct GvcMixerDialogPrivate GvcMixerDialogPrivate; +typedef struct _GvcMixerDialog GvcMixerDialog; +typedef struct _GvcMixerDialogClass GvcMixerDialogClass; +typedef struct _GvcMixerDialogPrivate GvcMixerDialogPrivate; -typedef struct +struct _GvcMixerDialog { GtkDialog parent; GvcMixerDialogPrivate *priv; -} GvcMixerDialog; +}; -typedef struct +struct _GvcMixerDialogClass { GtkDialogClass parent_class; -} GvcMixerDialogClass; +}; + +GType gvc_mixer_dialog_get_type (void) G_GNUC_CONST; -GType gvc_mixer_dialog_get_type (void); +GvcMixerDialog * gvc_mixer_dialog_new (MateMixerControl *control); -GvcMixerDialog * gvc_mixer_dialog_new (GvcMixerControl *control); -gboolean gvc_mixer_dialog_set_page (GvcMixerDialog *dialog, const gchar* page); +gboolean gvc_mixer_dialog_set_page (GvcMixerDialog *dialog, + const gchar *page); G_END_DECLS diff --git a/mate-volume-control/src/gvc-stream-status-icon.c b/mate-volume-control/src/gvc-stream-status-icon.c index 86cd947..4e80e91 100644 --- a/mate-volume-control/src/gvc-stream-status-icon.c +++ b/mate-volume-control/src/gvc-stream-status-icon.c @@ -27,16 +27,12 @@ #include #include -#include "gvc-channel-bar.h" -#include "gvc-stream-status-icon.h" - -// XXX remove the #if and just use mate_gdk_spawn_command_line_on_screen after -// https://github.com/mate-desktop/mate-desktop/pull/120 -#if GTK_CHECK_VERSION (3, 0, 0) #define MATE_DESKTOP_USE_UNSTABLE_API + #include -#define gdk_spawn_command_line_on_screen mate_gdk_spawn_command_line_on_screen -#endif + +#include "gvc-channel-bar.h" +#include "gvc-stream-status-icon.h" #define GVC_STREAM_STATUS_ICON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_STREAM_STATUS_ICON, GvcStreamStatusIconPrivate)) @@ -230,13 +226,14 @@ static void on_menu_activate_open_volume_control (GtkMenuItem *item, GvcStreamStatusIcon *icon) { - GError *error; - - error = NULL; - gdk_spawn_command_line_on_screen (gtk_widget_get_screen (icon->priv->dock), - "mate-volume-control", - &error); + GError *error = NULL; + // XXX update to libmate-desktop 1.9.1 and uncomment this + /* + mate_spawn_command_line_on_screen (gtk_widget_get_screen (icon->priv->dock), + "mate-volume-control", + &error); + */ if (error != NULL) { GtkWidget *dialog; diff --git a/mate-volume-control/src/mvc-helpers.c b/mate-volume-control/src/mvc-helpers.c new file mode 100644 index 0000000..2861bbd --- /dev/null +++ b/mate-volume-control/src/mvc-helpers.c @@ -0,0 +1,155 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2014 Michal Ratajsky + * + * 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 +#include + +#include + +#ifdef HAVE_PULSEAUDIO +#include +#endif + +#include "mvc-helpers.h" + +#ifdef HAVE_PULSEAUDIO +static pa_position_t +position_to_pulse (MateMixerChannelPosition position) +{ + switch (position) { + case MATE_MIXER_CHANNEL_MONO: + return PA_CHANNEL_POSITION_MONO; + case MATE_MIXER_CHANNEL_FRONT_LEFT: + return PA_CHANNEL_POSITION_FRONT_LEFT; + case MATE_MIXER_CHANNEL_FRONT_RIGHT: + return PA_CHANNEL_POSITION_FRONT_RIGHT; + case MATE_MIXER_CHANNEL_FRONT_CENTER: + return PA_CHANNEL_POSITION_FRONT_CENTER; + case MATE_MIXER_CHANNEL_LFE: + return PA_CHANNEL_POSITION_LFE; + case MATE_MIXER_CHANNEL_BACK_LEFT: + return PA_CHANNEL_POSITION_REAR_LEFT; + case MATE_MIXER_CHANNEL_BACK_RIGHT: + return PA_CHANNEL_POSITION_REAR_RIGHT; + case MATE_MIXER_CHANNEL_BACK_CENTER: + return PA_CHANNEL_POSITION_REAR_CENTER; + case MATE_MIXER_CHANNEL_FRONT_LEFT_CENTER: + return PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER; + case MATE_MIXER_CHANNEL_FRONT_RIGHT_CENTER: + return PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER; + case MATE_MIXER_CHANNEL_SIDE_LEFT: + return PA_CHANNEL_POSITION_SIDE_LEFT; + case MATE_MIXER_CHANNEL_SIDE_RIGHT: + return PA_CHANNEL_POSITION_SIDE_RIGHT; + case MATE_MIXER_CHANNEL_TOP_FRONT_LEFT: + return PA_CHANNEL_POSITION_TOP_FRONT_LEFT; + case MATE_MIXER_CHANNEL_TOP_FRONT_RIGHT: + return PA_CHANNEL_POSITION_TOP_FRONT_RIGHT; + case MATE_MIXER_CHANNEL_TOP_FRONT_CENTER: + return PA_CHANNEL_POSITION_TOP_FRONT_CENTER; + case MATE_MIXER_CHANNEL_TOP_CENTER: + return PA_CHANNEL_POSITION_TOP_CENTER; + case MATE_MIXER_CHANNEL_TOP_BACK_LEFT: + return PA_CHANNEL_POSITION_TOP_REAR_LEFT; + case MATE_MIXER_CHANNEL_TOP_BACK_RIGHT: + return PA_CHANNEL_POSITION_TOP_REAR_RIGHT; + case MATE_MIXER_CHANNEL_TOP_BACK_CENTER: + return PA_CHANNEL_POSITION_TOP_REAR_CENTER; + default: + return PA_CHANNEL_POSITION_INVALID; + } +} +#endif + +const gchar * +mvc_channel_position_to_string (MateMixerChannelPosition position) +{ +#ifdef HAVE_PULSEAUDIO + return pa_channel_position_to_string (position_to_pulse (position)); +#endif + return NULL; +} + +const gchar * +mvc_channel_position_to_pretty_string (MateMixerChannelPosition position) +{ +#ifdef HAVE_PULSEAUDIO + return pa_channel_position_to_pretty_string (position_to_pulse (position)); +#endif + return NULL; +} + +const gchar * +mvc_channel_map_to_pretty_string (MateMixerStream *stream) +{ + g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL); + + /* Modeled after PulseAudio 5.0, probably could be extended with other combinations */ + switch (mate_mixer_stream_get_num_channels (stream)) { + case 1: + if (mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_MONO)) + return _("Mono"); + break; + case 2: + if (mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_FRONT_LEFT) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_FRONT_RIGHT)) + return _("Stereo"); + break; + case 4: + if (mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_FRONT_LEFT) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_FRONT_RIGHT) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_BACK_LEFT) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_BACK_RIGHT)) + return _("Surround 4.0"); + break; + case 5: + if (mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_FRONT_LEFT) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_FRONT_RIGHT) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_BACK_LEFT) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_BACK_RIGHT)) + if (mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_LFE)) + return _("Surround 4.1"); + if (mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_FRONT_CENTER)) + return _("Surround 5.0"); + break; + case 6: + if (mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_FRONT_LEFT) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_FRONT_RIGHT) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_FRONT_CENTER) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_BACK_LEFT) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_BACK_RIGHT) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_LFE)) + return _("Surround 5.1"); + break; + case 8: + if (mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_FRONT_LEFT) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_FRONT_RIGHT) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_FRONT_CENTER) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_BACK_LEFT) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_BACK_RIGHT) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_SIDE_LEFT) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_SIDE_RIGHT) && + mate_mixer_stream_has_position (stream, MATE_MIXER_CHANNEL_LFE)) + return _("Surround 7.1"); + break; + } + + return NULL; +} diff --git a/mate-volume-control/src/mvc-helpers.h b/mate-volume-control/src/mvc-helpers.h new file mode 100644 index 0000000..248c843 --- /dev/null +++ b/mate-volume-control/src/mvc-helpers.h @@ -0,0 +1,36 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2014 Michal Ratajsky + * + * 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. + * + */ + +#ifndef __MVC_HELPERS_H +#define __MVC_HELPERS_H + +#include + +#include + +G_BEGIN_DECLS + +const gchar *mvc_channel_position_to_string (MateMixerChannelPosition position); +const gchar *mvc_channel_position_to_pretty_string (MateMixerChannelPosition position); +const gchar *mvc_channel_map_to_pretty_string (MateMixerStream *stream); + +G_END_DECLS + +#endif /* __MVC_HELPERS_H */ -- cgit v1.2.1