From fe11e6ad36166f9e5e7279ffc59249dd7788360a Mon Sep 17 00:00:00 2001 From: Conor Curran Date: Wed, 16 Feb 2011 18:37:15 +0000 Subject: moving towards a voip input item --- src/pulseaudio-mgr.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 79 insertions(+), 5 deletions(-) (limited to 'src/pulseaudio-mgr.c') diff --git a/src/pulseaudio-mgr.c b/src/pulseaudio-mgr.c index 3aed1f1..78feeb3 100644 --- a/src/pulseaudio-mgr.c +++ b/src/pulseaudio-mgr.c @@ -47,10 +47,18 @@ static void pm_default_sink_info_callback (pa_context *c, const pa_sink_info *info, int eol, void *userdata); +static void pm_default_source_info_callback (pa_context *c, + const pa_source_info *info, + int eol, + void *userdata); static void pm_sink_info_callback (pa_context *c, const pa_sink_info *sink, int eol, void *userdata); +static void pm_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, @@ -64,6 +72,7 @@ static void pm_toggle_mute_for_every_sink_callback (pa_context *c, int eol, void* userdata); + static gboolean reconnect_to_pulse (gpointer user_data); static gint connection_attempts = 0; @@ -187,7 +196,10 @@ pm_subscribed_events_callback (pa_context *c, 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) { + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + + } + else{ pa_operation_unref (pa_context_get_sink_input_info (c, index, pm_sink_input_info_callback, userdata)); @@ -276,24 +288,47 @@ pm_server_info_callback (pa_context *c, active_sink_deactivate (ACTIVE_SINK (userdata)); return; } + // Go for the default sink if (info->default_sink_name != NULL) { g_debug ("default sink name from the server ain't null'"); if (!(operation = pa_context_get_sink_info_by_name (c, info->default_sink_name, pm_default_sink_info_callback, userdata) )) { - } - else{ + g_warning("pa_context_get_sink_info_by_namet() failed"); + active_sink_deactivate (ACTIVE_SINK (userdata)); pa_operation_unref(operation); return; } - } + } // If there is no default sink, try to determine a sink from the list of sinks else if (!(operation = pa_context_get_sink_info_list(c, pm_sink_info_callback, - NULL))) { + userdata))) { g_warning("pa_context_get_sink_info_list() failed"); + active_sink_deactivate (ACTIVE_SINK (userdata)); + pa_operation_unref(operation); return; } + // And the source + if (info->default_source_name != NULL) { + g_debug ("default source name from the server is not null'"); + if (!(operation = pa_context_get_source_info_by_name (c, + info->default_source_name, + pm_default_source_info_callback, + userdata) )) { + g_warning("pa_context_get_default_source_info() failed"); + // TODO: call some input deactivate method on active sink + pa_operation_unref(operation); + return; + } + } + else if (!(operation = pa_context_get_source_info_list(c, + pm_source_info_callback, + userdata))) { + g_warning("pa_context_get_sink_info_list() failed"); + // TODO: call some input deactivate method on active sink + } + pa_operation_unref(operation); } @@ -356,6 +391,17 @@ pm_sink_input_info_callback (pa_context *c, g_warning("\n Sink input info callback : SINK INPUT INFO IS NULL BUT EOL was not POSITIVE!!!"); return; } + + 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 ("And yes its a VOIP app ..."); + } + //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; @@ -404,3 +450,31 @@ pm_toggle_mute_for_every_sink_callback (pa_context *c, } } +// Source info related callbacks +static void +pm_default_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; + } + g_debug ("server has handed us a default sink"); + //active_sink_update_source (ACTIVE_SINK (userdata), info); + } +} + +static void +pm_source_info_callback (pa_context *c, + const pa_source_info *info, + int eol, + void *userdata) +{ + +} \ No newline at end of file -- cgit v1.2.3 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/pulseaudio-mgr.c | 99 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 79 insertions(+), 20 deletions(-) (limited to 'src/pulseaudio-mgr.c') 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 -- cgit v1.2.3 From 4bebcafef41b3dbc6b4f3f3e2f6382d82390335f Mon Sep 17 00:00:00 2001 From: Conor Curran Date: Thu, 17 Feb 2011 18:54:58 +0000 Subject: getting there --- src/pulseaudio-mgr.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/pulseaudio-mgr.c') diff --git a/src/pulseaudio-mgr.c b/src/pulseaudio-mgr.c index 05b2c8e..211933b 100644 --- a/src/pulseaudio-mgr.c +++ b/src/pulseaudio-mgr.c @@ -201,6 +201,7 @@ pm_subscribed_events_callback (pa_context *c, } break; case PA_SUBSCRIPTION_EVENT_SOURCE: + g_debug ("Looks like source event of some description"); // We don't care about any other sink other than the active one. if (index != active_sink_get_source_index (sink)) return; @@ -420,23 +421,23 @@ pm_sink_input_info_callback (pa_context *c, } // Check if this is Voip sink input gint result = pa_proplist_contains (info->proplist, PA_PROP_MEDIA_ROLE); + ActiveSink* a_sink = ACTIVE_SINK (userdata); + if (result == 1){ g_debug ("Sink input info has media role property"); const char* value = pa_proplist_gets (info->proplist, PA_PROP_MEDIA_ROLE); g_debug ("prop role = %s", value); if (g_strcmp0 (value, "phone") == 0) { g_debug ("And yes its a VOIP app ..."); + active_sink_activate_voip_item (a_sink); // 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); } // 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); } @@ -534,6 +535,7 @@ pm_update_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 ("Got a source update for %s , index %i", info->name, info->index); active_sink_update_voip_input_source (ACTIVE_SINK (userdata), info); } } \ No newline at end of file -- cgit v1.2.3 From 8263f9aed8c1c66cfe7a7749a4d78c096165acd3 Mon Sep 17 00:00:00 2001 From: Conor Curran Date: Thu, 17 Feb 2011 19:58:09 +0000 Subject: enough for one day --- src/pulseaudio-mgr.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'src/pulseaudio-mgr.c') diff --git a/src/pulseaudio-mgr.c b/src/pulseaudio-mgr.c index 211933b..1cfe7af 100644 --- a/src/pulseaudio-mgr.c +++ b/src/pulseaudio-mgr.c @@ -19,9 +19,9 @@ with this program. If not, see . /**Notes * - * Approach now is to set up the communication channels then query the server - * fetch its default sink. If this fails then fetch the list of sinks and take - * the first one which is not the auto-null sink. + * Approach now is to set up the communication channels, query the server + * fetch its default sink/source. If this fails then fetch the list of sinks/sources + * and take the first one which is not the auto-null sink. * TODO: need to handle the situation where one chink in this linear chain breaks * i.e. start off the process again and count the attempts (note different to reconnect attempts) @@ -165,6 +165,16 @@ pm_update_mute (gboolean update) GINT_TO_POINTER (update))); } +void +pm_update_mic_gain (gint source_index, pa_cvolume new_gain) +{ + pa_operation_unref (pa_context_set_source_volume_by_index (pulse_context, + source_index, + &new_gain, + NULL, + NULL) ); +} + /**********************************************************************************************************************/ // Pulse-Audio asychronous call-backs /**********************************************************************************************************************/ @@ -217,10 +227,12 @@ pm_subscribed_events_callback (pa_context *c, break; case PA_SUBSCRIPTION_EVENT_SINK_INPUT: // We don't care about sink input removals. + g_debug ("sink input event"); if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - g_debug ("Just saw a sink input removal event"); + g_debug ("Just saw a sink input removal event - index = %i", index); } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { + g_debug ("some new sink input event ? - index = %i", index); // Determine if its a VOIP app or a maybe blocking state. pa_operation_unref (pa_context_get_sink_input_info (c, index, -- cgit v1.2.3 From d8cc480485f8f46142298341ef5336a0572be5b4 Mon Sep 17 00:00:00 2001 From: Conor Curran Date: Fri, 18 Feb 2011 13:05:58 +0000 Subject: all working nicely, custom mute behaviour needed --- src/pulseaudio-mgr.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/pulseaudio-mgr.c') diff --git a/src/pulseaudio-mgr.c b/src/pulseaudio-mgr.c index 1cfe7af..8f7a290 100644 --- a/src/pulseaudio-mgr.c +++ b/src/pulseaudio-mgr.c @@ -229,7 +229,13 @@ pm_subscribed_events_callback (pa_context *c, // We don't care about sink input removals. g_debug ("sink input event"); if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - g_debug ("Just saw a sink input removal event - index = %i", index); + gint cached_index = active_sink_get_current_sink_input_index (sink); + + g_debug ("Just saw a sink input removal event - index = %i and cached index = %i", index, cached_index); + + if (index == cached_index){ + active_sink_deactivate_voip_client (sink); + } } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { g_debug ("some new sink input event ? - index = %i", index); @@ -440,8 +446,8 @@ pm_sink_input_info_callback (pa_context *c, const char* value = pa_proplist_gets (info->proplist, PA_PROP_MEDIA_ROLE); g_debug ("prop role = %s", value); if (g_strcmp0 (value, "phone") == 0) { - g_debug ("And yes its a VOIP app ..."); - active_sink_activate_voip_item (a_sink); + g_debug ("And yes its a VOIP app ... sink input index = %i", info->index); + active_sink_activate_voip_item (a_sink, (gint)info->index, (gint)info->client); // 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 -- cgit v1.2.3 From 5882cc24cda26ab021224c66abf579b6b603617b Mon Sep 17 00:00:00 2001 From: Conor Curran Date: Fri, 18 Feb 2011 16:22:58 +0000 Subject: and unmutes on slider activation --- src/pulseaudio-mgr.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/pulseaudio-mgr.c') diff --git a/src/pulseaudio-mgr.c b/src/pulseaudio-mgr.c index 8f7a290..e319793 100644 --- a/src/pulseaudio-mgr.c +++ b/src/pulseaudio-mgr.c @@ -175,6 +175,15 @@ pm_update_mic_gain (gint source_index, pa_cvolume new_gain) NULL) ); } +void +pm_update_mic_mute (gint source_index, gint mute_update) +{ + pa_operation_unref (pa_context_set_source_mute_by_index (pulse_context, + source_index, + mute_update, + NULL, + NULL)); +} /**********************************************************************************************************************/ // Pulse-Audio asychronous call-backs /**********************************************************************************************************************/ @@ -258,6 +267,7 @@ pm_subscribed_events_callback (pa_context *c, } + static void pm_context_state_callback (pa_context *c, void *userdata) { -- cgit v1.2.3 From 9a424c26c67544aafdd7cff2d66519b1c72e8aa0 Mon Sep 17 00:00:00 2001 From: Conor Curran Date: Fri, 18 Feb 2011 16:56:17 +0000 Subject: bug free afaics ... --- src/pulseaudio-mgr.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'src/pulseaudio-mgr.c') diff --git a/src/pulseaudio-mgr.c b/src/pulseaudio-mgr.c index e319793..76102e4 100644 --- a/src/pulseaudio-mgr.c +++ b/src/pulseaudio-mgr.c @@ -225,7 +225,7 @@ pm_subscribed_events_callback (pa_context *c, 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); + active_sink_deactivate_voip_source (sink, FALSE); } else{ pa_operation_unref (pa_context_get_source_info_by_index (c, @@ -421,8 +421,12 @@ pm_default_sink_info_callback (pa_context *c, if (IS_ACTIVE_SINK (userdata) == FALSE){ 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"); + } + // Only repopulate if there is a change with regards the index + if (active_sink_get_index (ACTIVE_SINK (userdata)) == info->index) + return; + + g_debug ("Pulse Server has handed us a new default sink"); active_sink_populate (ACTIVE_SINK (userdata), info); } } @@ -523,7 +527,11 @@ 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 source"); + // If there is an index change we need to change our cached source + if (active_sink_get_source_index (ACTIVE_SINK (userdata)) == info->index) + return; + g_debug ("Pulse Server has handed us a new default source"); + active_sink_deactivate_voip_source (ACTIVE_SINK (userdata), TRUE); active_sink_update_voip_input_source (ACTIVE_SINK (userdata), info); } } -- cgit v1.2.3