aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConor Curran <conor.curran@canonical.com>2010-02-03 22:02:41 -0800
committerConor Curran <conor.curran@canonical.com>2010-02-03 22:02:41 -0800
commit60ea7aa0f6219a69d05b658cba562d1e2c6104e2 (patch)
tree30107d5272dc0eb1226e314b5f160899059a6e97
parent54209010fc5b99fd7074ae1271cfea86abaea5c6 (diff)
downloadayatana-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
-rw-r--r--src/Makefile.am4
-rw-r--r--src/common-defs.h4
-rw-r--r--src/indicator-sound.c70
-rw-r--r--src/pulse-manager.c4
-rw-r--r--src/pulse-manager.h29
-rw-r--r--src/slider-menu-item.c122
-rw-r--r--src/slider-menu-item.h54
-rw-r--r--src/sound-service.c26
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.*/