From c1fdbb5237dd04d6508fafc7d4af67645d4c66c5 Mon Sep 17 00:00:00 2001 From: Conor Curran Date: Thu, 17 Feb 2011 15:17:31 +0000 Subject: back end plugged together for proof of concept --- src/active-sink.c | 28 +++++++++++++ src/active-sink.h | 9 ++++- src/pulseaudio-mgr.c | 99 ++++++++++++++++++++++++++++++++++++---------- src/voip-input-menu-item.c | 62 ++++++++++++++++++++--------- src/voip-input-menu-item.h | 8 ++-- 5 files changed, 162 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/active-sink.c b/src/active-sink.c index 6b0063d..4cf8dc0 100644 --- a/src/active-sink.c +++ b/src/active-sink.c @@ -87,6 +87,21 @@ active_sink_init (ActiveSink *self) slider_menu_item_enable (priv->volume_slider_menuitem, FALSE); } +void +active_sink_activate_voip_item (ActiveSink* self) +{ + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); + voip_input_menu_item_enable (priv->voip_input_menu_item, TRUE); +} + +void +active_sink_deactivate_voip_source (ActiveSink* self) +{ + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); + voip_input_menu_item_enable (priv->voip_input_menu_item, FALSE); +} + + static void active_sink_dispose (GObject *object) { @@ -286,7 +301,20 @@ void active_sink_update_voip_input_source (ActiveSink* self, const pa_source_info* update) { ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); + voip_input_menu_item_update (priv->voip_input_menu_item, update); +} +gboolean +active_sink_is_voip_source_populated (ActiveSink* self) +{ + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); + return voip_input_menu_item_is_populated (priv->voip_input_menu_item); +} + +gint active_sink_get_source_index (ActiveSink* self) +{ + ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self); + return voip_input_menu_item_get_index (priv->voip_input_menu_item); } ActiveSink* diff --git a/src/active-sink.h b/src/active-sink.h index 6b13058..5c6b31a 100644 --- a/src/active-sink.h +++ b/src/active-sink.h @@ -52,16 +52,21 @@ GType active_sink_get_type (void) G_GNUC_CONST; void active_sink_populate (ActiveSink* sink, const pa_sink_info* update); void active_sink_update (ActiveSink* sink, const pa_sink_info* update); -void active_sink_update_voip_input (ActiveSink* sink, const pa_source_info* update); +void active_sink_update_voip_input_source (ActiveSink* sink, const pa_source_info* update); +void active_sink_activate_voip_item (ActiveSink* sink); +gboolean active_sink_is_voip_source_populated (ActiveSink* sink); gboolean active_sink_is_populated (ActiveSink* sink); + void active_sink_determine_blocking_state (ActiveSink* self); gint active_sink_get_index (ActiveSink* self); +gint active_sink_get_source_index (ActiveSink* self); + SoundState active_sink_get_state (ActiveSink* self); void active_sink_deactivate (ActiveSink* self); - +void active_sink_deactivate_voip_source (ActiveSink* self); void active_sink_update_mute (ActiveSink* self, gboolean mute_update); void active_sink_update_volume (ActiveSink* self, gdouble percent); void active_sink_ensure_sink_is_unmuted (ActiveSink* self); diff --git a/src/pulseaudio-mgr.c b/src/pulseaudio-mgr.c index 78feeb3..05b2c8e 100644 --- a/src/pulseaudio-mgr.c +++ b/src/pulseaudio-mgr.c @@ -59,6 +59,10 @@ static void pm_source_info_callback (pa_context *c, const pa_source_info *info, int eol, void *userdata); +static void pm_update_source_info_callback (pa_context *c, + const pa_source_info *info, + int eol, + void *userdata); static void pm_sink_input_info_callback (pa_context *c, const pa_sink_input_info *info, int eol, @@ -172,19 +176,21 @@ pm_subscribed_events_callback (pa_context *c, uint32_t index, void* userdata) { + if (IS_ACTIVE_SINK (userdata) == FALSE){ + g_critical ("subscribed events callback - our userdata is not what we think it should be"); + return; + } + ActiveSink* sink = ACTIVE_SINK (userdata); + switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { case PA_SUBSCRIPTION_EVENT_SINK: - if (IS_ACTIVE_SINK (userdata) == FALSE){ - g_warning ("subscribed events callback - our userdata is not what we think it should be"); - return; - } - ActiveSink* sink = ACTIVE_SINK (userdata); + // We don't care about any other sink other than the active one. if (index != active_sink_get_index (sink)) - return; + return; if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - active_sink_deactivate (ACTIVE_SINK (userdata)); + active_sink_deactivate (sink); } else{ @@ -194,12 +200,27 @@ pm_subscribed_events_callback (pa_context *c, userdata) ); } break; + case PA_SUBSCRIPTION_EVENT_SOURCE: + // We don't care about any other sink other than the active one. + if (index != active_sink_get_source_index (sink)) + return; + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + active_sink_deactivate_voip_source (sink); + } + else{ + pa_operation_unref (pa_context_get_source_info_by_index (c, + index, + pm_update_source_info_callback, + userdata) ); + } + break; case PA_SUBSCRIPTION_EVENT_SINK_INPUT: // We don't care about sink input removals. if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - + g_debug ("Just saw a sink input removal event"); } - else{ + else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { + // Determine if its a VOIP app or a maybe blocking state. pa_operation_unref (pa_context_get_sink_input_info (c, index, pm_sink_input_info_callback, userdata)); @@ -256,6 +277,7 @@ pm_context_state_callback (pa_context *c, void *userdata) if (!(o = pa_context_subscribe (c, (pa_subscription_mask_t) (PA_SUBSCRIPTION_MASK_SINK| + PA_SUBSCRIPTION_MASK_SOURCE| PA_SUBSCRIPTION_MASK_SINK_INPUT| PA_SUBSCRIPTION_MASK_SERVER), NULL, NULL))) { g_warning("pa_context_subscribe() failed"); @@ -273,7 +295,8 @@ pm_context_state_callback (pa_context *c, void *userdata) /** After startup we go straight for the server info to see if it has details of - the default sink. If so it makes things much easier. + the default sink and source. Normally these are valid, if there is none set + fetch the list of each and try to determine the sink. **/ static void pm_server_info_callback (pa_context *c, @@ -326,9 +349,8 @@ pm_server_info_callback (pa_context *c, pm_source_info_callback, userdata))) { g_warning("pa_context_get_sink_info_list() failed"); - // TODO: call some input deactivate method on active sink + // TODO: call some input deactivate method for the source } - pa_operation_unref(operation); } @@ -392,21 +414,28 @@ pm_sink_input_info_callback (pa_context *c, return; } + if (IS_ACTIVE_SINK (userdata) == FALSE){ + g_warning ("sink input info callback - our user data is not what we think it should be"); + return; + } + // Check if this is Voip sink input gint result = pa_proplist_contains (info->proplist, PA_PROP_MEDIA_ROLE); if (result == 1){ g_debug ("Sink input info has media role property"); const char* value = pa_proplist_gets (info->proplist, PA_PROP_MEDIA_ROLE); - if (g_strcmp0 (value, "phone")) { + g_debug ("prop role = %s", value); + if (g_strcmp0 (value, "phone") == 0) { g_debug ("And yes its a VOIP app ..."); + // TODO to start with we will assume our source is the same as what this 'client' + // is pointing at. This should probably be more intelligent : + // query for the list of source output info's and going on the name of the client + // from the sink input ensure our voip item is using the right source. + } //g_free (value); } - if (IS_ACTIVE_SINK (userdata) == FALSE){ - g_warning ("sink input info callback - our user data is not what we think it should be"); - return; - } - + // And finally check for the mute blocking state ActiveSink* a_sink = ACTIVE_SINK (userdata); if (active_sink_get_index (a_sink) == info->sink){ active_sink_determine_blocking_state (a_sink); @@ -465,8 +494,8 @@ pm_default_source_info_callback (pa_context *c, g_warning ("Default sink info callback - our user data is not what we think it should be"); return; } - g_debug ("server has handed us a default sink"); - //active_sink_update_source (ACTIVE_SINK (userdata), info); + g_debug ("server has handed us a default source"); + active_sink_update_voip_input_source (ACTIVE_SINK (userdata), info); } } @@ -476,5 +505,35 @@ pm_source_info_callback (pa_context *c, int eol, void *userdata) { + if (eol > 0) { + return; + } + else { + if (IS_ACTIVE_SINK (userdata) == FALSE){ + g_warning ("Default sink info callback - our user data is not what we think it should be"); + return; + } + // For now we will take the first available + if (active_sink_is_voip_source_populated (ACTIVE_SINK (userdata)) == FALSE){ + active_sink_update_voip_input_source (ACTIVE_SINK (userdata), info); + } + } +} +static void +pm_update_source_info_callback (pa_context *c, + const pa_source_info *info, + int eol, + void *userdata) +{ + if (eol > 0) { + return; + } + else { + if (IS_ACTIVE_SINK (userdata) == FALSE){ + g_warning ("Default sink info callback - our user data is not what we think it should be"); + return; + } + active_sink_update_voip_input_source (ACTIVE_SINK (userdata), info); + } } \ No newline at end of file diff --git a/src/voip-input-menu-item.c b/src/voip-input-menu-item.c index 51ddd95..e904503 100644 --- a/src/voip-input-menu-item.c +++ b/src/voip-input-menu-item.c @@ -1,5 +1,5 @@ /* -Copyright 2010 Canonical Ltd. +Copyright 2011 Canonical Ltd. Authors: Conor Curran @@ -33,6 +33,8 @@ struct _VoipInputMenuItemPrivate { guint32 volume_steps; pa_channel_map channel_map; pa_volume_t base_volume; + gint index; + gint sink_input_index; }; #define VOIP_INPUT_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VOIP_INPUT_MENU_ITEM_TYPE, VoipInputMenuItemPrivate)) @@ -68,6 +70,12 @@ voip_input_menu_item_init (VoipInputMenuItem *self) dbusmenu_menuitem_property_set( DBUSMENU_MENUITEM(self), DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_VOIP_INPUT_MENUITEM_TYPE ); + VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (self); + dbusmenu_menuitem_property_set_bool( DBUSMENU_MENUITEM(self), + DBUSMENU_MENUITEM_PROP_VISIBLE, + FALSE ); + + priv->index = -1; } static void @@ -107,40 +115,58 @@ handle_event (DbusmenuMenuitem * mi, } void -voip_input_menu_item_update_(VoipInputMenuItem* item, +voip_input_menu_item_update (VoipInputMenuItem* item, const pa_source_info* source) { + VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); + // only overwrite the constants of each source if the device has changed + if (priv->index != source->index){ + priv->base_volume = source->base_volume; + priv->volume_steps = source->n_volume_steps; + priv->channel_map = source->channel_map; + } + priv->volume = source->volume; + priv->mute = source->mute; +/* + GVariant* new_volume = g_variant_new_double(update); + dbusmenu_menuitem_property_set_variant(DBUSMENU_MENUITEM(item), + DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL, + new_volume); +*/ } -void -voip_input_menu_item_update_source_details (VoipInputMenuItem* item, - const pa_source_info* source) +gboolean +voip_input_menu_item_is_populated (VoipInputMenuItem* item) { VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); - priv->base_volume = source->base_volume; - priv->volume_steps = source->n_volume_steps; - priv->channel_map = source->channel_map; - priv->volume = source->volume; - priv->mute = source->mute; + return priv->index != -1; } +gint +voip_input_menu_item_get_index (VoipInputMenuItem* item) +{ + VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); + return priv->index; +} -/* -voip_input_menu_item_update (VoipInputMenuItem* item, - gdouble update) +void +voip_input_menu_item_deactivate (VoipInputMenuItem* item) { - GVariant* new_volume = g_variant_new_double(update); - dbusmenu_menuitem_property_set_variant(DBUSMENU_MENUITEM(item), - DBUSMENU_VOIP_INPUT_MENUITEM_LEVEL, - new_volume); + VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); + priv->index = -1; } -*/ void voip_input_menu_item_enable (VoipInputMenuItem* item, gboolean active) { + VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (item); + if (priv->index != -1){ + if (active == TRUE) + g_warning ("Tried to enable the VOIP menuitem but we don't have an active source"); + active = FALSE; + } dbusmenu_menuitem_property_set_bool( DBUSMENU_MENUITEM(item), DBUSMENU_MENUITEM_PROP_VISIBLE, active ); diff --git a/src/voip-input-menu-item.h b/src/voip-input-menu-item.h index ad70289..70dc9fa 100644 --- a/src/voip-input-menu-item.h +++ b/src/voip-input-menu-item.h @@ -1,5 +1,5 @@ /* -Copyright 2010 Canonical Ltd. +Copyright 2011 Canonical Ltd. Authors: Conor Curran @@ -48,10 +48,10 @@ GType voip_input_menu_item_get_type (void); void voip_input_menu_item_update (VoipInputMenuItem* item, const pa_source_info* source); -void voip_input_menu_item_update_source_details (VoipInputMenuItem* item, - const pa_source_info* source); - void voip_input_menu_item_enable (VoipInputMenuItem* item, gboolean active); +gboolean voip_input_menu_item_is_populated (VoipInputMenuItem* item); +gint voip_input_menu_item_get_index (VoipInputMenuItem* item); +void voip_input_menu_item_deactivate (VoipInputMenuItem* item); VoipInputMenuItem* voip_input_menu_item_new (ActiveSink* sink); -- cgit v1.2.3