aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/indicator-sound.c6
-rw-r--r--src/pulse-manager.c149
-rw-r--r--src/pulse-manager.h12
-rw-r--r--src/sound-service-dbus.c12
-rw-r--r--src/sound-service-dbus.h2
-rw-r--r--src/sound-service.xml5
6 files changed, 120 insertions, 66 deletions
diff --git a/src/indicator-sound.c b/src/indicator-sound.c
index 7356e3c..e36c03f 100644
--- a/src/indicator-sound.c
+++ b/src/indicator-sound.c
@@ -60,7 +60,6 @@ struct _IndicatorSoundClass {
struct _IndicatorSound {
IndicatorObject parent;
IndicatorServiceManager *service;
- guint chosen_sink;
};
// GObject Boiler plate
GType indicator_sound_get_type (void);
@@ -115,8 +114,6 @@ static void indicator_sound_init (IndicatorSound *self)
{
/* Set good defaults */
self->service = NULL;
- /* For now we stick to 0 for defaults*/
- self->chosen_sink = 0;
/* Now let's fire these guys up. */
self->service = indicator_service_manager_new_version(INDICATOR_SOUND_DBUS_NAME, INDICATOR_SOUND_DBUS_VERSION);
@@ -221,7 +218,6 @@ static GtkWidget* get_slider(IndicatorObject * io)
static gboolean slider_value_changed_event_cb(GtkRange *range, GtkScrollType scroll, double value, gpointer user_data)
{
- IndicatorSound* sound = INDICATOR_SOUND(user_data);
- org_ayatana_indicator_sound_set_sink_volume(sound_dbus_proxy, sound->chosen_sink, value, NULL);
+ org_ayatana_indicator_sound_set_sink_volume(sound_dbus_proxy, value, NULL);
return FALSE;
}
diff --git a/src/pulse-manager.c b/src/pulse-manager.c
index 985b14b..4b52295 100644
--- a/src/pulse-manager.c
+++ b/src/pulse-manager.c
@@ -8,7 +8,8 @@
static GHashTable *sink_hash = NULL;
static SoundServiceDbus *dbus_service = NULL;
-static gint DEFAULT_SINK_INDEX = 0;
+// Until we find a satisfactory default sink this index should remain < 0
+static gint DEFAULT_SINK_INDEX = -1;
// PA related
static pa_context *pulse_context = NULL;
static pa_glib_mainloop *pa_main_loop = NULL;
@@ -16,15 +17,24 @@ static void context_state_callback(pa_context *c, void *userdata);
static void pulse_sink_info_callback(pa_context *c, const pa_sink_info *sink_info, int eol, void *userdata);
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 pulse_default_sink_set_volume_callback(pa_context *c, const pa_sink_info *info, int eol, void *userdata);
+static void destroy_sink_info(void *value);
-pa_context* get_context(void)
-{
- return pulse_context;
-}
-void set_sink_volume(gint sink_index, gint percent)
+void set_sink_volume(guint percent)
{
- g_debug("in the pulse manager:set_sink_volume with index %i and percent %i", sink_index, percent);
+ g_debug("in the pulse manager:set_sink_volume with percent %i", percent);
+ pa_volume_t new_volume = (pa_volume_t) ((percent * PA_VOLUME_NORM) / 100);
+ if(DEFAULT_SINK_INDEX < 0)
+ {
+ g_warning("We have no default sink !!! - returning after doing nothing");
+ return;
+ }
+ pa_context_get_sink_info_by_index(pulse_context, DEFAULT_SINK_INDEX, pulse_default_sink_set_volume_callback, &new_volume);
+/* //pa&s->volume*/
+/* pa_cvolume dev_vol = s->volume;*/
+/* pa_cvolume_set(&dev_vol, s->volume.channels, volume);*/
}
void establish_pulse_activities(SoundServiceDbus *service)
@@ -34,7 +44,8 @@ void establish_pulse_activities(SoundServiceDbus *service)
g_assert(pa_main_loop);
pulse_context = pa_context_new(pa_glib_mainloop_get_api(pa_main_loop), "ayatana.indicator.sound");
g_assert(pulse_context);
- sink_hash = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
+
+ sink_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, destroy_sink_info);
// Establish event callback registration
pa_context_set_state_callback(pulse_context, context_state_callback, NULL);
pa_context_connect(pulse_context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL);
@@ -65,27 +76,31 @@ void toggle_global_mute(gboolean mute_value)
g_debug("in the pulse manager: toggle global mute value %i", mute_value);
}
+static void destroy_sink_info(void *value)
+{
+ sink_info *sink = (sink_info*)value;
+ g_free(sink->name);
+ g_free(sink->description);
+ g_free(sink->icon_name);
+ g_free(sink);
+}
static void test_hash(){
guint size = 0;
size = g_hash_table_size(sink_hash);
g_debug("Size of hash = %i", size);
- gint *key;
- key = g_new(gint, 1);
- *key = 0;
- sink_info *s = g_hash_table_lookup(sink_hash, key);
+ sink_info *s = g_hash_table_lookup(sink_hash, GINT_TO_POINTER(2));
g_debug("and the name of our sink is %s", s->name);
}
+/**
+TODO do not ship with this method like this - assumes sink index"
+**/
static gboolean sink_available()
{
if (g_hash_table_size(sink_hash) < 1)
return FALSE;
- int *key;
- key = g_new(gint, 1);
- *key = 0;
- sink_info *s = g_hash_table_lookup(sink_hash, key);
- //int value = g_strcasecmp(s->name, " auto_null ");
+ sink_info *s = g_hash_table_lookup(sink_hash, GINT_TO_POINTER(2));
// TODO more testing is required for the case of having no available sink
return ((g_strcasecmp(s->name, " auto_null ") != 0) && s->active_port == TRUE);
}
@@ -98,11 +113,8 @@ static gboolean sink_is_muted(gint sink_index)
sink_index = DEFAULT_SINK_INDEX;
if (g_hash_table_size(sink_hash) < 1)
return FALSE;
- int *key;
- key = g_new(gint, 1);
- *key = sink_index;
// TODO ensure hash has a key with this value!
- sink_info *s = g_hash_table_lookup(sink_hash, key);
+ sink_info *s = g_hash_table_lookup(sink_hash, GINT_TO_POINTER(sink_index));
return s->mute;
}
@@ -125,17 +137,21 @@ static void check_sink_input_while_muted_event(gint sink_index)
/*}*/
+//NOT quite sure if the first fails and second fail will there be a memory leak?
static void gather_pulse_information(pa_context *c, void *userdata)
{
pa_operation *operation;
-
- if (!(operation = pa_context_get_sink_info_list(c, pulse_sink_info_callback, NULL)))
+ if(!(operation = pa_context_get_server_info(c, pulse_server_info_callback, userdata)))
{
- g_warning("pa_context_get_sink_info_list() failed");
- return;
+ g_warning("pa_context_get_server_info failed");
+ if (!(operation = pa_context_get_sink_info_list(c, pulse_sink_info_callback, NULL)))
+ {
+ g_warning("pa_context_get_sink_info_list() failed - cannot fetch server or sink info - leaving . . .");
+ return;
+ }
}
pa_operation_unref(operation);
-
+ return;
}
@@ -155,8 +171,10 @@ static void pulse_sink_info_callback(pa_context *c, const pa_sink_info *sink, in
{
if (eol > 0) {
test_hash();
+ DEFAULT_SINK_INDEX = (DEFAULT_SINK_INDEX < 0) ? 0 : DEFAULT_SINK_INDEX;
update_pa_state(TRUE, sink_available(), sink_is_muted(-1));
-
+ g_debug("default sink index : %d", DEFAULT_SINK_INDEX);
+
// TODO follow this pattern for all other async call-backs involving lists - safest/most accurate approach.
if (pa_context_errno(c) == PA_ERR_NOENTITY)
return;
@@ -164,24 +182,46 @@ static void pulse_sink_info_callback(pa_context *c, const pa_sink_info *sink, in
return;
}
else{
- gint *key;
- key = g_new(gint, 1);
- *key = sink->index;
sink_info *value;
- value = g_new(sink_info, 1);
+ value = g_new0(sink_info, 1);
value->index = value->device_index = sink->index;
- value->name = sink->name;
- value->description = sink->description;
- value->icon_name = pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_ICON_NAME);
+ value->name = g_strdup(sink->name);
+ value->description = g_strdup(sink->description);
+ value->icon_name = g_strdup(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_ICON_NAME));
value->active_port = (sink->active_port != NULL);
value->mute = !!sink->mute;
- g_hash_table_insert(sink_hash, key, value);
- // VOLUME focus tmrw.
- //value->volume = sink->volume;
- //value->channel_map = sink->channel_map;
+/* value->volume = sink->volume;*/
+/* value->channel_map = sink->channel_map;*/
+ g_hash_table_insert(sink_hash, GINT_TO_POINTER(sink->index), value);
}
}
+/**
+Will attempt to set the volume on the default sink - should not be called if there is no default sink
+**/
+static void pulse_default_sink_set_volume_callback(pa_context *c, const pa_sink_info *info, int eol, void *userdata)
+{
+ pa_volume_t *new_volume = (pa_volume_t*)userdata;
+ pa_cvolume dev_vol = info->volume;
+ g_debug("about to try and set the volume on the default sink");
+ pa_cvolume_set(&dev_vol, info->volume.channels, *new_volume);
+ g_debug("about to try and set the volume on the default sink");
+}
+static void pulse_default_sink_info_callback(pa_context *c, const pa_sink_info *info, int eol, void *userdata)
+{
+ g_debug("default sink info callback");
+ if (eol > 0) {
+ if (pa_context_errno(c) == PA_ERR_NOENTITY)
+ return;
+ g_warning("Default Sink info callback failure");
+ return;
+ }
+ 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));
+ }
+}
static void pulse_sink_input_info_callback(pa_context *c, const pa_sink_input_info *info, int eol, void *userdata){
if (eol > 0) {
@@ -202,6 +242,35 @@ static void pulse_sink_input_info_callback(pa_context *c, const pa_sink_input_in
}
}
+static void pulse_server_info_callback(pa_context *c, const pa_server_info *info, void *userdata)
+{
+ g_debug("server info callback");
+ pa_operation *operation;
+ if (info == NULL)
+ {
+ g_warning("No server - get the hell out of here");
+ return;
+ }
+
+ if(info->default_sink_name != NULL)
+ {
+ if (!(operation = pa_context_get_sink_info_by_name(c, info->default_sink_name, pulse_default_sink_info_callback, userdata)))
+ {
+ g_warning("pa_context_get_sink_info_by_name() failed");
+ }
+ else{
+ pa_operation_unref(operation);
+ return;
+ }
+ }
+ if (!(operation = pa_context_get_sink_info_list(c, pulse_sink_info_callback, NULL)))
+ {
+ g_warning("pa_context_get_sink_info_list() failed");
+ return;
+ }
+ 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) {
case PA_SUBSCRIPTION_EVENT_SINK:
@@ -210,9 +279,7 @@ static void subscribed_events_callback(pa_context *c, enum pa_subscription_event
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.
- //g_debug("Subscribed_events_callback - type = sink input and index = %i", index);
- //g_debug("Sink input info query just about to happen");
- pa_operation_unref(pa_context_get_sink_input_info(c, index, pulse_sink_input_info_callback, userdata));
+ pa_operation_unref(pa_context_get_sink_input_info(c, index, pulse_sink_input_info_callback, userdata));
break;
}
}
diff --git a/src/pulse-manager.h b/src/pulse-manager.h
index 0567b5d..39ae41c 100644
--- a/src/pulse-manager.h
+++ b/src/pulse-manager.h
@@ -30,13 +30,13 @@
typedef struct {
- const gchar* name;
- const gchar* description;
- const gchar* icon_name;
+ gchar* name;
+ gchar* description;
+ gchar* icon_name;
gint index;
gint device_index;
- pa_cvolume volume;
- pa_channel_map channel_map;
+// pa_cvolume volume;
+// pa_channel_map channel_map;
gboolean mute;
gboolean active_port;
} sink_info;
@@ -45,7 +45,7 @@ typedef struct {
//void set_volume(gint sink_index, gint volume_percent);
pa_context* get_context(void);
void establish_pulse_activities(SoundServiceDbus *service);
-void set_sink_volume(gint sink_index, gint percent);
+void set_sink_volume(guint percent);
void toggle_global_mute(gboolean mute_value);
diff --git a/src/sound-service-dbus.c b/src/sound-service-dbus.c
index 58030cc..5e22dae 100644
--- a/src/sound-service-dbus.c
+++ b/src/sound-service-dbus.c
@@ -85,16 +85,12 @@ sound_service_dbus_class_init (SoundServiceDbusClass *klass)
/**
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.
**/
-gboolean sound_service_dbus_set_sink_volume(SoundServiceDbus* service, const guint sink_index, const guint volume_percent, GError** gerror)
+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 on sink %i", volume_percent, sink_index);
-
-/* if (!IS_SOUND_SERVICE_DBUS(service)) {*/
-/* g_warning("NO BAD EVIL!");*/
-/* return FALSE;*/
-/* }*/
- return TRUE;
+ 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);
}
GList *
diff --git a/src/sound-service-dbus.h b/src/sound-service-dbus.h
index bf7f10a..eea6d26 100644
--- a/src/sound-service-dbus.h
+++ b/src/sound-service-dbus.h
@@ -60,7 +60,7 @@ void sound_service_dbus_sink_input_while_muted (SoundServiceDbus* obj, gint sink
void set_pa_sinks_hash(SoundServiceDbus *self, GHashTable *sinks);
// DBUS METHODS
-gboolean sound_service_dbus_set_sink_volume(SoundServiceDbus* service, const guint sink_index, const guint volume_percent, GError** gerror);
+void sound_service_dbus_set_sink_volume(SoundServiceDbus* service, const guint volume_percent, GError** gerror);
GList *sound_service_dbus_get_sink_list(SoundServiceDbus* service);
diff --git a/src/sound-service.xml b/src/sound-service.xml
index b4a3d6a..26d83e5 100644
--- a/src/sound-service.xml
+++ b/src/sound-service.xml
@@ -4,11 +4,6 @@
<method name = "SetSinkVolume">
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="sound_service_dbus_set_sink_volume"/>
<arg type='u' name='volume_percent' direction="in"/>
- <arg type='u' name='sink_to_set' direction="in"/>
- </method>
- <method name="GetSinkList">
- <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="sound_service_dbus_get_sink_list"/>
- <arg name="sinks" direction="out" type="au"/>
</method>
<!-- Will need to hook up another signal which monitors for volume change