diff options
author | Conor Curran <conor.curran@canonical.com> | 2010-02-10 13:11:00 +0000 |
---|---|---|
committer | Conor Curran <conor.curran@canonical.com> | 2010-02-10 13:11:00 +0000 |
commit | 1b4d886b058dcfc0c0c89631bdeb91209ebfcdda (patch) | |
tree | 515c6778ea438bdf966b5a52b30aaed76e52026d /src/pulse-manager.c | |
parent | 8c992efe8d490c63021bca280c4e2d46f22bca40 (diff) | |
parent | ef8f7d725ef912219e1829d4c22db9abbc00df1a (diff) | |
download | ayatana-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/pulse-manager.c')
-rw-r--r-- | src/pulse-manager.c | 193 |
1 files changed, 132 insertions, 61 deletions
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 |