aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorConor Curran <conor.curran@canonical.com>2010-02-10 13:11:00 +0000
committerConor Curran <conor.curran@canonical.com>2010-02-10 13:11:00 +0000
commit1b4d886b058dcfc0c0c89631bdeb91209ebfcdda (patch)
tree515c6778ea438bdf966b5a52b30aaed76e52026d /src
parent8c992efe8d490c63021bca280c4e2d46f22bca40 (diff)
parentef8f7d725ef912219e1829d4c22db9abbc00df1a (diff)
downloadayatana-indicator-sound-1b4d886b058dcfc0c0c89631bdeb91209ebfcdda.tar.gz
ayatana-indicator-sound-1b4d886b058dcfc0c0c89631bdeb91209ebfcdda.tar.bz2
ayatana-indicator-sound-1b4d886b058dcfc0c0c89631bdeb91209ebfcdda.zip
merged with dev branch - should be seen as first release from now on will request merges
Diffstat (limited to 'src')
-rw-r--r--src/common-defs.h3
-rw-r--r--src/indicator-sound.c224
-rw-r--r--src/pulse-manager.c193
-rw-r--r--src/pulse-manager.h1
-rw-r--r--src/slider-menu-item.c3
-rw-r--r--src/slider-menu-item.h1
-rw-r--r--src/sound-service-dbus.c138
-rw-r--r--src/sound-service-dbus.h19
-rw-r--r--src/sound-service.c34
-rw-r--r--src/sound-service.h4
-rw-r--r--src/sound-service.xml19
11 files changed, 466 insertions, 173 deletions
diff --git a/src/common-defs.h b/src/common-defs.h
index 6cacb49..896caba 100644
--- a/src/common-defs.h
+++ b/src/common-defs.h
@@ -1,6 +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"
+#define SIGNAL_SINK_VOLUME_UPDATE "SinkVolumeUpdate"
+#define SIGNAL_SINK_MUTE_UPDATE "SinkMuteUpdate"
// DBUS items
#define DBUSMENU_SLIDER_MENUITEM_TYPE "x-canonical-ido-slider-item"
diff --git a/src/indicator-sound.c b/src/indicator-sound.c
index e8babdf..07ffe30 100644
--- a/src/indicator-sound.c
+++ b/src/indicator-sound.c
@@ -78,18 +78,40 @@ static GtkLabel * get_label (IndicatorObject * io);
static GtkImage * get_icon (IndicatorObject * io);
static GtkMenu * get_menu (IndicatorObject * io);
static GtkWidget *volume_slider = NULL;
-static gdouble input_value_from_across_the_dbus = 0.0;
-static GtkImage *speaker_image = NULL;
static gboolean new_slider_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client);
static void slider_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GValue * value, GtkWidget *widget);
-static gboolean slider_value_changed_event_cb(GtkRange *range, GtkScrollType scroll, double value, gpointer user_data);
-static void change_speaker_image(gdouble volume_percent);
+static gboolean slider_value_changed_event_cb(GtkRange *range, GtkScrollType scroll_type, gdouble input_value, gpointer user_data);
+
+static void prepare_state_machine();
+static void determine_state_from_volume(gdouble volume_percent);
+static void update_state(const gint state);
+static void fetch_volume_percent_from_dbus();
+static void fetch_mute_value_from_dbus();
+/*static void revert_state();*/
// DBUS communication
static DBusGProxy *sound_dbus_proxy = NULL;
static void connection_changed (IndicatorServiceManager * sm, gboolean connected, gpointer userdata);
-static void catch_signal_sink_input_while_muted(DBusGProxy * proxy, gint sink_index, gboolean value, gpointer userdata);
+
+static void catch_signal_sink_input_while_muted(DBusGProxy * proxy, gboolean value, gpointer userdata);
+static void catch_signal_sink_volume_update(DBusGProxy * proxy, gdouble volume_percent, gpointer userdata);
+static void catch_signal_sink_mute_update(DBusGProxy *proxy, gboolean mute_value, gpointer userdata);
+
+/****Volume States 'members' ***/
+static const gint STATE_MUTED = 0;
+static const gint STATE_ZERO = 1;
+static const gint STATE_LOW = 2;
+static const gint STATE_MEDIUM = 3;
+static const gint STATE_HIGH = 4;
+static const gint STATE_MUTED_WHILE_INPUT = 5;
+static const gint STATE_SINKS_NONE = 5;
+static GHashTable *volume_states = NULL;
+static GtkImage *speaker_image = NULL;
+static gint current_state = 0;
+static gint previous_state = 0;
+static gdouble initial_volume_percent = 0;
+static gboolean initial_mute = FALSE;
static void
indicator_sound_class_init (IndicatorSoundClass *klass)
@@ -119,9 +141,37 @@ static void indicator_sound_init (IndicatorSound *self)
/* Now let's fire these guys up. */
self->service = indicator_service_manager_new_version(INDICATOR_SOUND_DBUS_NAME, INDICATOR_SOUND_DBUS_VERSION);
g_signal_connect(G_OBJECT(self->service), INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE, G_CALLBACK(connection_changed), self);
+ prepare_state_machine();
return;
}
+
+/*static void test_images_hash()*/
+/*{*/
+/* g_debug("about to test the images hash"); */
+/* gchar* current_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(current_state));*/
+/* g_debug("start up current image name = %s", current_name); */
+/* gchar* previous_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(previous_state));*/
+/* g_debug("start up previous image name = %s", previous_name); */
+/*}*/
+
+/*
+Prepare states Array.
+*/
+static void prepare_state_machine()
+{
+ // TODO we need three more images
+ volume_states = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
+ g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_MUTED), g_strdup("audio-volume-muted"));
+ g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_ZERO), g_strdup(/*"audio-volume-zero"*/"audio-volume-muted"));
+ g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_LOW), g_strdup("audio-volume-low"));
+ g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_MEDIUM), g_strdup("audio-volume-medium"));
+ g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_HIGH), g_strdup("audio-volume-high"));
+ g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_MUTED_WHILE_INPUT), g_strdup(/*"audio-volume-muted-blocking"*/"audio-volume-muted"));
+ g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_SINKS_NONE), g_strdup(/*"audio-output-none"*/"audio-volume-muted"));
+ //test_images_hash();
+}
+
static void
connection_changed (IndicatorServiceManager * sm, gboolean connected, gpointer userdata)
{
@@ -142,8 +192,18 @@ connection_changed (IndicatorServiceManager * sm, gboolean connected, gpointer u
g_error_free(error);
}
g_debug("about to connect to the signals");
- dbus_g_proxy_add_signal(sound_dbus_proxy, SIGNAL_SINK_INPUT_WHILE_MUTED, G_TYPE_INT, G_TYPE_BOOLEAN, G_TYPE_INVALID);
+ dbus_g_proxy_add_signal(sound_dbus_proxy, SIGNAL_SINK_INPUT_WHILE_MUTED, G_TYPE_BOOLEAN, G_TYPE_INVALID);
+
dbus_g_proxy_connect_signal(sound_dbus_proxy, SIGNAL_SINK_INPUT_WHILE_MUTED, G_CALLBACK(catch_signal_sink_input_while_muted), NULL, NULL);
+ dbus_g_proxy_add_signal(sound_dbus_proxy, SIGNAL_SINK_VOLUME_UPDATE, G_TYPE_DOUBLE, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(sound_dbus_proxy, SIGNAL_SINK_VOLUME_UPDATE, G_CALLBACK(catch_signal_sink_volume_update), NULL, NULL);
+ dbus_g_proxy_add_signal(sound_dbus_proxy, SIGNAL_SINK_MUTE_UPDATE, G_TYPE_BOOLEAN, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(sound_dbus_proxy, SIGNAL_SINK_MUTE_UPDATE, G_CALLBACK(catch_signal_sink_mute_update), NULL, NULL);
+
+ // Ensure we are in a coherent state with the service at start up.
+ // Preserve ordering!
+ fetch_volume_percent_from_dbus();
+ fetch_mute_value_from_dbus();
}
} else {
@@ -153,13 +213,75 @@ connection_changed (IndicatorServiceManager * sm, gboolean connected, gpointer u
return;
}
+static void fetch_volume_percent_from_dbus()
+{
+ GError * error = NULL;
+ gdouble *volume_percent_input;
+ volume_percent_input = g_new0(gdouble, 1);
+ org_ayatana_indicator_sound_get_sink_volume(sound_dbus_proxy, volume_percent_input, &error);
+ if (error != NULL) {
+ g_warning("Unable to fetch VOLUME at indicator start up: %s", error->message);
+ g_error_free(error);
+ g_free(volume_percent_input);
+ return;
+ }
+ initial_volume_percent = *volume_percent_input;
+ determine_state_from_volume(initial_volume_percent);
+ g_free(volume_percent_input);
+ g_debug("at the indicator start up and the volume percent returned from dbus method is %f", initial_volume_percent);
+}
-static void catch_signal_sink_input_while_muted(DBusGProxy * proxy, gint sink_index, gboolean value, gpointer userdata)
+static void fetch_mute_value_from_dbus()
{
- //gtk_image_set_from_icon_name(speaker_image, "audio-volume-muted-blocking-symbolic", GTK_ICON_SIZE_MENU);
- g_debug("signal caught - I don't believe it ! with index %i and value %i", sink_index, value);
+ GError * error = NULL;
+ gboolean *mute_input;
+ mute_input = g_new0(gboolean, 1);
+ org_ayatana_indicator_sound_get_sink_mute(sound_dbus_proxy, mute_input, &error);
+ if (error != NULL) {
+ g_warning("Unable to fetch MUTE at indicator start up: %s", error->message);
+ g_error_free(error);
+ g_free(mute_input);
+ return;
+ }
+ initial_mute = *mute_input;
+ if (initial_mute == TRUE)
+ update_state(STATE_MUTED);
+ g_free(mute_input);
+ g_debug("at the indicator start up and the MUTE returned from dbus method is %i", initial_mute);
+}
+
+static void catch_signal_sink_input_while_muted(DBusGProxy * proxy, gboolean block_value, gpointer userdata)
+{
+ g_debug("signal caught - sink input while muted with value %i", block_value);
+}
+
+static void catch_signal_sink_volume_update(DBusGProxy *proxy, gdouble volume_percent, gpointer userdata)
+{
+ g_debug("signal caught - update sink volume with value : %f", volume_percent);
+ GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider);
+ gboolean in_use = gtk_widget_has_grab(volume_slider);
+ if(in_use == TRUE)
+ {
+ g_debug("looks like the slider is the UI element in use therefore ignore this volume message => prevent circular semi feedback.");
+ return;
+ }
+ GtkRange *range = (GtkRange*)slider;
+ gtk_range_set_value(range, volume_percent);
+ determine_state_from_volume(volume_percent);
}
+static void catch_signal_sink_mute_update(DBusGProxy *proxy, gboolean mute_value, gpointer userdata)
+{
+ //We can be sure the service won't send a mute signal unless it has changed !
+ //UNMUTE's force a volume update therefore icon is updated appropriately => no need for unmute handling here.
+ if(mute_value == TRUE)
+ {
+ g_debug("signal caught - sink mute update - MUTE");
+ update_state(STATE_MUTED);
+ }
+}
+
+
static void
indicator_sound_dispose (GObject *object)
{
@@ -169,6 +291,7 @@ indicator_sound_dispose (GObject *object)
g_object_unref(G_OBJECT(self->service));
self->service = NULL;
}
+ g_hash_table_destroy(volume_states);
G_OBJECT_CLASS (indicator_sound_parent_class)->dispose (object);
return;
}
@@ -189,26 +312,55 @@ get_label (IndicatorObject * io)
static GtkImage *
get_icon (IndicatorObject * io)
{
- speaker_image = GTK_IMAGE(gtk_image_new_from_icon_name("audio-volume-high", GTK_ICON_SIZE_MENU));
+ gchar* current_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(current_state));
+ g_debug("At start-up attempting to set the image to %s", current_name);
+ speaker_image = GTK_IMAGE(gtk_image_new_from_icon_name(current_name, GTK_ICON_SIZE_MENU));
gtk_widget_show(GTK_WIDGET(speaker_image));
return speaker_image;
}
-static void change_speaker_image(gdouble volume_percent)
-{
+static void update_state(const gint state)
+{
+ g_debug("update state beginning - previous_state = %i", previous_state);
+
+ previous_state = current_state;
+
+ g_debug("update state 3rd line - previous_state = %i", previous_state);
+
+ current_state = state;
+ gchar* image_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(current_state));
+ gtk_image_set_from_icon_name(speaker_image, image_name, GTK_ICON_SIZE_MENU);
+}
+
+/*static void revert_state()*/
+/*{*/
+
+/* g_debug("revert state beginning - previous_state = %i", previous_state);*/
+/* current_state = previous_state;*/
+/* gchar* image_name = g_hash_table_lookup(volume_states, GINT_TO_POINTER(current_state));*/
+/* gtk_image_set_from_icon_name(speaker_image, image_name, GTK_ICON_SIZE_MENU);*/
+/* g_debug("after reverting back to previous state of %i", current_state);*/
+/*}*/
+
+static void determine_state_from_volume(gdouble volume_percent)
+{
+ g_debug("determine_state_from_volume - previous_state = %i", previous_state);
+ gint state = previous_state;
if (volume_percent < 30.0 && volume_percent > 0){
- gtk_image_set_from_icon_name(speaker_image, "audio-volume-low", GTK_ICON_SIZE_MENU);
+ state = STATE_LOW;
}
else if(volume_percent < 70.0 && volume_percent > 30.0){
- gtk_image_set_from_icon_name(speaker_image, "audio-volume-medium", GTK_ICON_SIZE_MENU);
+ state = STATE_MEDIUM;
}
else if(volume_percent > 70.0){
- gtk_image_set_from_icon_name(speaker_image, "audio-volume-high", GTK_ICON_SIZE_MENU);
- }
- else if(volume_percent <= 0.0){
- gtk_image_set_from_icon_name(speaker_image, "audio-volume-zero", GTK_ICON_SIZE_MENU);
+ state = STATE_HIGH;
}
+ else if(volume_percent == 0.0){
+ state = STATE_ZERO;
+ }
+ update_state(state);
}
+
/* Indicator based function to get the menu for the whole
applet. This starts up asking for the parts of the menu
@@ -233,10 +385,13 @@ static gboolean new_slider_item(DbusmenuMenuitem * newitem, DbusmenuMenuitem * p
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), volume_slider);
-
- GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider);
+
+ GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider);
+ g_signal_connect(slider, "change-value", G_CALLBACK(slider_value_changed_event_cb), newitem);
GtkRange* range = (GtkRange*)slider;
- g_signal_connect(G_OBJECT(range), "change-value", G_CALLBACK(slider_value_changed_event_cb), newitem);
+ gtk_range_set_value(range, initial_volume_percent);
+
+ gtk_widget_show_all(volume_slider);
return TRUE;
}
@@ -244,30 +399,23 @@ static gboolean new_slider_item(DbusmenuMenuitem * newitem, DbusmenuMenuitem * p
we need to be responsive to that. */
static void slider_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GValue * value, GtkWidget *widget)
{
- g_debug("slider_prop_change_cb ");
+ g_debug("slider_prop_change_cb - dodgy updater ");
g_debug("about to set the slider to %f", g_value_get_double(value));
GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider);
- GtkRange* range = (GtkRange*)slider;
- gdouble level;
- level = gtk_range_get_fill_level(range);
- input_value_from_across_the_dbus = level;
- g_debug("the current level is %f", level);
-
+ GtkRange* range = (GtkRange*)slider;
gtk_range_set_value(range, g_value_get_double(value));
return;
}
-static gboolean slider_value_changed_event_cb(GtkRange *range, GtkScrollType scroll, double slider_value, gpointer user_data)
+static gboolean slider_value_changed_event_cb(GtkRange *range, GtkScrollType scroll_type, gdouble input_value, gpointer user_data)
{
- if(slider_value != input_value_from_across_the_dbus)
- {
- 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);
- change_speaker_image(slider_value);
- }
+ DbusmenuMenuitem *item = (DbusmenuMenuitem*)user_data;
+ gdouble clamped_input = CLAMP(input_value, 0, 100);
+ GValue value = {0};
+ g_debug("User input on SLIDER - = %f", clamped_input);
+ g_value_init(&value, G_TYPE_DOUBLE);
+ g_value_set_double(&value, clamped_input);
+ dbusmenu_menuitem_handle_event (item, "slider_change", &value, 0);
return FALSE;
}
diff --git a/src/pulse-manager.c b/src/pulse-manager.c
index ce63b0d..8bf6cac 100644
--- a/src/pulse-manager.c
+++ b/src/pulse-manager.c
@@ -19,34 +19,13 @@ static void pulse_sink_info_callback(pa_context *c, const pa_sink_info *sink_inf
static void context_success_callback(pa_context *c, int success, void *userdata);
static void pulse_sink_input_info_callback(pa_context *c, const pa_sink_input_info *info, int eol, void *userdata);
static void pulse_server_info_callback(pa_context *c, const pa_server_info *info, void *userdata);
+static void update_sink_info(pa_context *c, const pa_sink_info *info, int eol, void *userdata);
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.
+Entry point
*/
-void set_sink_volume(gdouble 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");
- return;
- }
- gdouble linear_input = (gdouble)(percent);
- linear_input /= 100.0;
- g_debug("linear double input = %f", linear_input);
- pa_volume_t new_volume = pa_sw_volume_from_linear(linear_input);
- // Use this to achieve more accurate scaling using the base volume (in the sink struct already!)
- //pa_volume_t new_volume = (pa_volume_t) ((GPOINTER_TO_INT(linear_input) * s->base_volume) / 100);
- g_debug("about to try to set the sw volume to a linear volume of %f", pa_sw_volume_to_linear(new_volume));
- g_debug("and an actual volume of %f", (gdouble)new_volume);
- pa_cvolume dev_vol;
- sink_info *s = g_hash_table_lookup(sink_hash, GINT_TO_POINTER(DEFAULT_SINK_INDEX));
- pa_cvolume_set(&dev_vol, s->volume.channels, new_volume);
- pa_operation_unref(pa_context_set_sink_volume_by_index(pulse_context, DEFAULT_SINK_INDEX, &dev_vol, NULL, NULL));
-}
-
void establish_pulse_activities(SoundServiceDbus *service)
{
dbus_service = service;
@@ -70,20 +49,9 @@ void close_pulse_activites()
g_hash_table_destroy(sink_hash);
pa_glib_mainloop_free(pa_main_loop);
pa_main_loop = NULL;
+ g_debug("I just closed communication with Pulse");
}
-static void mute_each_sink(gpointer key, gpointer value, gpointer user_data)
-{
- sink_info *info = (sink_info*)value;
- pa_operation_unref(pa_context_set_sink_mute_by_index(pulse_context, info->index, GPOINTER_TO_INT(user_data), context_success_callback, NULL));
- g_debug("in the pulse manager: mute each sink %i", GPOINTER_TO_INT(user_data));
-}
-
-void toggle_global_mute(gboolean mute_value)
-{
- g_hash_table_foreach(sink_hash, mute_each_sink, GINT_TO_POINTER(mute_value));
- g_debug("in the pulse manager: toggle global mute value %i", mute_value);
-}
static void destroy_sink_info(void *value)
{
@@ -94,15 +62,19 @@ static void destroy_sink_info(void *value)
g_free(sink);
}
-static void test_hash(){
- guint size = 0;
- size = g_hash_table_size(sink_hash);
- g_debug("Size of hash = %i", size);
- sink_info *s = g_hash_table_lookup(sink_hash, GINT_TO_POINTER(DEFAULT_SINK_INDEX));
- g_debug("The name of our sink is %s", s->name);
- g_debug("and the max volume is %f", (gdouble)s->base_volume);
+/*static void test_hash(){*/
+/* guint size = 0;*/
+/* size = g_hash_table_size(sink_hash);*/
+/* g_debug("Size of hash = %i", size);*/
+/* sink_info *s = g_hash_table_lookup(sink_hash, GINT_TO_POINTER(DEFAULT_SINK_INDEX)); */
+/* g_debug("The name of our sink is %s", s->name); */
+/* g_debug("and the max volume is %f", (gdouble)s->base_volume); */
-}
+/*}*/
+
+/*
+Controllers & Utilities
+*/
static gboolean sink_available()
{
@@ -121,19 +93,22 @@ static gboolean default_sink_is_muted()
return FALSE;
if (g_hash_table_size(sink_hash) < 1)
return FALSE;
- // TODO ensure hash has a key with this value!
sink_info *s = g_hash_table_lookup(sink_hash, GINT_TO_POINTER(DEFAULT_SINK_INDEX));
return s->mute;
}
static void check_sink_input_while_muted_event(gint sink_index)
{
+ g_debug("SINKINPUTWHILEMUTED SIGNAL EVENT TO BE SENT FROM PA MANAGER - check trace for value");
+
if (default_sink_is_muted(sink_index) == TRUE)
{
- g_debug("SINKINPUTWHILEMUTED SIGNAL EVENT TO BE SENT FROM PA MANAGER");
- sound_service_dbus_sink_input_while_muted (dbus_service, sink_index, TRUE);
+ sound_service_dbus_sink_input_while_muted (dbus_service, TRUE);
+ }
+ else
+ {
+ sound_service_dbus_sink_input_while_muted(dbus_service, FALSE);
}
- return;
}
static gdouble get_default_sink_volume()
@@ -147,6 +122,47 @@ static gdouble get_default_sink_volume()
return value;
}
+static void mute_each_sink(gpointer key, gpointer value, gpointer user_data)
+{
+ sink_info *info = (sink_info*)value;
+ pa_operation_unref(pa_context_set_sink_mute_by_index(pulse_context, info->index, GPOINTER_TO_INT(user_data), context_success_callback, NULL));
+ g_debug("in the pulse manager: mute each sink %i", GPOINTER_TO_INT(user_data));
+}
+
+void toggle_global_mute(gboolean mute_value)
+{
+ g_hash_table_foreach(sink_hash, mute_each_sink, GINT_TO_POINTER(mute_value));
+ g_debug("in the pulse manager: toggle global mute value %i", mute_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(gdouble 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");
+ return;
+ }
+ gdouble linear_input = (gdouble)(percent);
+ linear_input /= 100.0;
+ g_debug("linear double input = %f", linear_input);
+ pa_volume_t new_volume = pa_sw_volume_from_linear(linear_input);
+ // Use this to achieve more accurate scaling using the base volume (in the sink struct already!)
+ //pa_volume_t new_volume = (pa_volume_t) ((GPOINTER_TO_INT(linear_input) * s->base_volume) / 100);
+ g_debug("about to try to set the sw volume to a linear volume of %f", pa_sw_volume_to_linear(new_volume));
+ g_debug("and an actual volume of %f", (gdouble)new_volume);
+ pa_cvolume dev_vol;
+ sink_info *s = g_hash_table_lookup(sink_hash, GINT_TO_POINTER(DEFAULT_SINK_INDEX));
+ pa_cvolume_set(&dev_vol, s->volume.channels, new_volume);
+
+ pa_operation_unref(pa_context_set_sink_volume_by_index(pulse_context, DEFAULT_SINK_INDEX, &dev_vol, NULL, NULL));
+}
+
/**********************************************************************************************************************/
// Pulse-Audio asychronous call-backs
@@ -177,33 +193,33 @@ static void context_success_callback(pa_context *c, int success, void *userdata)
/**
On Service startup this callback will be called multiple times resulting our sinks_hash container to be filled with the
available sinks.
-key -> index
-value -> sink_info
-For now this callback it assumes it only used at startup. It may be necessary to use if sinks become available after startup
+For now this callback it assumes it only used at startup. It may be necessary to use if sinks become available after startup.
+Major candidate for refactoring.
**/
static void pulse_sink_info_callback(pa_context *c, const pa_sink_info *sink, int eol, void *userdata)
{
if (eol > 0) {
- gboolean device_available;
- device_available = sink_available();
+ gboolean device_available = sink_available();
if(device_available == TRUE)
{
// Hopefully the PA server has set the default device if not default to 0
DEFAULT_SINK_INDEX = (DEFAULT_SINK_INDEX < 0) ? 0 : DEFAULT_SINK_INDEX;
- test_hash();
+ // TODO optimize
+ // Cache method returns! (unneccessary multiple utility calls)
+ // test_hash();
update_pa_state(TRUE, device_available, default_sink_is_muted(), get_default_sink_volume());
- g_debug("default sink index : %d", DEFAULT_SINK_INDEX);
-
+ sound_service_dbus_update_sink_volume(dbus_service, get_default_sink_volume());
+ sound_service_dbus_update_sink_mute(dbus_service, default_sink_is_muted());
+ g_debug("default sink index : %d", DEFAULT_SINK_INDEX);
}
else{
//Update the indicator to show PA either is not ready or has no available sink
g_warning("Cannot find a suitable default sink ...");
update_pa_state(FALSE, device_available, TRUE, 0);
}
-
}
else{
- g_debug("About to add an item to our hash");
+ g_debug("About to add an item to our hash");
sink_info *value;
value = g_new0(sink_info, 1);
value->index = value->device_index = sink->index;
@@ -216,7 +232,7 @@ static void pulse_sink_info_callback(pa_context *c, const pa_sink_info *sink, in
value->base_volume = sink->base_volume;
value->channel_map = sink->channel_map;
g_hash_table_insert(sink_hash, GINT_TO_POINTER(sink->index), value);
- g_debug("After adding an item to our hash");
+ g_debug("After adding an item to our hash");
}
}
@@ -253,7 +269,58 @@ static void pulse_sink_input_info_callback(pa_context *c, const pa_sink_input_in
g_debug("\n SINK INPUT INFO sink index : %d \n", info->sink);
check_sink_input_while_muted_event(info->sink);
}
-}
+}
+
+static void update_sink_info(pa_context *c, const pa_sink_info *info, int eol, void *userdata)
+{
+ if (eol > 0) {
+ if (pa_context_errno(c) == PA_ERR_NOENTITY)
+ return;
+ g_warning("Sink INPUT info callback failure");
+ return;
+ }
+
+ GList *keys = g_hash_table_get_keys(sink_hash);
+ gint position = g_list_index(keys, GINT_TO_POINTER(info->index));
+ if(position >= 0) // => index is within the keys of the hash.
+ {
+ sink_info *s = g_hash_table_lookup(sink_hash, GINT_TO_POINTER(info->index));
+ //g_debug("attempting to update sink with name %s", s->name);
+ s->name = g_strdup(info->name);
+ s->description = g_strdup(info->description);
+ s->icon_name = g_strdup(pa_proplist_gets(info->proplist, PA_PROP_DEVICE_ICON_NAME));
+ s->active_port = (info->active_port != NULL);
+ // NASTY!!
+ gboolean mute_changed = s->mute != !!info->mute;
+ s->mute = !!info->mute;
+ s->volume = info->volume;
+ s->base_volume = info->base_volume;
+ s->channel_map = info->channel_map;
+ if(DEFAULT_SINK_INDEX == s->index)
+ {
+ //update the UI
+ pa_volume_t vol = pa_cvolume_avg(&s->volume);
+ // Use the base of the device to ensure maximum acceptable levels on the hardware
+ gdouble volume_percent = (vol/s->base_volume) * 100;
+ g_debug("When using base volume => volume = %f", volume_percent);
+ g_debug("about to update ui with linear volume of %f", pa_sw_volume_to_linear(vol));
+ sound_service_dbus_update_sink_volume(dbus_service, pa_sw_volume_to_linear(vol));
+ if (mute_changed == TRUE)
+ sound_service_dbus_update_sink_mute(dbus_service, s->mute);
+
+ update_mute_ui(s->mute);
+ }
+ }
+ else
+ {
+ // TODO ADD new sink - part of big refactor
+ g_debug("attempting to add new sink with name %s", info->name);
+ //sink_info *s;
+ //s = g_new0(sink_info, 1);
+ //update the sinks hash with new sink.
+ }
+}
+
static void pulse_server_info_callback(pa_context *c, const pa_server_info *info, void *userdata)
{
@@ -289,7 +356,11 @@ static void pulse_server_info_callback(pa_context *c, const pa_server_info *info
static void subscribed_events_callback(pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata){
switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
case PA_SUBSCRIPTION_EVENT_SINK:
- //g_debug("Event sink for %i", index);
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
+ //TODO handle the remove event => if its our default sink - grey out the ui with update_pa_state
+ } else {
+ pa_operation_unref(pa_context_get_sink_info_by_index(c, index, update_sink_info, userdata));
+ }
break;
case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
// This will be triggered when the sink receives input from a new stream
diff --git a/src/pulse-manager.h b/src/pulse-manager.h
index ddfc721..8fa32b3 100644
--- a/src/pulse-manager.h
+++ b/src/pulse-manager.h
@@ -24,4 +24,3 @@ void toggle_global_mute(gboolean mute_value);
void close_pulse_activites();
-
diff --git a/src/slider-menu-item.c b/src/slider-menu-item.c
index 2620e6e..2e8321d 100644
--- a/src/slider-menu-item.c
+++ b/src/slider-menu-item.c
@@ -91,11 +91,8 @@ handle_event (DbusmenuMenuitem * mi, const gchar * name, const GValue * value, g
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_ENABLED, sinks_available);
- //g_debug("Sending the initial value of the slider over dbus = %f", start_volume * 100);
return self;
}
diff --git a/src/slider-menu-item.h b/src/slider-menu-item.h
index 48e71ff..c4423e3 100644
--- a/src/slider-menu-item.h
+++ b/src/slider-menu-item.h
@@ -46,6 +46,7 @@ struct _SliderMenuItem {
};
GType slider_menu_item_get_type (void);
+// TODO for now the volume percent param is not being used - remove once init mystery is solved
SliderMenuItem* slider_menu_item_new(gboolean sinks_available, gdouble current_vol);
G_END_DECLS
diff --git a/src/sound-service-dbus.c b/src/sound-service-dbus.c
index 5e22dae..a4c6eda 100644
--- a/src/sound-service-dbus.c
+++ b/src/sound-service-dbus.c
@@ -25,24 +25,34 @@
#include <dbus/dbus-glib.h>
#include "dbus-shared-names.h"
#include "sound-service-dbus.h"
-#include "sound-service-server.h"
#include "common-defs.h"
#include "sound-service-marshal.h"
#include "pulse-manager.h"
+// DBUS methods -
+// TODO - other should be static and moved from the header to here
+static gboolean sound_service_dbus_get_sink_volume(SoundServiceDbus* service, gdouble* volume_percent_input, GError** gerror);
+static gboolean sound_service_dbus_get_sink_mute(SoundServiceDbus* service, gboolean* mute_input, GError** gerror);
+static void sound_service_dbus_set_sink_volume(SoundServiceDbus* service, const guint volume_percent, GError** gerror);
+
+#include "sound-service-server.h"
+
typedef struct _SoundServiceDbusPrivate SoundServiceDbusPrivate;
struct _SoundServiceDbusPrivate
{
DBusGConnection *system_bus;
DBusGConnection *connection;
- GHashTable *sinks_hash;
+ gdouble volume_percent;
+ gboolean mute;
};
/* Signals */
enum {
SINK_INPUT_WHILE_MUTED,
+ SINK_VOLUME_UPDATE,
+ SINK_MUTE_UPDATE,
LAST_SIGNAL
};
@@ -51,12 +61,12 @@ static guint signals[LAST_SIGNAL] = { 0 };
#define SOUND_SERVICE_DBUS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUND_SERVICE_DBUS_TYPE, SoundServiceDbusPrivate))
-
static void sound_service_dbus_class_init (SoundServiceDbusClass *klass);
static void sound_service_dbus_init (SoundServiceDbus *self);
static void sound_service_dbus_dispose (GObject *object);
static void sound_service_dbus_finalize (GObject *object);
+
/* GObject Boilerplate */
G_DEFINE_TYPE (SoundServiceDbus, sound_service_dbus, G_TYPE_OBJECT);
@@ -79,49 +89,27 @@ sound_service_dbus_class_init (SoundServiceDbusClass *klass)
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
- _sound_service_marshal_VOID__INT_BOOLEAN,
- G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_BOOLEAN);
-}
-
-/**
-DBUS Method Callbacks
-TODO do not see the point in this returning a boolean and also needing a sink index since the service needs to be ultimately aware of what sink is chosen.
-**/
-void sound_service_dbus_set_sink_volume(SoundServiceDbus* service, const guint volume_percent, GError** gerror)
-{
- g_debug("in the set sink volume method in the sound service dbus!, with volume_percent of %i", volume_percent);
- set_sink_volume(volume_percent);
-}
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
-GList *
-sound_service_dbus_get_sink_list (SoundServiceDbus *self)
-{
- SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self);
-
- return g_hash_table_get_keys (priv->sinks_hash);
-}
+ signals[SINK_VOLUME_UPDATE] = g_signal_new("sink-volume-update",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__DOUBLE,
+ G_TYPE_NONE, 1, G_TYPE_DOUBLE);
+ signals[SINK_MUTE_UPDATE] = g_signal_new("sink-mute-update",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
-/**
-Utility methods to emit signals from the service into the ether.
-**/
-void sound_service_dbus_sink_input_while_muted(SoundServiceDbus* obj, gint sink_index, gboolean value)
-{
-/* g_assert((num < LAST_SIGNAL) && (num >= 0));*/
- g_debug("Emitting signal: SINK_INPUT_WHILE_MUTED, with sink_index %i and value %i", sink_index, value);
- g_signal_emit(obj,
- signals[SINK_INPUT_WHILE_MUTED],
- 0,
- sink_index,
- value);
}
-void set_pa_sinks_hash(SoundServiceDbus *self, GHashTable *sinks)
-{
- SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self);
- priv->sinks_hash = sinks;
-}
-
static void
sound_service_dbus_init (SoundServiceDbus *self)
{
@@ -130,6 +118,7 @@ sound_service_dbus_init (SoundServiceDbus *self)
priv->system_bus = NULL;
priv->connection = NULL;
+ priv->volume_percent = 0;
/* Get the system bus */
priv->system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
@@ -148,6 +137,7 @@ sound_service_dbus_init (SoundServiceDbus *self)
return;
}
+
static void
sound_service_dbus_dispose (GObject *object)
{
@@ -162,3 +152,69 @@ sound_service_dbus_finalize (GObject *object)
return;
}
+
+/**
+DBUS Method Callbacks
+**/
+static void sound_service_dbus_set_sink_volume(SoundServiceDbus* service, const guint volume_percent, GError** gerror)
+{
+ g_debug("in the set sink volume method in the sound service dbus!, with volume_percent of %i", volume_percent);
+ set_sink_volume(volume_percent);
+}
+
+static gboolean sound_service_dbus_get_sink_volume (SoundServiceDbus *self, gdouble *volume_percent_input, GError** gerror)
+{
+ SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self);
+ g_debug("Get sink volume method in the sound service dbus!, about to send over volume percent of %f", priv->volume_percent);
+ *volume_percent_input = priv->volume_percent;
+ return TRUE;
+}
+
+static gboolean sound_service_dbus_get_sink_mute (SoundServiceDbus *self, gboolean *mute_input, GError** gerror)
+{
+ SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (self);
+ g_debug("Get sink mute - sound service dbus!, about to send over mute_value of %i", priv->mute);
+ *mute_input = priv->mute;
+ return TRUE;
+}
+
+/**
+SIGNALS
+Utility methods to emit signals from the service into the ether.
+**/
+void sound_service_dbus_sink_input_while_muted(SoundServiceDbus* obj, gboolean block_value)
+{
+ g_debug("Emitting signal: SINK_INPUT_WHILE_MUTED, with block_value: %i", block_value);
+ g_signal_emit(obj,
+ signals[SINK_INPUT_WHILE_MUTED],
+ 0,
+ block_value);
+}
+
+void sound_service_dbus_update_sink_volume(SoundServiceDbus* obj, gdouble sink_volume)
+{
+ SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (obj);
+ priv->volume_percent = sink_volume * 100;
+
+ g_debug("Emitting signal: SINK_VOLUME_UPDATE, with sink_volme %f", priv->volume_percent);
+ g_signal_emit(obj,
+ signals[SINK_VOLUME_UPDATE],
+ 0,
+ priv->volume_percent);
+}
+
+void sound_service_dbus_update_sink_mute(SoundServiceDbus* obj, gboolean sink_mute)
+{
+ g_debug("Emitting signal: SINK_MUTE_UPDATE, with sink mute %i", sink_mute);
+
+ SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (obj);
+ priv->mute = sink_mute;
+
+ g_signal_emit(obj,
+ signals[SINK_MUTE_UPDATE],
+ 0,
+ priv->mute);
+}
+
+
+
diff --git a/src/sound-service-dbus.h b/src/sound-service-dbus.h
index eea6d26..ef0d7dd 100644
--- a/src/sound-service-dbus.h
+++ b/src/sound-service-dbus.h
@@ -50,19 +50,16 @@ struct _SoundServiceDbus {
struct _SoundServiceDbusClass {
GObjectClass parent_class;
/* Signals -> outward messages to the DBUS and beyond*/
- void (* sink_input_while_muted) (SoundServiceDbus *self, gint sink_index, gboolean is_muted, gpointer sound_data);
-};
-
+ // TODO - ARE THESE NECESSARY ?
+ //void (* sink_input_while_muted) (SoundServiceDbus *self, gboolean block_value, gpointer sound_data);
+ //void (* sink_volume_update) (SoundServiceDbus *self, gdouble sink_volume, gpointer sound_data);
+};
GType sound_service_dbus_get_type (void) G_GNUC_CONST;
-// Utility methods to get the messages across into the sound-service-dbus
-void sound_service_dbus_sink_input_while_muted (SoundServiceDbus* obj, gint sink_index, gboolean value);
-void set_pa_sinks_hash(SoundServiceDbus *self, GHashTable *sinks);
-
-// DBUS METHODS
-void sound_service_dbus_set_sink_volume(SoundServiceDbus* service, const guint volume_percent, GError** gerror);
-GList *sound_service_dbus_get_sink_list(SoundServiceDbus* service);
-
+// Utility methods to get the SIGNAL messages across into the sound-service-dbus
+void sound_service_dbus_sink_input_while_muted (SoundServiceDbus* obj, gboolean block_value);
+void sound_service_dbus_update_sink_volume(SoundServiceDbus* obj, gdouble sink_volume);
+void sound_service_dbus_update_sink_mute(SoundServiceDbus* obj, gboolean sink_mute);
G_END_DECLS
diff --git a/src/sound-service.c b/src/sound-service.c
index 76975cd..4f76dd1 100644
--- a/src/sound-service.c
+++ b/src/sound-service.c
@@ -5,7 +5,6 @@ Copyright 2010 Canonical Ltd.
Authors:
Conor Curran <conor.curran@canonical.com>
Ted Gould <ted@canonical.com>
- Christoph Korn <c_korn@gmx.de>
Cody Russell <crussell@canonical.com>
This program is free software: you can redistribute it and/or modify it
@@ -40,7 +39,7 @@ static gboolean b_all_muted = FALSE;
static gboolean b_pulse_ready = FALSE;
static gdouble volume_percent = 0.0;
-static void set_global_mute();
+static void set_global_mute_from_ui();
static gboolean idle_routine (gpointer data);
static void rebuild_sound_menu(DbusmenuMenuitem *root, SoundServiceDbus *service);
@@ -74,7 +73,7 @@ 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);
+ g_signal_connect(G_OBJECT(mute_all_menuitem), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(set_global_mute_from_ui), NULL);
//TODO: If no valid sinks are found grey out the item(s)
dbusmenu_menuitem_property_set_bool(mute_all_menuitem, DBUSMENU_MENUITEM_PROP_ENABLED, b_sink_available);
@@ -93,8 +92,14 @@ static void rebuild_sound_menu(DbusmenuMenuitem *root, SoundServiceDbus *service
g_signal_connect(G_OBJECT(settings_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
G_CALLBACK(show_sound_settings_dialog), NULL);
}
+/* 'public' method allowing the server to update the mute UI*/
+void update_mute_ui(gboolean incoming_mute_value)
+{
+ b_all_muted = incoming_mute_value;
+ dbusmenu_menuitem_property_set(mute_all_menuitem, DBUSMENU_MENUITEM_PROP_LABEL, _(b_all_muted == FALSE ? "Mute All" : "Unmute"));
+}
-static void set_global_mute()
+static void set_global_mute_from_ui()
{
b_all_muted = !b_all_muted;
toggle_global_mute(b_all_muted);
@@ -102,8 +107,9 @@ static void set_global_mute()
/* GValue value = {0};*/
/* g_value_init(&value, G_TYPE_DOUBLE);*/
-/* g_value_set_double(&value, 100.0);*/
+/* g_value_set_double(&value, 99.0);*/
/* // Testing*/
+/* g_debug("BUGGY volume update");*/
/* dbusmenu_menuitem_property_set_value(DBUSMENU_MENUITEM(volume_slider_menuitem), DBUSMENU_SLIDER_MENUITEM_PROP_VOLUME, &value);*/
}
@@ -116,9 +122,9 @@ service_shutdown (IndicatorService *service, gpointer user_data)
{
if (mainloop != NULL) {
-
- g_debug("Service shutdown - but commented out for right now");
- close_pulse_activites();
+ g_debug("Service shutdown !");
+ // TODO: uncomment for release !!
+ close_pulse_activites();
g_main_loop_quit(mainloop);
}
return;
@@ -132,11 +138,6 @@ void update_pa_state(gboolean pa_state, gboolean sink_available, gboolean sink_m
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);
- g_debug("About to send over the volume slider");
- GValue value = {0};
- g_value_init(&value, G_TYPE_DOUBLE);
- g_value_set_double(&value, volume_percent * 100);
- dbusmenu_menuitem_property_set_value(DBUSMENU_MENUITEM(volume_slider_menuitem), DBUSMENU_SLIDER_MENUITEM_PROP_VOLUME, &value);
}
@@ -168,6 +169,13 @@ main (int argc, char ** argv)
dbusmenu_server_set_root(server, root_menuitem);
establish_pulse_activities(dbus_interface);
+/* // THIS DOES NOT WORK FROM HERE*/
+/* GValue value = {0};*/
+/* g_value_init(&value, G_TYPE_DOUBLE);*/
+/* g_value_set_double(&value, volume_percent * 100);*/
+/* g_debug("About to send over the volume slider initial value %f", (volume_percent * 100));*/
+/* dbusmenu_menuitem_property_set_value(DBUSMENU_MENUITEM(volume_slider_menuitem), DBUSMENU_SLIDER_MENUITEM_PROP_VOLUME, &value);*/
+
// Run the loop
mainloop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(mainloop);
diff --git a/src/sound-service.h b/src/sound-service.h
index fec52a3..d36ea41 100644
--- a/src/sound-service.h
+++ b/src/sound-service.h
@@ -8,7 +8,6 @@ Copyright 2010 Canonical Ltd.
Authors:
Conor Curran <conor.curran@canonical.com>
Ted Gould <ted@canonical.com>
- Christoph Korn <c_korn@gmx.de>
Cody Russell <crussell@canonical.com>
This program is free software: you can redistribute it and/or modify it
@@ -39,11 +38,10 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include "dbus-shared-names.h"
-
// ENTRY AND EXIT POINTS
void service_shutdown(IndicatorService * service, gpointer user_data);
int main (int argc, char ** argv);
void update_pa_state(gboolean pa_state, gboolean sink_available, gboolean sink_muted, gdouble current_vol);
-
+void update_mute_ui(gboolean incoming_mute_value);
#endif
diff --git a/src/sound-service.xml b/src/sound-service.xml
index 26d83e5..580f0e1 100644
--- a/src/sound-service.xml
+++ b/src/sound-service.xml
@@ -5,14 +5,31 @@
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="sound_service_dbus_set_sink_volume"/>
<arg type='u' name='volume_percent' direction="in"/>
</method>
+ <method name = "GetSinkVolume">
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="sound_service_dbus_get_sink_volume"/>
+ <arg type='d' name='volume_percent_input' direction="out"/>
+ </method>
+
+ <method name = "GetSinkMute">
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="sound_service_dbus_get_sink_mute"/>
+ <arg type='b' name='mute_input' direction="out"/>
+ </method>
<!-- Will need to hook up another signal which monitors for volume change
Our respective UI element should listen to this and therefore will be updated with accurate setting-->
<!-- Triggered when a sink is muted but the input has been sent to that sink -->
<signal name="SinkInputWhileMuted">
- <arg name="sink_index" type="x" direction="out"/>
+ <arg name="block_value" type="b" direction="out"/>
+ </signal>
+
+ <signal name="SinkVolumeUpdate">
+ <arg name="volume_percent" type="u" direction="out"/>
+ </signal>
+
+ <signal name="SinkMuteUpdate">
<arg name="mute_value" type="b" direction="out"/>
</signal>
+
</interface>
</node>