diff options
author | Conor Curran <conor.curran@canonical.com> | 2010-02-03 22:02:41 -0800 |
---|---|---|
committer | Conor Curran <conor.curran@canonical.com> | 2010-02-03 22:02:41 -0800 |
commit | 60ea7aa0f6219a69d05b658cba562d1e2c6104e2 (patch) | |
tree | 30107d5272dc0eb1226e314b5f160899059a6e97 /src | |
parent | 54209010fc5b99fd7074ae1271cfea86abaea5c6 (diff) | |
download | ayatana-indicator-sound-60ea7aa0f6219a69d05b658cba562d1e2c6104e2.tar.gz ayatana-indicator-sound-60ea7aa0f6219a69d05b658cba562d1e2c6104e2.tar.bz2 ayatana-indicator-sound-60ea7aa0f6219a69d05b658cba562d1e2c6104e2.zip |
slider now works from the safe side of the dbusmenu
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/common-defs.h | 4 | ||||
-rw-r--r-- | src/indicator-sound.c | 70 | ||||
-rw-r--r-- | src/pulse-manager.c | 4 | ||||
-rw-r--r-- | src/pulse-manager.h | 29 | ||||
-rw-r--r-- | src/slider-menu-item.c | 122 | ||||
-rw-r--r-- | src/slider-menu-item.h | 54 | ||||
-rw-r--r-- | src/sound-service.c | 26 |
8 files changed, 256 insertions, 57 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index b5c9157..543ec58 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -53,7 +53,9 @@ indicator_sound_service_SOURCES = \ sound-service-dbus.c \ sound-service-server.h \ sound-service-marshal.c \ - sound-service-marshal.h + sound-service-marshal.h \ + slider-menu-item.h \ + slider-menu-item.c indicator_sound_service_CFLAGS = $(SOUNDSERVICE_CFLAGS) $(GCONF_CFLAGS) -DLIBEXECDIR=\"$(libexecdir)\" -Wall -Werror indicator_sound_service_LDADD = $(SOUNDSERVICE_LIBS) $(GCONF_LIBS) diff --git a/src/common-defs.h b/src/common-defs.h index 0421bd6..6cacb49 100644 --- a/src/common-defs.h +++ b/src/common-defs.h @@ -1,5 +1,7 @@ /* constants used for signals on the dbus. This file is shared between client and server implementation */ - #define SIGNAL_SINK_INPUT_WHILE_MUTED "SinkInputWhileMuted" #define METHOD_SET_SINK_VOLUME "SetSinkVolume" +// DBUS items +#define DBUSMENU_SLIDER_MENUITEM_TYPE "x-canonical-ido-slider-item" +#define DBUSMENU_SLIDER_MENUITEM_PROP_VOLUME "volume" diff --git a/src/indicator-sound.c b/src/indicator-sound.c index e36c03f..c2c3159 100644 --- a/src/indicator-sound.c +++ b/src/indicator-sound.c @@ -77,11 +77,10 @@ G_DEFINE_TYPE (IndicatorSound, indicator_sound, INDICATOR_OBJECT_TYPE); static GtkLabel * get_label (IndicatorObject * io); static GtkImage * get_icon (IndicatorObject * io); static GtkMenu * get_menu (IndicatorObject * io); -static GtkWidget* get_slider(IndicatorObject * io); - static GtkWidget *volume_slider = NULL; -static GtkMenu *menu = NULL; +static gboolean new_slider_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client); +static void slider_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GValue * value); static gboolean slider_value_changed_event_cb(GtkRange *range, GtkScrollType scroll, double value, gpointer user_data); // DBUS communication @@ -199,25 +198,68 @@ get_icon (IndicatorObject * io) static GtkMenu * get_menu (IndicatorObject * io) { - menu = GTK_MENU(dbusmenu_gtkmenu_new(INDICATOR_SOUND_DBUS_NAME, INDICATOR_SOUND_DBUS_OBJECT)); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), get_slider(io)); - gtk_widget_show_all(volume_slider); + DbusmenuGtkMenu *menu = dbusmenu_gtkmenu_new(INDICATOR_SOUND_DBUS_NAME, INDICATOR_SOUND_DBUS_OBJECT); + DbusmenuGtkClient *client = dbusmenu_gtkmenu_get_client(menu); + dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_SLIDER_MENUITEM_TYPE, new_slider_item); + + //gtk_menu_shell_append (GTK_MENU_SHELL (menu), get_slider(io)); + //gtk_widget_show_all(volume_slider); - return menu; + return GTK_MENU(menu); } -static GtkWidget* get_slider(IndicatorObject * io) +static gboolean new_slider_item(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client) { + g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE); + g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE); + volume_slider = ido_scale_menu_item_new_with_range ("Volume", 2, 98, 1); + + GtkMenuItem *menu_volume_slider = GTK_MENU_ITEM(volume_slider); + dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, menu_volume_slider, parent); + g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(slider_prop_change_cb), NULL); + GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider); - GtkRange* range = (GtkRange*)slider; - //g_signal_connect(G_OBJECT(range), "value-changed", G_CALLBACK(slider_event_detected), NULL); - g_signal_connect(G_OBJECT(range), "change-value", G_CALLBACK(slider_value_changed_event_cb), io); - return volume_slider; + GtkRange* range = (GtkRange*)slider; + g_signal_connect(G_OBJECT(range), "change-value", G_CALLBACK(slider_value_changed_event_cb), newitem); + return TRUE; +} + +/* Whenever we have a property change on a DbusmenuMenuitem + we need to be responsive to that. */ +static void slider_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GValue * value) +{ + g_debug("slider_prop_change_cb "); + if (!g_strcmp0(prop, DBUSMENU_SLIDER_MENUITEM_PROP_VOLUME)) { + /* Set the slider value */ + g_debug("about to set it"); + GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider); + GtkRange* range = (GtkRange*)slider; + gtk_range_set_value(range, (gdouble)g_value_get_double(value)); + } + return; } -static gboolean slider_value_changed_event_cb(GtkRange *range, GtkScrollType scroll, double value, gpointer user_data) +static gboolean slider_value_changed_event_cb(GtkRange *range, GtkScrollType scroll, double slider_value, gpointer user_data) { - org_ayatana_indicator_sound_set_sink_volume(sound_dbus_proxy, value, NULL); + DbusmenuMenuitem *item = (DbusmenuMenuitem*)user_data; + GValue value = {0}; + g_value_init(&value, G_TYPE_DOUBLE); + g_value_set_double(&value, slider_value); + + dbusmenu_menuitem_handle_event (item, "slider_change", &value, 0); return FALSE; } + +/* GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider);*/ +/*static GtkWidget* get_slider(IndicatorObject * io)*/ +/*{*/ +/* volume_slider = ido_scale_menu_item_new_with_range ("Volume", 2, 98, 1);*/ +/* GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider);*/ +/* GtkRange* range = (GtkRange*)slider;*/ +/* //g_signal_connect(G_OBJECT(range), "value-changed", G_CALLBACK(slider_event_detected), NULL); */ +/* g_signal_connect(G_OBJECT(range), "change-value", G_CALLBACK(slider_value_changed_event_cb), io); */ +/* return volume_slider;*/ +/*}*/ + + diff --git a/src/pulse-manager.c b/src/pulse-manager.c index 75fb08a..e563aca 100644 --- a/src/pulse-manager.c +++ b/src/pulse-manager.c @@ -25,9 +25,9 @@ static void destroy_sink_info(void *value); Refine the resolution of the slider or binary scale it to achieve a more subtle volume control. Use the base volume stored in the sink struct to calculate actual linear volumes. */ -void set_sink_volume(guint percent) +void set_sink_volume(gdouble percent) { - g_debug("in the pulse manager:set_sink_volume with percent %i", percent); + g_debug("in the pulse manager:set_sink_volume with percent %f", percent); if(DEFAULT_SINK_INDEX < 0) { g_warning("We have no default sink !!! - returning after not attempting to set any volume of any sink"); diff --git a/src/pulse-manager.h b/src/pulse-manager.h index fa076d5..5271628 100644 --- a/src/pulse-manager.h +++ b/src/pulse-manager.h @@ -2,32 +2,6 @@ #include <glib.h> #include "sound-service-dbus.h" -//enum SinkInputType { -// SINK_INPUT_ALL, -// SINK_INPUT_CLIENT, -// SINK_INPUT_VIRTUAL -//}; - -//enum SinkType { -// SINK_ALL, -// SINK_HARDWARE, -// SINK_VIRTUAL, -//}; - -//enum SourceOutputType { -// SOURCE_OUTPUT_ALL, -// SOURCE_OUTPUT_CLIENT, -// SOURCE_OUTPUT_VIRTUAL -//}; - -//enum SourceType { -// SOURCE_ALL, -// SOURCE_NO_MONITOR, -// SOURCE_HARDWARE, -// SOURCE_VIRTUAL, -// SOURCE_MONITOR, -//}; - typedef struct { gchar* name; @@ -43,10 +17,9 @@ typedef struct { } sink_info; -//void set_volume(gint sink_index, gint volume_percent); pa_context* get_context(void); void establish_pulse_activities(SoundServiceDbus *service); -void set_sink_volume(guint percent); +void set_sink_volume(gdouble percent); void toggle_global_mute(gboolean mute_value); diff --git a/src/slider-menu-item.c b/src/slider-menu-item.c new file mode 100644 index 0000000..a1e4725 --- /dev/null +++ b/src/slider-menu-item.c @@ -0,0 +1,122 @@ +/* +Copyright 2010 Canonical Ltd. + +Authors: + Conor Curran <conor.curran@canonical.com> + Ted Gould <ted@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, 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, see <http://www.gnu.org/licenses/>. +*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <glib/gi18n.h> +#include "slider-menu-item.h" +#include "pulse-manager.h" +#include "common-defs.h" + +/*enum {*/ +/* VOLUME_CHANGED,*/ +/* FINAL_SIGNAL*/ +/*};*/ + +/*static guint slider_signals[FINAL_SIGNAL] = { 0 };*/ + +typedef struct _SliderMenuItemPrivate SliderMenuItemPrivate; + +struct _SliderMenuItemPrivate +{ + gdouble slider_value; +}; + +#define SLIDER_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SLIDER_MENU_ITEM_TYPE, SliderMenuItemPrivate)) + +/* Prototypes */ +static void slider_menu_item_class_init (SliderMenuItemClass *klass); +static void slider_menu_item_init (SliderMenuItem *self); +static void slider_menu_item_dispose (GObject *object); +static void slider_menu_item_finalize (GObject *object); +static void handle_event (DbusmenuMenuitem * mi, const gchar * name, const GValue * value, guint timestamp); + +G_DEFINE_TYPE (SliderMenuItem, slider_menu_item, DBUSMENU_TYPE_MENUITEM); + +static void slider_menu_item_class_init (SliderMenuItemClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (SliderMenuItemPrivate)); + + object_class->dispose = slider_menu_item_dispose; + object_class->finalize = slider_menu_item_finalize; + + DbusmenuMenuitemClass * mclass = DBUSMENU_MENUITEM_CLASS(klass); + mclass->handle_event = handle_event; +/* signals[VOLUME_CHANGED] = g_signal_new(SLIDER_MENU_ITEM_SIGNAL_VOLUME_CHANGED,*/ +/* G_TYPE_FROM_CLASS(klass),*/ +/* G_SIGNAL_RUN_LAST,*/ +/* G_STRUCT_OFFSET (SliderMenuItemClass, volume_changed),*/ +/* NULL, NULL,*/ +/* g_cclosure_marshal_VOID__DOUBLE,*/ +/* G_TYPE_NONE, 1, G_TYPE_DOUBLE);*/ + return; +} + +static void slider_menu_item_init (SliderMenuItem *self) +{ + g_debug("Building new Slider Menu Item"); + return; +} + +static void slider_menu_item_dispose (GObject *object) +{ + G_OBJECT_CLASS (slider_menu_item_parent_class)->dispose (object); + return; +} + +static void +slider_menu_item_finalize (GObject *object) +{ + G_OBJECT_CLASS (slider_menu_item_parent_class)->finalize (object); +} + + + +static void +handle_event (DbusmenuMenuitem * mi, const gchar * name, const GValue * value, guint timestamp) +{ + g_debug("in the handle event method of slider_menu_item"); + + set_sink_volume((gdouble)g_value_get_double(value)); +} + + + +SliderMenuItem* slider_menu_item_new(gboolean sinks_available, gdouble start_volume) +{ + SliderMenuItem *self = g_object_new(SLIDER_MENU_ITEM_TYPE, NULL); + //SliderMenuItemPrivate * priv = SLIDER_MENU_ITEM_GET_PRIVATE(self); + dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_SLIDER_MENUITEM_TYPE); + //TODO: If no valid sinks are found grey out the item(s) + dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_SENSITIVE, sinks_available); + + GValue value = {0}; + g_value_init(&value, G_TYPE_DOUBLE); + g_value_set_double(&value, start_volume); + //dbusmenu_menuitem_property_set_value(DBUSMENU_MENUITEM(self), DBUSMENU_SLIDER_MENUITEM_PROP_VOLUME, &value); + return self; +} + + + + diff --git a/src/slider-menu-item.h b/src/slider-menu-item.h new file mode 100644 index 0000000..48e71ff --- /dev/null +++ b/src/slider-menu-item.h @@ -0,0 +1,54 @@ +/* +Copyright 2010 Canonical Ltd. + +Authors: + Conor Curran <conor.curran@canonical.com> + Ted Gould <ted@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, 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, see <http://www.gnu.org/licenses/>. +*/ +#ifndef __SLIDER_MENU_ITEM_H__ +#define __SLIDER_MENU_ITEM_H__ + +#include <glib.h> +#include <glib-object.h> + +#include <libdbusmenu-glib/menuitem.h> + +G_BEGIN_DECLS + +#define SLIDER_MENU_ITEM_TYPE (slider_menu_item_get_type ()) +#define SLIDER_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SLIDER_MENU_ITEM_TYPE, SliderMenuItem)) +#define SLIDER_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SLIDER_MENU_ITEM_TYPE, SliderMenuItemClass)) +#define IS_SLIDER_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SLIDER_MENU_ITEM_TYPE)) +#define IS_SLIDER_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SLIDER_MENU_ITEM_TYPE)) +#define SLIDER_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SLIDER_MENU_ITEM_TYPE, SliderMenuItemClass)) + +typedef struct _SliderMenuItem SliderMenuItem; +typedef struct _SliderMenuItemClass SliderMenuItemClass; + +struct _SliderMenuItemClass { + DbusmenuMenuitemClass parent_class; +}; + +struct _SliderMenuItem { + DbusmenuMenuitem parent; +}; + +GType slider_menu_item_get_type (void); +SliderMenuItem* slider_menu_item_new(gboolean sinks_available, gdouble current_vol); + +G_END_DECLS + +#endif + diff --git a/src/sound-service.c b/src/sound-service.c index 1537fce..ce2b101 100644 --- a/src/sound-service.c +++ b/src/sound-service.c @@ -23,19 +23,22 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include "sound-service.h" #include "sound-service-dbus.h" #include "pulse-manager.h" +#include "slider-menu-item.h" #include "common-defs.h" -//TODO: Follow hungarian notation + // GTK + DBUS -static GMainLoop * mainloop = NULL; -static DbusmenuMenuitem * root_menuitem = NULL; -static DbusmenuMenuitem * mute_all_menuitem = NULL; -static SoundServiceDbus * dbus_interface = NULL; +static GMainLoop *mainloop = NULL; +static DbusmenuMenuitem *root_menuitem = NULL; +static DbusmenuMenuitem *mute_all_menuitem = NULL; +static SliderMenuItem *volume_slider_menuitem = NULL; +static SoundServiceDbus *dbus_interface = NULL; // PULSEAUDIO static gboolean b_sink_available = FALSE; static gboolean b_all_muted = FALSE; static gboolean b_pulse_ready = FALSE; +static gdouble volume_percent = 0.0; static void set_global_mute(); static gboolean idle_routine (gpointer data); @@ -58,13 +61,17 @@ Build the DBus menu items. For now Mute all/Unmute is the only available option **/ static void rebuild_sound_menu(DbusmenuMenuitem *root, SoundServiceDbus *service) { + // Mute button mute_all_menuitem = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(mute_all_menuitem, DBUSMENU_MENUITEM_PROP_LABEL, _(b_all_muted == FALSE ? "Mute All" : "Unmute")); g_signal_connect(G_OBJECT(mute_all_menuitem), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(set_global_mute), NULL); //TODO: If no valid sinks are found grey out the item(s) dbusmenu_menuitem_property_set_bool(mute_all_menuitem, DBUSMENU_MENUITEM_PROP_SENSITIVE, b_sink_available); + + // Slider + volume_slider_menuitem = slider_menu_item_new(b_sink_available, volume_percent); dbusmenu_menuitem_child_append(root, mute_all_menuitem); + dbusmenu_menuitem_child_append(root, DBUSMENU_MENUITEM(volume_slider_menuitem)); } static void set_global_mute() @@ -91,19 +98,16 @@ service_shutdown (IndicatorService *service, gpointer user_data) return; } -void update_pa_state(gboolean pa_state, gboolean sink_available, gboolean sink_muted, gdouble volume_percent) +void update_pa_state(gboolean pa_state, gboolean sink_available, gboolean sink_muted, gdouble percent) { b_sink_available = sink_available; b_all_muted = sink_muted; b_pulse_ready = pa_state; + volume_percent = percent; g_debug("update pa state with state %i, availability of %i, mute value of %i and a volume percent is %f", pa_state, sink_available, sink_muted, volume_percent); rebuild_sound_menu(root_menuitem, dbus_interface); } -/** -Pulsemanager will call this once enough info has been gathered about the PA state -**/ - /* Main, is well, main. It brings everything up and throws us into the mainloop of no return. Some refactoring needed.*/ |