aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac6
-rw-r--r--debian/changelog14
-rw-r--r--debian/control2
-rw-r--r--src/indicator-sound.c186
-rw-r--r--src/pulse-manager.c155
-rw-r--r--src/sound-service-dbus.c2
-rw-r--r--src/sound-service.c41
7 files changed, 269 insertions, 137 deletions
diff --git a/configure.ac b/configure.ac
index 7c308e2..48022e2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@ AC_INIT(src/indicator-sound.c)
AC_PREREQ(2.53)
AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE(indicator-sound, 0.1.0)
+AM_INIT_AUTOMAKE(indicator-sound, 0.1.1)
AM_MAINTAINER_MODE
@@ -27,10 +27,10 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
GTK_REQUIRED_VERSION=2.12
INDICATOR_REQUIRED_VERSION=0.3.0
-DBUSMENUGTK_REQUIRED_VERSION=0.2.0
+DBUSMENUGTK_REQUIRED_VERSION=0.2.2
POLKIT_REQUIRED_VERSION=0.92
PULSE_AUDIO_REQUIRED_VERSION=0.9.19
-INDICATOR_DISPLAY_OBJECTS=0.1.0
+INDICATOR_DISPLAY_OBJECTS=0.1.2
PKG_CHECK_MODULES(APPLET, gtk+-2.0 >= $GTK_REQUIRED_VERSION
indicator >= $INDICATOR_REQUIRED_VERSION
diff --git a/debian/changelog b/debian/changelog
index 16d3797..f1c5e0a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,17 @@
+indicator-sound (0.1.1-0ubuntu1) lucid; urgency=low
+
+ * New upstream version
+ - resolve the UI keyboard controls which were lacking (lp: #521088)
+ - the volume control should now be far smoother
+ - included is the ability to dynamically swap output devices
+ using gnome volume control
+ - use of new icons from the new humanity theme.
+ - update volume slider in the right direction on mouse scroll (lp: #521090)
+ * debian/control:
+ - updated ido requirement
+
+ -- Sebastien Bacher <seb128@ubuntu.com> Thu, 18 Feb 2010 17:46:11 +0100
+
indicator-sound (0.1.0-0ubuntu2) lucid; urgency=low
* Backport trunk change to fix audiosink detection and volume controls
diff --git a/debian/control b/debian/control
index 7754b96..9a93e4a 100644
--- a/debian/control
+++ b/debian/control
@@ -14,7 +14,7 @@ Build-Depends: debhelper (>= 7),
libindicator-dev (>= 0.3.0),
libpulse-dev (>= 0.9.18),
libpulse-mainloop-glib0 (>= 0.9.18),
- libido-0.1-dev (>= 0.1.1),
+ libido-0.1-dev (>= 0.1.2),
libgconf2-dev
Standards-Version: 3.8.4
Homepage: https://launchpad.net/indicator-sound
diff --git a/src/indicator-sound.c b/src/indicator-sound.c
index a8bbeea..8e79db6 100644
--- a/src/indicator-sound.c
+++ b/src/indicator-sound.c
@@ -20,10 +20,11 @@ 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/>.
*/
-
+#include <math.h>
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
#include <libdbusmenu-gtk/menu.h>
#include <libido/idoscalemenuitem.h>
@@ -81,8 +82,10 @@ static GtkMenu * get_menu (IndicatorObject * io);
static GtkWidget *volume_slider = 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 user_change_value_event_cb(GtkRange *range, GtkScrollType scroll_type, gdouble input_value, gpointer user_data);
+// Alternative callback mechanism, may use this again once ido is updated.
+/*static gboolean user_change_value_event_cb(GtkRange *range, GtkScrollType scroll_type, gdouble input_value, gpointer user_data);*/
static gboolean value_changed_event_cb(GtkRange *range, gpointer user_data);
+static gboolean key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer data);
// DBUS communication
static DBusGProxy *sound_dbus_proxy = NULL;
@@ -97,7 +100,6 @@ static void fetch_mute_value_from_dbus();
static void prepare_state_machine();
static void determine_state_from_volume(gdouble volume_percent);
static void update_state(const gint state);
-/*static void revert_state();*/
static const gint STATE_MUTED = 0;
static const gint STATE_ZERO = 1;
static const gint STATE_LOW = 2;
@@ -146,15 +148,6 @@ static void indicator_sound_init (IndicatorSound *self)
}
-/*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.
*/
@@ -162,14 +155,13 @@ 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();
+ g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_MUTED), g_strdup("audio-volume-muted-panel"));
+ g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_ZERO), g_strdup("audio-volume-zero-panel"));
+ g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_LOW), g_strdup("audio-volume-low-panel"));
+ g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_MEDIUM), g_strdup("audio-volume-medium-panel"));
+ g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_HIGH), g_strdup("audio-volume-high-panel"));
+ g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_MUTED_WHILE_INPUT), g_strdup("audio-volume-muted-blocking-panel"));
+ g_hash_table_insert(volume_states, GINT_TO_POINTER(STATE_SINKS_NONE), g_strdup("audio-output-none-panel"));
}
static void
@@ -257,9 +249,12 @@ static void catch_signal_sink_input_while_muted(DBusGProxy * proxy, gboolean blo
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);
GtkRange *range = (GtkRange*)slider;
+
+ // DEBUG
+ gdouble current_value = gtk_range_get_value(range);
+ g_debug("SIGNAL- update sink volume - current_value : %f and new value : %f", current_value, volume_percent);
gtk_range_set_value(range, volume_percent);
determine_state_from_volume(volume_percent);
}
@@ -270,9 +265,10 @@ static void catch_signal_sink_mute_update(DBusGProxy *proxy, gboolean mute_value
//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);
}
+ g_debug("signal caught - sink mute update with mute value: %i", mute_value);
+ gtk_widget_set_sensitive(volume_slider, !mute_value);
}
@@ -315,30 +311,22 @@ get_icon (IndicatorObject * io)
static void update_state(const gint state)
{
- g_debug("update state beginning - previous_state = %i", previous_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);
+/* 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);
+/* g_debug("determine_state_from_volume - previous_state = %i", previous_state);*/
+
gint state = previous_state;
if (volume_percent < 30.0 && volume_percent > 0){
state = STATE_LOW;
@@ -366,38 +354,50 @@ get_menu (IndicatorObject * io)
DbusmenuGtkClient *client = dbusmenu_gtkmenu_get_client(menu);
dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_SLIDER_MENUITEM_TYPE, new_slider_item);
+ // register Key-press listening on the menu widget as the slider does not allow this.
+ g_signal_connect(menu, "key-press-event", G_CALLBACK(key_press_cb), NULL);
+
return GTK_MENU(menu);
}
+/**
+new_slider_item:
+Create a new dBusMenu Slider item, register the
+**/
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", initial_volume_percent, 0, 100, 0.5);
+ g_object_set(volume_slider, "reverse-scroll-events", TRUE, NULL);
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);
+ // register slider changes listening on the range
GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider);
- g_signal_connect(slider, "change-value", G_CALLBACK(user_change_value_event_cb), newitem);
g_signal_connect(slider, "value-changed", G_CALLBACK(value_changed_event_cb), newitem);
+ // alternative callback mechanism which i could use again at some point.
+/* g_signal_connect(slider, "change-value", G_CALLBACK(user_change_value_event_cb), newitem); */
+ // Set images on the ido
primary_image = ido_scale_menu_item_get_primary_image((IdoScaleMenuItem*)volume_slider);
gtk_image_set_from_icon_name(GTK_IMAGE(primary_image), g_hash_table_lookup(volume_states, GINT_TO_POINTER(STATE_ZERO)), GTK_ICON_SIZE_MENU);
GtkWidget* secondary_image = ido_scale_menu_item_get_secondary_image((IdoScaleMenuItem*)volume_slider);
gtk_image_set_from_icon_name(GTK_IMAGE(secondary_image), g_hash_table_lookup(volume_states, GINT_TO_POINTER(STATE_HIGH)), GTK_ICON_SIZE_MENU);
-/* GtkRange* range = (GtkRange*)slider; */
-/* gtk_range_set_value(range, initial_volume_percent); */
-
gtk_widget_show_all(volume_slider);
+
return TRUE;
}
-/* Whenever we have a property change on a DbusmenuMenuitem
- we need to be responsive to that. */
+/**
+slider_prop_change_cb:
+Whenever we have a property change on a DbusmenuMenuitem this will be called.
+**/
static void slider_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GValue * value, GtkWidget *widget)
{
g_debug("slider_prop_change_cb - dodgy updater ");
@@ -409,35 +409,95 @@ static void slider_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GValue *
}
/**
-This callback will get triggered irregardless of whether its a user change or a programmatic change
-Our usecase for this particular callback is only interested if the slider is changed by the user hitting either icon
-which will result in a programmatic value change of 0 or 100 (work around).
+value_changed_event_cb:
+This callback will get triggered irregardless of whether its a user change or a programmatic change.
**/
static gboolean value_changed_event_cb(GtkRange *range, gpointer user_data)
{
- gdouble current_value = gtk_range_get_value(range);
- if(current_value == 0 || current_value == 100)
- {
- DbusmenuMenuitem *item = (DbusmenuMenuitem*)user_data;
- GValue value = {0};
- g_value_init(&value, G_TYPE_DOUBLE);
- g_value_set_double(&value, current_value);
- g_debug("Value changed listener - = %f", current_value);
- dbusmenu_menuitem_handle_event (item, "slider_change", &value, 0);
- }
+ gdouble current_value = CLAMP(gtk_range_get_value(range), 0, 100);
+ DbusmenuMenuitem *item = (DbusmenuMenuitem*)user_data;
+ GValue value = {0};
+ g_value_init(&value, G_TYPE_DOUBLE);
+ g_value_set_double(&value, current_value);
+ g_debug("Value changed callback - = %f", current_value);
+ dbusmenu_menuitem_handle_event (item, "slider_change", &value, 0);
+ // This is not ideal in that the icon ui will update on ui actions and not on actual service feedback.
+ // but necessary for now as the server does not send volume update information if the source of change was this ui.
+ determine_state_from_volume(current_value);
return FALSE;
}
-static gboolean user_change_value_event_cb(GtkRange *range, GtkScrollType scroll_type, gdouble input_value, gpointer user_data)
+/**
+key_press_cb:
+**/
+static gboolean key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer data)
{
- 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;
-}
+ if (current_state == STATE_MUTED)
+ return FALSE;
+
+ GtkWidget* slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)volume_slider);
+ GtkRange* range = (GtkRange*)slider;
+ gdouble current_value = gtk_range_get_value(range);
+ gdouble new_value = current_value;
+ const gdouble five_percent = 5;
+
+ switch(event->keyval)
+ {
+ case GDK_Right:
+ if(event->state & GDK_CONTROL_MASK)
+ {
+ new_value = 100;
+ }
+ else
+ {
+ new_value = current_value + five_percent;
+ }
+ break;
+ case GDK_Left:
+ if(event->state & GDK_CONTROL_MASK)
+ {
+ new_value = 0;
+ }
+ else
+ {
+ new_value = current_value - five_percent;
+ }
+ break;
+ case GDK_plus:
+ new_value = current_value + five_percent;
+ break;
+ case GDK_minus:
+ new_value = current_value - five_percent;
+ break;
+ default:
+ break;
+ }
+
+ new_value = CLAMP(new_value, 0, 100);
+ if(new_value != current_value)
+ {
+ g_debug("Attempting to set the range from the key listener to %f", new_value);
+ gtk_range_set_value(range, new_value);
+ }
+ return FALSE;
+}
+
+/**
+This callback should only be called when the user actually drags the slider.
+Turned off for now in favour of the non descriminating value-changed call back.
+Once the grabbing listener is implemented on the slider may revert to using this.
+Its another tool for filtering unwanted volume change updates.
+**/
+/*static gboolean user_change_value_event_cb(GtkRange *range, GtkScrollType scroll_type, gdouble input_value, gpointer user_data)*/
+/*{*/
+/* 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 aa3481a..9b9d7cd 100644
--- a/src/pulse-manager.c
+++ b/src/pulse-manager.c
@@ -43,10 +43,16 @@ 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 pulse_source_info_callback(pa_context *c, const pa_source_info *i, int eol, void *userdata);
static void destroy_sink_info(void *value);
static gboolean determine_sink_availability();
+/**
+Refactoring notes
+Push all UI updates out through update PA state in the service.
+**/
+
/*
Entry point
*/
@@ -86,16 +92,6 @@ 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); */
-
-/*}*/
-
/*
Controllers & Utilities
*/
@@ -158,15 +154,22 @@ static gdouble get_default_sink_volume()
return 0;
sink_info *s = g_hash_table_lookup(sink_hash, GINT_TO_POINTER(DEFAULT_SINK_INDEX));
pa_volume_t vol = pa_cvolume_avg(&s->volume);
- gdouble value = pa_sw_volume_to_linear(vol);
- g_debug("software volume = %f", value);
- return value;
+ gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM;
+ g_debug("software volume = %f", volume_percent);
+ return volume_percent;
}
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));
+ if(GPOINTER_TO_INT(user_data) == 1){
+ sound_service_dbus_update_sink_mute(dbus_service, TRUE);
+ }
+ else{
+ sound_service_dbus_update_sink_volume(dbus_service, get_default_sink_volume());
+ }
+
g_debug("in the pulse manager: mute each sink %i", GPOINTER_TO_INT(user_data));
}
@@ -189,19 +192,17 @@ void set_sink_volume(gdouble percent)
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_volume_t new_volume = (pa_volume_t) ((percent * PA_VOLUME_NORM) / 100);
+ g_debug("new_volume double check :%f", pa_sw_volume_to_linear(new_volume));
+ g_debug("new volume calculated :%f", (gdouble)new_volume);
+ pa_cvolume dev_vol;
pa_cvolume_set(&dev_vol, s->volume.channels, new_volume);
-
+ s->volume = dev_vol;
pa_operation_unref(pa_context_set_sink_volume_by_index(pulse_context, DEFAULT_SINK_INDEX, &dev_vol, NULL, NULL));
+
}
@@ -245,9 +246,6 @@ static void pulse_sink_info_callback(pa_context *c, const pa_sink_info *sink, in
if(device_available == TRUE)
{
update_pa_state(TRUE, device_available, default_sink_is_muted(), get_default_sink_volume());
- 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
@@ -284,7 +282,17 @@ static void pulse_default_sink_info_callback(pa_context *c, const pa_sink_info *
else{
DEFAULT_SINK_INDEX = info->index;
g_debug("Just set the default sink index to %i", DEFAULT_SINK_INDEX);
- pa_operation_unref(pa_context_get_sink_info_list(c, pulse_sink_info_callback, NULL));
+ GList *keys = g_hash_table_get_keys(sink_hash);
+ gint position = g_list_index(keys, GINT_TO_POINTER(info->index));
+ // Only update sink-list if the index is not in our already fetched list.
+ if(position < 0)
+ {
+ pa_operation_unref(pa_context_get_sink_info_list(c, pulse_sink_info_callback, NULL));
+ }
+ else
+ {
+ update_pa_state(TRUE, determine_sink_availability(), default_sink_is_muted(), get_default_sink_volume());
+ }
}
}
@@ -321,30 +329,39 @@ static void update_sink_info(pa_context *c, const pa_sink_info *info, int eol, v
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;
+ gboolean volume_changed = (pa_cvolume_equal(&info->volume, &s->volume) == 0);
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);
+ if (volume_changed == TRUE && s->mute == FALSE)
+ {
+ pa_volume_t vol = pa_cvolume_avg(&s->volume);
+ gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM;
+ g_debug("Updating volume from PA manager with volume = %f", volume_percent);
+ sound_service_dbus_update_sink_volume(dbus_service, volume_percent);
+ }
- update_mute_ui(s->mute);
+ if (mute_changed == TRUE)
+ {
+ g_debug("Updating Mute from PA manager with mute = %i", s->mute);
+ sound_service_dbus_update_sink_mute(dbus_service, s->mute);
+ update_mute_ui(s->mute);
+ if(s->mute == FALSE){
+ pa_volume_t vol = pa_cvolume_avg(&s->volume);
+ gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM;
+ g_debug("Updating volume from PA manager with volume = %f", volume_percent);
+ sound_service_dbus_update_sink_volume(dbus_service, volume_percent);
+ }
+ }
}
}
else
@@ -389,24 +406,64 @@ static void pulse_server_info_callback(pa_context *c, const pa_server_info *info
pa_operation_unref(operation);
}
-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) {
+static void pulse_source_info_callback(pa_context *c, const pa_source_info *i, int eol, void *userdata)
+{
+ g_debug("pulse source info callback");
+}
+
+
+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:
- 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 {
+ g_debug("PA_SUBSCRIPTION_EVENT_SINK event triggered");
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE)
+ {
+ //TODO handle the remove event => if its our default sink - update date 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
- // If a playback client is paused and then resumed this will NOT trigger this event.
- pa_operation_unref(pa_context_get_sink_input_info(c, index, pulse_sink_input_info_callback, userdata));
- break;
+ g_debug("PA_SUBSCRIPTION_EVENT_SINK_INPUT event triggered!!");
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE)
+ {
+ //TODO handle the remove event
+ }
+ else
+ {
+ pa_operation_unref(pa_context_get_sink_input_info(c, index, pulse_sink_input_info_callback, userdata));
+ }
+ break;
+ case PA_SUBSCRIPTION_EVENT_SOURCE:
+ g_debug("PA_SUBSCRIPTION_EVENT_SOURCE of some description ???");
+
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE)
+ {
+ //TODO handle the remove event
+ }
+ else
+ {
+ pa_operation *o;
+ if (!(o = pa_context_get_source_info_by_index(c, index, pulse_source_info_callback, userdata))) {
+ g_warning("pa_context_get_source_info_by_index() failed");
+ return;
+ }
+ pa_operation_unref(o);
+ }
+ break;
case PA_SUBSCRIPTION_EVENT_SERVER:
- if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_SINK ) {
- g_debug("server change of some sink type ???");
+ g_debug("PA_SUBSCRIPTION_EVENT_SERVER change of some description ???");
+ pa_operation *o;
+ if(!(o = pa_context_get_server_info(c, pulse_server_info_callback, userdata)))
+ {
+ g_warning("pa_context_get_server_info() failed");
+ return;
}
+ pa_operation_unref(o);
+ break;
}
}
diff --git a/src/sound-service-dbus.c b/src/sound-service-dbus.c
index a4c6eda..99a9d34 100644
--- a/src/sound-service-dbus.c
+++ b/src/sound-service-dbus.c
@@ -194,7 +194,7 @@ void sound_service_dbus_sink_input_while_muted(SoundServiceDbus* obj, gboolean
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;
+ priv->volume_percent = sink_volume;
g_debug("Emitting signal: SINK_VOLUME_UPDATE, with sink_volme %f", priv->volume_percent);
g_signal_emit(obj,
diff --git a/src/sound-service.c b/src/sound-service.c
index d5c4eae..62f6bc6 100644
--- a/src/sound-service.c
+++ b/src/sound-service.c
@@ -74,7 +74,6 @@ static void rebuild_sound_menu(DbusmenuMenuitem *root, SoundServiceDbus *service
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_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);
// Slider
@@ -92,25 +91,29 @@ 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*/
+
+/**
+update_mute_ui:
+'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"));
+ dbusmenu_menuitem_property_set(mute_all_menuitem,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ _(b_all_muted == FALSE ? "Mute All" : "Unmute"));
}
-
+/**
+set_global_mute_from_ui:
+Callback for the dbusmenuitem button
+**/
static void set_global_mute_from_ui()
{
b_all_muted = !b_all_muted;
toggle_global_mute(b_all_muted);
- dbusmenu_menuitem_property_set(mute_all_menuitem, DBUSMENU_MENUITEM_PROP_LABEL, _(b_all_muted == FALSE ? "Mute All" : "Unmute"));
-
-/* GValue value = {0};*/
-/* g_value_init(&value, G_TYPE_DOUBLE);*/
-/* 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);*/
+ dbusmenu_menuitem_property_set(mute_all_menuitem,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ _(b_all_muted == FALSE ? "Mute All" : "Unmute"));
}
@@ -137,7 +140,12 @@ void update_pa_state(gboolean pa_state, gboolean sink_available, gboolean sink_m
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);
+ sound_service_dbus_update_sink_volume(dbus_interface, percent);
+ sound_service_dbus_update_sink_mute(dbus_interface, sink_muted);
+
+ // Only rebuild the menu on start up...
+ if(volume_slider_menuitem == NULL)
+ rebuild_sound_menu(root_menuitem, dbus_interface);
}
@@ -169,13 +177,6 @@ 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);