From de3e2fc0c8a77708b4921c4d3b3c83efee01cc28 Mon Sep 17 00:00:00 2001 From: Michal Ratajsky Date: Fri, 20 Jun 2014 16:14:59 +0200 Subject: Port applet to libmatemixer --- configure.ac | 1 + mate-volume-control/src/applet-main.c | 63 ++-- mate-volume-control/src/dialog-main.c | 48 ++-- mate-volume-control/src/gvc-applet.c | 350 +++++++++++------------ mate-volume-control/src/gvc-applet.h | 27 +- mate-volume-control/src/gvc-mixer-dialog.h | 2 + mate-volume-control/src/gvc-stream-status-icon.c | 190 ++++++------ mate-volume-control/src/gvc-stream-status-icon.h | 23 +- 8 files changed, 323 insertions(+), 381 deletions(-) diff --git a/configure.ac b/configure.ac index dc56d33..588b06d 100644 --- a/configure.ac +++ b/configure.ac @@ -127,6 +127,7 @@ if test "x$enable_pulseaudio" != "xno"; then unique-$UNIQUE_API_VERSION libxml-2.0 mate-desktop-2.0 >= $MATE_DESKTOP_REQUIRED_VERSION + libmatemixer ) AC_SUBST(VOLUME_CONTROL_CFLAGS) diff --git a/mate-volume-control/src/applet-main.c b/mate-volume-control/src/applet-main.c index f6bc9f5..767d2e1 100644 --- a/mate-volume-control/src/applet-main.c +++ b/mate-volume-control/src/applet-main.c @@ -20,83 +20,68 @@ #include "config.h" -#include -#include -#include -#include -#include - #include #include #include + +#include #include +#include #include "gvc-applet.h" -#include "gvc-log.h" - -#define GVCA_DBUS_NAME "org.mate.VolumeControlApplet" static gboolean show_version = FALSE; -static gboolean debug = FALSE; int main (int argc, char **argv) { - GError *error; - GvcApplet *applet; - UniqueApp *app = NULL; - static GOptionEntry entries[] = { - { "debug", 0, 0, G_OPTION_ARG_NONE, &debug, N_("Enable debugging code"), NULL }, - { "version", 0, 0, G_OPTION_ARG_NONE, &show_version, N_("Version of this application"), NULL }, - { NULL, 0, 0, 0, NULL, NULL, NULL } + GError *error = NULL; + GvcApplet *applet; + UniqueApp *app = NULL; + GOptionEntry entries[] = { + { "version", 'v', 0, G_OPTION_ARG_NONE, &show_version, N_("Version of this application"), NULL }, + { NULL } }; bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); - gvc_log_init (); - - error = NULL; gtk_init_with_args (&argc, &argv, (char *) _(" — MATE Volume Control Applet"), entries, GETTEXT_PACKAGE, &error); - if (error != NULL) { g_warning ("%s", error->message); - exit (1); + return 1; } - if (show_version) { - g_print ("%s %s\n", argv [0], VERSION); - exit (1); + g_print ("%s %s\n", argv[0], VERSION); + return 0; } - gvc_log_set_debug (debug); + app = unique_app_new (GVC_APPLET_DBUS_NAME, NULL); - if (debug == FALSE) { - app = unique_app_new (GVCA_DBUS_NAME, NULL); - if (unique_app_is_running (app)) { - g_warning ("Applet is already running, exiting"); - return 0; - } + if (unique_app_is_running (app)) { + g_warning ("Applet is already running, exiting"); + return 0; + } + if (!mate_mixer_init ()) { + g_warning ("libmatemixer initialization failed, exiting"); + return 1; } gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), ICON_DATA_DIR); applet = gvc_applet_new (); - gvc_applet_start (applet); + gvc_applet_start (applet); gtk_main (); - if (applet != NULL) { - g_object_unref (applet); - } - if (app != NULL) { - g_object_unref (app); - } + 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 985e58d..929ed0c 100644 --- a/mate-volume-control/src/dialog-main.c +++ b/mate-volume-control/src/dialog-main.c @@ -20,25 +20,19 @@ #include "config.h" -#include -#include -#include -#include -#include - #include #include #include + +#include #include +#include #include "gvc-mixer-dialog.h" -#include "gvc-log.h" -#define GVCA_DBUS_NAME "org.mate.VolumeControl" #define DIALOG_POPUP_TIMEOUT 3 static gboolean show_version = FALSE; -static gboolean debug = FALSE; static gchar* page = NULL; static guint popup_id = 0; @@ -147,43 +141,37 @@ on_control_connecting (GvcMixerControl *control, int main (int argc, char **argv) { - GError *error; - GvcMixerControl *control; - UniqueApp *app; - static GOptionEntry entries[] = { - { "page", 'p', 0, G_OPTION_ARG_STRING, &page, N_("Startup page"), "effects|hardware|input|output|applications" }, - { "debug", 0, 0, G_OPTION_ARG_NONE, &debug, N_("Enable debugging code"), NULL }, - { "version", 0, 0, G_OPTION_ARG_NONE, &show_version, N_("Version of this application"), NULL }, - { NULL, 0, 0, 0, NULL, NULL, NULL } + GError *error = NULL; + GvcMixerControl *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 } }; bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); - gvc_log_init (); - - error = NULL; gtk_init_with_args (&argc, &argv, (char *) _(" — MATE Volume Control"), entries, GETTEXT_PACKAGE, &error); if (error != NULL) { g_warning ("%s", error->message); - exit (1); + return 1; } - if (show_version) { - g_print ("%s %s\n", argv [0], VERSION); - exit (1); + g_print ("%s %s\n", argv[0], VERSION); + return 0; } - gvc_log_set_debug (debug); + app = unique_app_new (GVC_DIALOG_DBUS_NAME, NULL); - app = unique_app_new (GVCA_DBUS_NAME, NULL); if (unique_app_is_running (app)) { unique_app_send_message (app, UNIQUE_ACTIVATE, NULL); - exit (0); + return 0; } gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), @@ -199,13 +187,11 @@ main (int argc, char **argv) "ready", G_CALLBACK (on_control_ready), app); - gvc_mixer_control_open (control); + gvc_mixer_control_open (control); gtk_main (); - if (control != NULL) { - g_object_unref (control); - } + g_object_unref (control); return 0; } diff --git a/mate-volume-control/src/gvc-applet.c b/mate-volume-control/src/gvc-applet.c index b2807f1..4522a8f 100644 --- a/mate-volume-control/src/gvc-applet.c +++ b/mate-volume-control/src/gvc-applet.c @@ -18,28 +18,25 @@ * */ -#include "config.h" +// XXX there are some bugs unrelated to the port, let's see if I can fix them: +// - clicking in the slider makes it disappear +// - drag all the way down to mute, then start dragging up and the change won't +// be reflected until i stop dragging +// - disable the slider if the volume is not changable -#include -#include -#include -#include -#include -#include +#include "config.h" #include #include #include +#include #include "gvc-applet.h" -#include "gvc-mixer-control.h" #include "gvc-stream-status-icon.h" #define GVC_APPLET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_APPLET, GvcAppletPrivate)) -#define SCALE_SIZE 128 - -static const char *output_icon_names[] = { +static const gchar *icon_names_output[] = { "audio-volume-muted", "audio-volume-low", "audio-volume-medium", @@ -47,7 +44,7 @@ static const char *output_icon_names[] = { NULL }; -static const char *input_icon_names[] = { +static const gchar *icon_names_input[] = { "audio-input-microphone-muted", "audio-input-microphone-low", "audio-input-microphone-medium", @@ -55,211 +52,182 @@ static const char *input_icon_names[] = { NULL }; -struct GvcAppletPrivate +struct _GvcAppletPrivate { - GvcStreamStatusIcon *input_status_icon; - GvcStreamStatusIcon *output_status_icon; - GvcMixerControl *control; + GvcStreamStatusIcon *icon_input; + GvcStreamStatusIcon *icon_output; + gboolean running; + MateMixerControl *control; }; -static void gvc_applet_class_init (GvcAppletClass *klass); -static void gvc_applet_init (GvcApplet *applet); -static void gvc_applet_finalize (GObject *object); +static void gvc_applet_class_init (GvcAppletClass *klass); +static void gvc_applet_init (GvcApplet *applet); G_DEFINE_TYPE (GvcApplet, gvc_applet, G_TYPE_OBJECT) static void -maybe_show_status_icons (GvcApplet *applet) +update_icon_input (GvcApplet *applet) { - gboolean show; - GvcMixerStream *stream; - GSList *source_outputs, *l; - - show = TRUE; - stream = gvc_mixer_control_get_default_sink (applet->priv->control); - if (stream == NULL) { - show = FALSE; - } - gtk_status_icon_set_visible (GTK_STATUS_ICON (applet->priv->output_status_icon), show); - - - show = FALSE; - stream = gvc_mixer_control_get_default_source (applet->priv->control); - source_outputs = gvc_mixer_control_get_source_outputs (applet->priv->control); - if (stream != NULL && source_outputs != NULL) { - /* Check that we're not trying to add the peak detector - * as an application doing recording */ - for (l = source_outputs ; l ; l = l->next) { - GvcMixerStream *s = l->data; - const char *id; - - id = gvc_mixer_stream_get_application_id (s); - if (id == NULL) { - show = TRUE; - break; - } + MateMixerStream *stream; + gboolean show = FALSE; - if (!g_str_equal (id, "org.mate.VolumeControl") && - !g_str_equal (id, "org.PulseAudio.pavucontrol")) { - show = TRUE; - break; + /* Enable the input icon in case there is an input stream present and there + * is a non-mixer application using the input */ + stream = mate_mixer_control_get_default_input_stream (applet->priv->control); + if (stream != NULL) { + const gchar *app; + const GList *inputs = + mate_mixer_control_list_streams (applet->priv->control); + + while (inputs) { + MateMixerStream *input = MATE_MIXER_STREAM (inputs->data); + MateMixerStreamFlags flags = mate_mixer_stream_get_flags (input); + + if (flags & MATE_MIXER_STREAM_INPUT && + flags & MATE_MIXER_STREAM_APPLICATION) { + MateMixerClientStream *client = + MATE_MIXER_CLIENT_STREAM (input); + + app = mate_mixer_client_stream_get_app_id (client); + if (app == NULL) { + /* A recording application which has no + * identifier set */ + show = TRUE; + break; + } + + if (!g_str_equal (app, "org.mate.VolumeControl") && + !g_str_equal (app, "org.gnome.VolumeControl") && + !g_str_equal (app, "org.PulseAudio.pavucontrol")) { + show = TRUE; + break; + } } + inputs = inputs->next; } } - gtk_status_icon_set_visible (GTK_STATUS_ICON (applet->priv->input_status_icon), show); - g_slist_free (source_outputs); -} + gvc_stream_status_icon_set_mixer_stream (applet->priv->icon_input, stream); -void -gvc_applet_start (GvcApplet *applet) -{ - g_return_if_fail (GVC_IS_APPLET (applet)); - - maybe_show_status_icons (applet); + gtk_status_icon_set_visible (GTK_STATUS_ICON (applet->priv->icon_input), show); } static void -gvc_applet_dispose (GObject *object) +update_icon_output (GvcApplet *applet) { - GvcApplet *applet = GVC_APPLET (object); + MateMixerStream *stream; - if (applet->priv->control != NULL) { - g_object_unref (applet->priv->control); - applet->priv->control = NULL; - } + stream = mate_mixer_control_get_default_output_stream (applet->priv->control); - G_OBJECT_CLASS (gvc_applet_parent_class)->dispose (object); + gvc_stream_status_icon_set_mixer_stream (applet->priv->icon_output, stream); + + /* Enable the output icon in case there is an output stream present */ + gtk_status_icon_set_visible (GTK_STATUS_ICON (applet->priv->icon_output), + (stream != NULL) ? TRUE : FALSE); } -static void -update_default_source (GvcApplet *applet) +void +gvc_applet_start (GvcApplet *applet) { - GvcMixerStream *stream; + g_return_if_fail (GVC_IS_APPLET (applet)); - stream = gvc_mixer_control_get_default_source (applet->priv->control); - if (stream != NULL) { - gvc_stream_status_icon_set_mixer_stream (applet->priv->input_status_icon, - stream); - maybe_show_status_icons(applet); - } else { - g_debug ("Unable to get default source, or no source available"); - } -} + if (G_UNLIKELY (applet->priv->running)) + return; -static void -update_default_sink (GvcApplet *applet) -{ - GvcMixerStream *stream; + if (mate_mixer_control_open (applet->priv->control) == FALSE) { + /* Normally this should never happen, in the worst case we + * should end up with the Null module */ + g_warning ("Failed to connect to a sound system"); - stream = gvc_mixer_control_get_default_sink (applet->priv->control); - if (stream != NULL) { - gvc_stream_status_icon_set_mixer_stream (applet->priv->output_status_icon, - stream); - maybe_show_status_icons(applet); - } else { - g_warning ("Unable to get default sink"); + gtk_status_icon_set_visible (GTK_STATUS_ICON (applet->priv->icon_output), + FALSE); + gtk_status_icon_set_visible (GTK_STATUS_ICON (applet->priv->icon_input), + FALSE); } -} -static void -on_control_ready (GvcMixerControl *control, - GvcApplet *applet) -{ - update_default_sink (applet); - update_default_source (applet); + applet->priv->running = TRUE; } static void -on_control_connecting (GvcMixerControl *control, - GvcApplet *applet) +on_control_state_notify (MateMixerControl *control, + GParamSpec *pspec, + GvcApplet *applet) { - g_debug ("Connecting.."); + MateMixerState state = mate_mixer_control_get_state (control); + + if (state == MATE_MIXER_STATE_FAILED) + g_warning ("Failed to connect to a sound system"); + + /* Each status change may affect the visibility of the icons */ + update_icon_output (applet); + update_icon_input (applet); } static void -on_control_default_sink_changed (GvcMixerControl *control, - guint id, - GvcApplet *applet) +on_control_default_input_notify (MateMixerControl *control, + GParamSpec *pspec, + GvcApplet *applet) { - update_default_sink (applet); + update_icon_input (applet); } static void -on_control_default_source_changed (GvcMixerControl *control, - guint id, - GvcApplet *applet) +on_control_default_output_notify (MateMixerControl *control, + GParamSpec *pspec, + GvcApplet *applet) { - update_default_source (applet); + update_icon_output (applet); } static void -on_control_stream_removed (GvcMixerControl *control, - guint id, - GvcApplet *applet) +on_control_stream_added (MateMixerControl *control, + const gchar *name, + GvcApplet *applet) { - maybe_show_status_icons (applet); + MateMixerStream *stream; + MateMixerStreamFlags flags; + + stream = mate_mixer_control_get_stream (control, name); + if (G_UNLIKELY (stream == NULL)) + return; + + flags = mate_mixer_stream_get_flags (stream); + + /* Newly added input application stream may cause the input status + * icon to change visibility */ + if (flags & MATE_MIXER_STREAM_INPUT && + flags & MATE_MIXER_STREAM_APPLICATION) + update_icon_input (applet); } static void -on_control_stream_added (GvcMixerControl *control, - guint id, - GvcApplet *applet) +on_control_stream_removed (MateMixerControl *control, + const gchar *name, + GvcApplet *applet) { - maybe_show_status_icons (applet); + /* The removed stream could be an application input, which may cause + * the input status icon to disappear */ + update_icon_input (applet); } -static GObject * -gvc_applet_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_params) +static void +gvc_applet_dispose (GObject *object) { - GObject *object; - GvcApplet *self; - - object = G_OBJECT_CLASS (gvc_applet_parent_class)->constructor (type, n_construct_properties, construct_params); - - self = GVC_APPLET (object); - - self->priv->control = gvc_mixer_control_new ("MATE Volume Control Applet"); - g_signal_connect (self->priv->control, - "ready", - G_CALLBACK (on_control_ready), - self); - g_signal_connect (self->priv->control, - "connecting", - G_CALLBACK (on_control_connecting), - self); - g_signal_connect (self->priv->control, - "default-sink-changed", - G_CALLBACK (on_control_default_sink_changed), - self); - g_signal_connect (self->priv->control, - "default-source-changed", - G_CALLBACK (on_control_default_source_changed), - self); - g_signal_connect (self->priv->control, - "stream-added", - G_CALLBACK (on_control_stream_added), - self); - g_signal_connect (self->priv->control, - "stream-removed", - G_CALLBACK (on_control_stream_removed), - self); + GvcApplet *applet = GVC_APPLET (object); - gvc_mixer_control_open (self->priv->control); + g_clear_object (&applet->priv->control); + g_clear_object (&applet->priv->icon_input); + g_clear_object (&applet->priv->icon_output); - return object; + G_OBJECT_CLASS (gvc_applet_parent_class)->dispose (object); } static void gvc_applet_class_init (GvcAppletClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->finalize = gvc_applet_finalize; object_class->dispose = gvc_applet_dispose; - object_class->constructor = gvc_applet_constructor; g_type_class_add_private (klass, sizeof (GvcAppletPrivate)); } @@ -269,42 +237,50 @@ gvc_applet_init (GvcApplet *applet) { applet->priv = GVC_APPLET_GET_PRIVATE (applet); - applet->priv->output_status_icon = gvc_stream_status_icon_new (NULL, - output_icon_names); - gvc_stream_status_icon_set_display_name (applet->priv->output_status_icon, - _("Output")); - gtk_status_icon_set_title (GTK_STATUS_ICON (applet->priv->output_status_icon), - _("Sound Output Volume")); - applet->priv->input_status_icon = gvc_stream_status_icon_new (NULL, - input_icon_names); - gvc_stream_status_icon_set_display_name (applet->priv->input_status_icon, - _("Input")); - gtk_status_icon_set_title (GTK_STATUS_ICON (applet->priv->input_status_icon), - _("Microphone Volume")); -} - -static void -gvc_applet_finalize (GObject *object) -{ - GvcApplet *applet; + applet->priv->icon_input = gvc_stream_status_icon_new (NULL, icon_names_input); + applet->priv->icon_output = gvc_stream_status_icon_new (NULL, icon_names_output); - g_return_if_fail (object != NULL); - g_return_if_fail (GVC_IS_APPLET (object)); - - applet = GVC_APPLET (object); - - g_return_if_fail (applet->priv != NULL); + gvc_stream_status_icon_set_display_name (applet->priv->icon_input, _("Input")); + gvc_stream_status_icon_set_display_name (applet->priv->icon_output, _("Output")); + gtk_status_icon_set_title (GTK_STATUS_ICON (applet->priv->icon_input), + _("Microphone Volume")); + gtk_status_icon_set_title (GTK_STATUS_ICON (applet->priv->icon_output), + _("Sound Output Volume")); - G_OBJECT_CLASS (gvc_applet_parent_class)->finalize (object); + applet->priv->control = mate_mixer_control_new (); + + mate_mixer_control_set_app_name (applet->priv->control, + _("MATE Volume Control Applet")); + + mate_mixer_control_set_app_id (applet->priv->control, GVC_APPLET_DBUS_NAME); + mate_mixer_control_set_app_version (applet->priv->control, VERSION); + mate_mixer_control_set_app_icon (applet->priv->control, "multimedia-volume-control"); + + g_signal_connect (applet->priv->control, + "notify::state", + G_CALLBACK (on_control_state_notify), + applet); + g_signal_connect (applet->priv->control, + "notify::default-input", + G_CALLBACK (on_control_default_input_notify), + applet); + g_signal_connect (applet->priv->control, + "notify::default-output", + G_CALLBACK (on_control_default_output_notify), + applet); + g_signal_connect (applet->priv->control, + "stream-added", + G_CALLBACK (on_control_stream_added), + applet); + g_signal_connect (applet->priv->control, + "stream-removed", + G_CALLBACK (on_control_stream_removed), + applet); } GvcApplet * gvc_applet_new (void) { - GObject *applet; - - applet = g_object_new (GVC_TYPE_APPLET, NULL); - - return GVC_APPLET (applet); + return g_object_new (GVC_TYPE_APPLET, NULL); } diff --git a/mate-volume-control/src/gvc-applet.h b/mate-volume-control/src/gvc-applet.h index 1cce717..50b3a80 100644 --- a/mate-volume-control/src/gvc-applet.h +++ b/mate-volume-control/src/gvc-applet.h @@ -21,34 +21,39 @@ #ifndef __GVC_APPLET_H #define __GVC_APPLET_H +#include #include G_BEGIN_DECLS +#define GVC_APPLET_DBUS_NAME "org.mate.VolumeControlApplet" + #define GVC_TYPE_APPLET (gvc_applet_get_type ()) #define GVC_APPLET(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_APPLET, GvcApplet)) -#define GVC_APPLET_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_APPLET, GvcAppletClass)) +#define GVC_APPLET_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GVC_TYPE_APPLET, GvcAppletClass)) #define GVC_IS_APPLET(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_APPLET)) #define GVC_IS_APPLET_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_APPLET)) #define GVC_APPLET_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_APPLET, GvcAppletClass)) -typedef struct GvcAppletPrivate GvcAppletPrivate; +typedef struct _GvcApplet GvcApplet; +typedef struct _GvcAppletClass GvcAppletClass; +typedef struct _GvcAppletPrivate GvcAppletPrivate; -typedef struct +struct _GvcApplet { - GObject parent; - GvcAppletPrivate *priv; -} GvcApplet; + GObject parent; + GvcAppletPrivate *priv; +}; -typedef struct +struct _GvcAppletClass { - GObjectClass parent_class; -} GvcAppletClass; + GObjectClass parent_class; +}; -GType gvc_applet_get_type (void); +GType gvc_applet_get_type (void) G_GNUC_CONST; GvcApplet * gvc_applet_new (void); -void gvc_applet_start (GvcApplet *applet); +void gvc_applet_start (GvcApplet *applet); G_END_DECLS diff --git a/mate-volume-control/src/gvc-mixer-dialog.h b/mate-volume-control/src/gvc-mixer-dialog.h index ca9c0a1..6db9ae5 100644 --- a/mate-volume-control/src/gvc-mixer-dialog.h +++ b/mate-volume-control/src/gvc-mixer-dialog.h @@ -26,6 +26,8 @@ G_BEGIN_DECLS +#define GVC_DIALOG_DBUS_NAME "org.mate.VolumeControl" + #define GVC_TYPE_MIXER_DIALOG (gvc_mixer_dialog_get_type ()) #define GVC_MIXER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_DIALOG, GvcMixerDialog)) #define GVC_MIXER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_DIALOG, GvcMixerDialogClass)) diff --git a/mate-volume-control/src/gvc-stream-status-icon.c b/mate-volume-control/src/gvc-stream-status-icon.c index dcf483d..51207ba 100644 --- a/mate-volume-control/src/gvc-stream-status-icon.c +++ b/mate-volume-control/src/gvc-stream-status-icon.c @@ -20,41 +20,41 @@ #include "config.h" -#include -#include -#include #include - #include #include #include -#if GTK_CHECK_VERSION (2, 21, 8) #include -#else -#include -#endif +#include -#include "gvc-mixer-stream.h" #include "gvc-channel-bar.h" #include "gvc-stream-status-icon.h" +// XXX the gdk_spawn_command_line_on_screen causes compiler warnings, remove the GTK3 +// check and instead use GdkAppLaunchContext and GAppInfo which should work with +// both GDKs + #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 +// XXX this file uses PA_DECIBEL_MININFTY, figure out how to handle it through the +// library and change it +#include + #define GVC_STREAM_STATUS_ICON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_STREAM_STATUS_ICON, GvcStreamStatusIconPrivate)) -struct GvcStreamStatusIconPrivate +struct _GvcStreamStatusIconPrivate { - char **icon_names; - GvcMixerStream *mixer_stream; - GtkWidget *dock; - GtkWidget *bar; - guint current_icon; - char *display_name; - gboolean thaw; + char **icon_names; + GtkWidget *dock; + GtkWidget *bar; + guint current_icon; + char *display_name; + gboolean thaw; + MateMixerStream *mixer_stream; }; enum @@ -65,35 +65,25 @@ enum PROP_ICON_NAMES, }; -static void gvc_stream_status_icon_class_init (GvcStreamStatusIconClass *klass); -static void gvc_stream_status_icon_init (GvcStreamStatusIcon *stream_status_icon); -static void gvc_stream_status_icon_finalize (GObject *object); +static void gvc_stream_status_icon_class_init (GvcStreamStatusIconClass *klass); +static void gvc_stream_status_icon_init (GvcStreamStatusIcon *stream_status_icon); +static void gvc_stream_status_icon_finalize (GObject *object); G_DEFINE_TYPE (GvcStreamStatusIcon, gvc_stream_status_icon, GTK_TYPE_STATUS_ICON) static void -on_adjustment_value_changed (GtkAdjustment *adjustment, - GvcStreamStatusIcon *icon) +on_adjustment_value_changed (GtkAdjustment *adjustment, + GvcStreamStatusIcon *icon) { - gdouble volume; - - if (icon->priv->thaw) - return; - - volume = gtk_adjustment_get_value (adjustment); - - /* Only push the volume if it's actually changed */ - if (gvc_mixer_stream_set_volume(icon->priv->mixer_stream, - (pa_volume_t) round (volume)) != FALSE) { - gvc_mixer_stream_push_volume(icon->priv->mixer_stream); - } + if (icon->priv->thaw == FALSE) + mate_mixer_stream_set_volume (icon->priv->mixer_stream, + round (gtk_adjustment_get_value (adjustment))); } static void update_dock (GvcStreamStatusIcon *icon) { GtkAdjustment *adj; - gboolean is_muted; g_return_if_fail (icon); @@ -101,9 +91,9 @@ update_dock (GvcStreamStatusIcon *icon) icon->priv->thaw = TRUE; gtk_adjustment_set_value (adj, - gvc_mixer_stream_get_volume (icon->priv->mixer_stream)); - is_muted = gvc_mixer_stream_get_is_muted (icon->priv->mixer_stream); - gvc_channel_bar_set_is_muted (GVC_CHANNEL_BAR (icon->priv->bar), is_muted); + mate_mixer_stream_get_volume (icon->priv->mixer_stream)); + gvc_channel_bar_set_is_muted (GVC_CHANNEL_BAR (icon->priv->bar), + mate_mixer_stream_get_mute (icon->priv->mixer_stream)); icon->priv->thaw = FALSE; } @@ -142,7 +132,7 @@ popup_dock (GvcStreamStatusIcon *icon, monitor_num = gdk_screen_get_monitor_at_point (screen, area.x, area.y); gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); - gtk_container_foreach (GTK_CONTAINER (icon->priv->dock), + gtk_container_foreach (GTK_CONTAINER (icon->priv->dock), (GtkCallback) gtk_widget_show_all, NULL); #if GTK_CHECK_VERSION (3, 0, 0) gtk_widget_get_preferred_size (icon->priv->dock, &dock_req, NULL); @@ -225,9 +215,9 @@ on_status_icon_button_press (GtkStatusIcon *status_icon, /* middle click acts as mute/unmute */ if (event->button == 2) { gboolean is_muted; - is_muted = gvc_mixer_stream_get_is_muted (icon->priv->mixer_stream); - gvc_mixer_stream_set_is_muted (icon->priv->mixer_stream, !is_muted); - gvc_mixer_stream_change_is_muted (icon->priv->mixer_stream, !is_muted); + is_muted = mate_mixer_stream_get_mute (icon->priv->mixer_stream); + + mate_mixer_stream_set_mute (icon->priv->mixer_stream, !is_muted); return TRUE; } return FALSE; @@ -285,7 +275,7 @@ on_status_icon_popup_menu (GtkStatusIcon *status_icon, item = gtk_check_menu_item_new_with_mnemonic (_("_Mute")); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), - gvc_mixer_stream_get_is_muted (icon->priv->mixer_stream)); + mate_mixer_stream_get_mute (icon->priv->mixer_stream)); g_signal_connect (item, "toggled", G_CALLBACK (on_menu_mute_toggled), @@ -435,27 +425,36 @@ on_dock_scroll_event (GtkWidget *widget, static void update_icon (GvcStreamStatusIcon *icon) { - guint volume; - gboolean is_muted; - guint n; - char *markup; - gboolean can_decibel; - gdouble db; + gint64 volume; + gdouble volume_db = 0; + gint64 normal_volume; + gboolean is_muted; + guint n; + char *markup; + gboolean can_decibel = FALSE; + MateMixerStreamFlags flags; if (icon->priv->mixer_stream == NULL) { return; } - volume = gvc_mixer_stream_get_volume (icon->priv->mixer_stream); - is_muted = gvc_mixer_stream_get_is_muted (icon->priv->mixer_stream); - db = gvc_mixer_stream_get_decibel (icon->priv->mixer_stream); - can_decibel = gvc_mixer_stream_get_can_decibel (icon->priv->mixer_stream); + volume = mate_mixer_stream_get_volume (icon->priv->mixer_stream); + is_muted = mate_mixer_stream_get_mute (icon->priv->mixer_stream); + + flags = mate_mixer_stream_get_flags (icon->priv->mixer_stream); + + if (flags & MATE_MIXER_STREAM_HAS_DECIBEL_VOLUME) { + volume_db = mate_mixer_stream_get_volume_db (icon->priv->mixer_stream); + can_decibel = TRUE; + } + + normal_volume = mate_mixer_stream_get_normal_volume (icon->priv->mixer_stream); /* select image */ if (volume <= 0 || is_muted) { n = 0; } else { - n = 3 * volume / PA_VOLUME_NORM + 1; + n = 3 * volume / normal_volume + 1; if (n < 1) { n = 1; } else if (n > 3) { @@ -477,26 +476,26 @@ update_icon (GvcStreamStatusIcon *icon) "%s: %s\n%s", icon->priv->display_name, _("Muted"), - gvc_mixer_stream_get_description (icon->priv->mixer_stream)); - } else if (can_decibel && (db > PA_DECIBEL_MININFTY)) { + mate_mixer_stream_get_description (icon->priv->mixer_stream)); + } else if (can_decibel && (volume_db > PA_DECIBEL_MININFTY)) { markup = g_strdup_printf ( "%s: %.0f%%\n%0.2f dB\n%s", icon->priv->display_name, - 100 * (float)volume / PA_VOLUME_NORM, - db, - gvc_mixer_stream_get_description (icon->priv->mixer_stream)); + 100 * (float) volume / normal_volume, + volume_db, + mate_mixer_stream_get_description (icon->priv->mixer_stream)); } else if (can_decibel) { markup = g_strdup_printf ( "%s: %.0f%%\n-∞ dB\n%s", icon->priv->display_name, - 100 * (float)volume / PA_VOLUME_NORM, - gvc_mixer_stream_get_description (icon->priv->mixer_stream)); + 100 * (float) volume / normal_volume, + mate_mixer_stream_get_description (icon->priv->mixer_stream)); } else { markup = g_strdup_printf ( "%s: %.0f%%\n%s", icon->priv->display_name, - 100 * (float)volume / PA_VOLUME_NORM, - gvc_mixer_stream_get_description (icon->priv->mixer_stream)); + 100 * (float) volume / normal_volume, + mate_mixer_stream_get_description (icon->priv->mixer_stream)); } gtk_status_icon_set_tooltip_markup (GTK_STATUS_ICON (icon), markup); g_free (markup); @@ -524,9 +523,9 @@ on_stream_volume_notify (GObject *object, } static void -on_stream_is_muted_notify (GObject *object, - GParamSpec *pspec, - GvcStreamStatusIcon *icon) +on_stream_mute_notify (GObject *object, + GParamSpec *pspec, + GvcStreamStatusIcon *icon) { update_icon (icon); update_dock (icon); @@ -546,7 +545,7 @@ gvc_stream_status_icon_set_display_name (GvcStreamStatusIcon *icon, void gvc_stream_status_icon_set_mixer_stream (GvcStreamStatusIcon *icon, - GvcMixerStream *stream) + MateMixerStream *stream) { g_return_if_fail (GVC_STREAM_STATUS_ICON (icon)); @@ -559,10 +558,10 @@ gvc_stream_status_icon_set_mixer_stream (GvcStreamStatusIcon *icon, G_CALLBACK (on_stream_volume_notify), icon); g_signal_handlers_disconnect_by_func (icon->priv->mixer_stream, - G_CALLBACK (on_stream_is_muted_notify), + G_CALLBACK (on_stream_mute_notify), icon); + g_object_unref (icon->priv->mixer_stream); - icon->priv->mixer_stream = NULL; } icon->priv->mixer_stream = stream; @@ -575,7 +574,7 @@ gvc_stream_status_icon_set_mixer_stream (GvcStreamStatusIcon *icon, icon->priv->thaw = TRUE; adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (icon->priv->bar))); gtk_adjustment_set_value (adj, - gvc_mixer_stream_get_volume (icon->priv->mixer_stream)); + mate_mixer_stream_get_volume (icon->priv->mixer_stream)); icon->priv->thaw = FALSE; g_signal_connect (icon->priv->mixer_stream, @@ -583,8 +582,8 @@ gvc_stream_status_icon_set_mixer_stream (GvcStreamStatusIcon *icon, G_CALLBACK (on_stream_volume_notify), icon); g_signal_connect (icon->priv->mixer_stream, - "notify::is-muted", - G_CALLBACK (on_stream_is_muted_notify), + "notify::mute", + G_CALLBACK (on_stream_mute_notify), icon); } @@ -647,16 +646,8 @@ on_bar_is_muted_notify (GObject *object, GParamSpec *pspec, GvcStreamStatusIcon *icon) { - gboolean is_muted; - - is_muted = gvc_channel_bar_get_is_muted (GVC_CHANNEL_BAR (object)); - - if (gvc_mixer_stream_get_is_muted (icon->priv->mixer_stream) != is_muted) { - /* Update the stream before pushing the change */ - gvc_mixer_stream_set_is_muted (icon->priv->mixer_stream, is_muted); - gvc_mixer_stream_change_is_muted (icon->priv->mixer_stream, - is_muted); - } + mate_mixer_stream_set_mute (icon->priv->mixer_stream, + gvc_channel_bar_get_is_muted (GVC_CHANNEL_BAR (object))); } static GObject * @@ -740,10 +731,7 @@ gvc_stream_status_icon_dispose (GObject *object) icon->priv->dock = NULL; } - if (icon->priv->mixer_stream != NULL) { - g_object_unref (icon->priv->mixer_stream); - icon->priv->mixer_stream = NULL; - } + g_clear_object (&icon->priv->mixer_stream); G_OBJECT_CLASS (gvc_stream_status_icon_parent_class)->dispose (object); } @@ -764,22 +752,25 @@ gvc_stream_status_icon_class_init (GvcStreamStatusIconClass *klass) g_param_spec_object ("mixer-stream", "mixer stream", "mixer stream", - GVC_TYPE_MIXER_STREAM, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); + MATE_MIXER_TYPE_STREAM, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_DISPLAY_NAME, g_param_spec_string ("display-name", "Display Name", "Name to display for this stream", NULL, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_ICON_NAMES, g_param_spec_boxed ("icon-names", "Icon Names", "Name of icon to display for this stream", G_TYPE_STRV, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); g_type_class_add_private (klass, sizeof (GvcStreamStatusIconPrivate)); } @@ -829,28 +820,21 @@ gvc_stream_status_icon_init (GvcStreamStatusIcon *icon) static void gvc_stream_status_icon_finalize (GObject *object) { - GvcStreamStatusIcon *stream_status_icon; - - g_return_if_fail (object != NULL); - g_return_if_fail (GVC_IS_STREAM_STATUS_ICON (object)); - - stream_status_icon = GVC_STREAM_STATUS_ICON (object); + GvcStreamStatusIcon *icon; - g_return_if_fail (stream_status_icon->priv != NULL); + icon = GVC_STREAM_STATUS_ICON (object); - g_strfreev (stream_status_icon->priv->icon_names); + g_strfreev (icon->priv->icon_names); G_OBJECT_CLASS (gvc_stream_status_icon_parent_class)->finalize (object); } GvcStreamStatusIcon * -gvc_stream_status_icon_new (GvcMixerStream *stream, - const char **icon_names) +gvc_stream_status_icon_new (MateMixerStream *stream, + const char **icon_names) { - GObject *icon; - icon = g_object_new (GVC_TYPE_STREAM_STATUS_ICON, + return g_object_new (GVC_TYPE_STREAM_STATUS_ICON, "mixer-stream", stream, "icon-names", icon_names, NULL); - return GVC_STREAM_STATUS_ICON (icon); } diff --git a/mate-volume-control/src/gvc-stream-status-icon.h b/mate-volume-control/src/gvc-stream-status-icon.h index 8c984a0..cd32f64 100644 --- a/mate-volume-control/src/gvc-stream-status-icon.h +++ b/mate-volume-control/src/gvc-stream-status-icon.h @@ -21,34 +21,37 @@ #ifndef __GVC_STREAM_STATUS_ICON_H #define __GVC_STREAM_STATUS_ICON_H +#include #include -#include "gvc-mixer-stream.h" +#include G_BEGIN_DECLS #define GVC_TYPE_STREAM_STATUS_ICON (gvc_stream_status_icon_get_type ()) #define GVC_STREAM_STATUS_ICON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_STREAM_STATUS_ICON, GvcStreamStatusIcon)) -#define GVC_STREAM_STATUS_ICON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_STREAM_STATUS_ICON, GvcStreamStatusIconClass)) +#define GVC_STREAM_STATUS_ICON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GVC_TYPE_STREAM_STATUS_ICON, GvcStreamStatusIconClass)) #define GVC_IS_STREAM_STATUS_ICON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_STREAM_STATUS_ICON)) #define GVC_IS_STREAM_STATUS_ICON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_STREAM_STATUS_ICON)) #define GVC_STREAM_STATUS_ICON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_STREAM_STATUS_ICON, GvcStreamStatusIconClass)) -typedef struct GvcStreamStatusIconPrivate GvcStreamStatusIconPrivate; +typedef struct _GvcStreamStatusIcon GvcStreamStatusIcon; +typedef struct _GvcStreamStatusIconClass GvcStreamStatusIconClass; +typedef struct _GvcStreamStatusIconPrivate GvcStreamStatusIconPrivate; -typedef struct +struct _GvcStreamStatusIcon { GtkStatusIcon parent; GvcStreamStatusIconPrivate *priv; -} GvcStreamStatusIcon; +}; -typedef struct +struct _GvcStreamStatusIconClass { GtkStatusIconClass parent_class; -} GvcStreamStatusIconClass; +}; -GType gvc_stream_status_icon_get_type (void); +GType gvc_stream_status_icon_get_type (void) G_GNUC_CONST; -GvcStreamStatusIcon * gvc_stream_status_icon_new (GvcMixerStream *stream, +GvcStreamStatusIcon * gvc_stream_status_icon_new (MateMixerStream *stream, const char **icon_names); void gvc_stream_status_icon_set_icon_names (GvcStreamStatusIcon *icon, @@ -56,7 +59,7 @@ void gvc_stream_status_icon_set_icon_names (GvcStreamStatu void gvc_stream_status_icon_set_display_name (GvcStreamStatusIcon *icon, const char *display_name); void gvc_stream_status_icon_set_mixer_stream (GvcStreamStatusIcon *icon, - GvcMixerStream *stream); + MateMixerStream *stream); G_END_DECLS -- cgit v1.2.1