Hi Tanu, On Mon, Mar 28, 2011 at 3:35 PM, Tanu Kaskinen <tanu.kaski...@digia.com> wrote: > From: Tanu Kaskinen <ext-tanu.kaski...@nokia.com> > > --- > src/modules/bluetooth/module-bluetooth-device.c | 126 > +++++++++++++++++------ > 1 files changed, 93 insertions(+), 33 deletions(-) > > diff --git a/src/modules/bluetooth/module-bluetooth-device.c > b/src/modules/bluetooth/module-bluetooth-device.c > index 540d48c..1154651 100644 > --- a/src/modules/bluetooth/module-bluetooth-device.c > +++ b/src/modules/bluetooth/module-bluetooth-device.c > @@ -185,6 +185,8 @@ struct userdata { > > #define MAX_PLAYBACK_CATCH_UP_USEC (100*PA_USEC_PER_MSEC) > > +#define CURRENT_HSP_DEVICE_KEY "current-hsp-device" /* Key to core->shared. > */ > + > #define USE_SCO_OVER_PCM(u) (u->profile == PROFILE_HSP && (u->hsp.sco_sink > && u->hsp.sco_source)) > > static int init_bt(struct userdata *u); > @@ -1961,6 +1963,8 @@ static pa_hook_result_t source_state_changed_cb(pa_core > *c, pa_source *s, struct > > /* Run from main thread */ > static int add_sink(struct userdata *u) { > + char *k; > + > if (USE_SCO_OVER_PCM(u)) { > pa_proplist *p; > > @@ -2014,6 +2018,10 @@ static int add_sink(struct userdata *u) { > if (u->profile == PROFILE_HSP) { > u->sink->set_volume = sink_set_volume_cb; > u->sink->n_volume_steps = 16; > + > + k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->sink); > + pa_shared_set(u->core, k, u); > + pa_xfree(k); > } > > return 0; > @@ -2021,6 +2029,8 @@ static int add_sink(struct userdata *u) { > > /* Run from main thread */ > static int add_source(struct userdata *u) { > + char *k; > + > if (USE_SCO_OVER_PCM(u)) { > u->source = u->hsp.sco_source; > pa_proplist_sets(u->source->proplist, "bluetooth.protocol", "hsp"); > @@ -2079,6 +2089,10 @@ static int add_source(struct userdata *u) { > if (u->profile == PROFILE_HSP) { > u->source->set_volume = source_set_volume_cb; > u->source->n_volume_steps = 16; > + > + k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->source); > + pa_shared_set(u->core, k, u); > + pa_xfree(k); > } > > return 0; > @@ -2325,6 +2339,8 @@ static int init_profile(struct userdata *u) { > > /* Run from main thread */ > static void stop_thread(struct userdata *u) { > + char *k; > + > pa_assert(u); > > if (u->thread) { > @@ -2349,11 +2365,23 @@ static void stop_thread(struct userdata *u) { > } > > if (u->sink) { > + if (u->profile == PROFILE_HSP) { > + k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->sink); > + pa_shared_remove(u->core, k); > + pa_xfree(k); > + } > + > pa_sink_unref(u->sink); > u->sink = NULL; > } > > if (u->source) { > + if (u->profile == PROFILE_HSP) { > + k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->source); > + pa_shared_remove(u->core, k); > + pa_xfree(k); > + } > + > pa_source_unref(u->source); > u->source = NULL; > } > @@ -2383,8 +2411,20 @@ static int start_thread(struct userdata *u) { > > if (USE_SCO_OVER_PCM(u)) { > if (sco_over_pcm_state_update(u) < 0) { > - u->sink = NULL; > - u->source = NULL; > + char *k; > + > + if (u->sink) { > + k = pa_sprintf_malloc("bluetooth-device@%p", (void*) > u->sink); > + pa_shared_remove(u->core, k); > + pa_xfree(k); > + u->sink = NULL; > + } > + if (u->source) { > + k = pa_sprintf_malloc("bluetooth-device@%p", (void*) > u->source); > + pa_shared_remove(u->core, k); > + pa_xfree(k); > + u->source = NULL; > + } > return -1; > } > > @@ -2421,9 +2461,25 @@ static int start_thread(struct userdata *u) { > return 0; > } > > +static void save_sco_volume_callbacks(struct userdata *u) { > + pa_assert(u); > + pa_assert(USE_SCO_OVER_PCM(u)); > + > + u->hsp.sco_sink_set_volume = u->hsp.sco_sink->set_volume; > + u->hsp.sco_source_set_volume = u->hsp.sco_source->set_volume; > +} > + > +static void restore_sco_volume_callbacks(struct userdata *u) { > + pa_assert(u); > + pa_assert(USE_SCO_OVER_PCM(u)); > + > + u->hsp.sco_sink->set_volume = u->hsp.sco_sink_set_volume; > + u->hsp.sco_source->set_volume = u->hsp.sco_source_set_volume; > +} > + > /* Run from main thread */ > static int card_set_profile(pa_card *c, pa_card_profile *new_profile) { > - struct userdata *u; > + struct userdata *u, *other_hsp_device; > enum profile *d; > pa_queue *inputs = NULL, *outputs = NULL; > const pa_bluetooth_device *device; > @@ -2439,6 +2495,9 @@ static int card_set_profile(pa_card *c, pa_card_profile > *new_profile) { > return -PA_ERR_IO; > } > > + if (u->profile == PROFILE_HSP) > + pa_shared_remove(u->core, CURRENT_HSP_DEVICE_KEY); > + > /* The state signal is sent by bluez, so it is racy to check > strictly for CONNECTED, we should also accept STREAMING state > as being good enough. However, if the profile is used > @@ -2448,6 +2507,10 @@ static int card_set_profile(pa_card *c, > pa_card_profile *new_profile) { > pa_log_warn("HSP is not connected, refused to switch profile"); > return -PA_ERR_IO; > } > + else if (*d == PROFILE_HSP && (other_hsp_device = pa_shared_get(u->core, > CURRENT_HSP_DEVICE_KEY))) { > + pa_log_warn("Another HSP device (%s) is already active, refused to > switch profile.", other_hsp_device->card->name); > + return -1; > + } > else if (device->audio_sink_state < PA_BT_AUDIO_STATE_CONNECTED && *d == > PROFILE_A2DP) { > pa_log_warn("A2DP is not connected, refused to switch profile"); > return -PA_ERR_IO; > @@ -2474,9 +2537,18 @@ static int card_set_profile(pa_card *c, > pa_card_profile *new_profile) { > stop_thread(u); > shutdown_bt(u); > > + if (USE_SCO_OVER_PCM(u)) > + restore_sco_volume_callbacks(u); > + > u->profile = *d; > u->sample_spec = u->requested_sample_spec; > > + if (USE_SCO_OVER_PCM(u)) > + save_sco_volume_callbacks(u); > + > + if (u->profile == PROFILE_HSP) > + pa_shared_set(u->core, CURRENT_HSP_DEVICE_KEY, u); > + > init_bt(u); > > if (u->profile != PROFILE_OFF) > @@ -2511,6 +2583,7 @@ static int add_card(struct userdata *u, const > pa_bluetooth_device *device) { > const char *ff; > char *n; > const char *default_profile; > + struct userdata *other_hsp_device = NULL; > > pa_assert(u); > pa_assert(device); > @@ -2636,11 +2709,21 @@ static int add_card(struct userdata *u, const > pa_bluetooth_device *device) { > pa_log_warn("Default profile not connected, selecting off profile"); > u->card->active_profile = pa_hashmap_get(u->card->profiles, "off"); > u->card->save_profile = FALSE; > + } else if (*d == PROFILE_HSP && (other_hsp_device = > pa_shared_get(u->core, CURRENT_HSP_DEVICE_KEY))) { > + pa_log_warn("Another HSP device (%s) is already active, selecting > off profile.", other_hsp_device->card->name); > + u->card->active_profile = pa_hashmap_get(u->card->profiles, "off"); > + u->card->save_profile = FALSE; > } > > d = PA_CARD_PROFILE_DATA(u->card->active_profile); > u->profile = *d; > > + if (USE_SCO_OVER_PCM(u)) > + save_sco_volume_callbacks(u); > + > + if (u->profile == PROFILE_HSP) > + pa_shared_set(u->core, CURRENT_HSP_DEVICE_KEY, u); > + > return 0; > } > > @@ -2704,7 +2787,7 @@ int pa__init(pa_module* m) { > struct userdata *u; > const char *address, *path; > DBusError err; > - char *mike, *speaker, *transport, *k; > + char *mike, *speaker, *transport; > const pa_bluetooth_device *device; > > pa_assert(m); > @@ -2805,20 +2888,6 @@ int pa__init(pa_module* m) { > /* Connect to the BT service */ > init_bt(u); > > - if (u->hsp.sco_sink) { > - u->hsp.sco_sink_set_volume = u->hsp.sco_sink->set_volume; > - k = pa_sprintf_malloc("bluetooth-device@%p", (void*) > u->hsp.sco_sink); > - pa_shared_set(u->core, k, u); > - pa_xfree(k); > - } > - > - if (u->hsp.sco_source) { > - u->hsp.sco_source_set_volume = u->hsp.sco_source->set_volume; > - k = pa_sprintf_malloc("bluetooth-device@%p", (void*) > u->hsp.sco_source); > - pa_shared_set(u->core, k, u); > - pa_xfree(k); > - } > - > if (u->profile != PROFILE_OFF) > if (init_profile(u) < 0) > goto fail; > @@ -2851,7 +2920,6 @@ int pa__get_n_used(pa_module *m) { > > void pa__done(pa_module *m) { > struct userdata *u; > - char *k; > > pa_assert(m); > > @@ -2866,6 +2934,12 @@ void pa__done(pa_module *m) { > > stop_thread(u); > > + if (USE_SCO_OVER_PCM(u)) > + restore_sco_volume_callbacks(u); > + > + if (u->profile == PROFILE_HSP) > + pa_shared_remove(u->core, CURRENT_HSP_DEVICE_KEY); > + > if (u->connection) { > > if (u->path) { > @@ -2893,20 +2967,6 @@ void pa__done(pa_module *m) { > > shutdown_bt(u); > > - if (u->hsp.sco_sink) { > - u->hsp.sco_sink->set_volume = u->hsp.sco_sink_set_volume; > - k = pa_sprintf_malloc("bluetooth-device@%p", (void*) > u->hsp.sco_sink); > - pa_shared_remove(u->core, k); > - pa_xfree(k); > - } > - > - if (u->hsp.sco_source) { > - u->hsp.sco_source->set_volume = u->hsp.sco_source_set_volume; > - k = pa_sprintf_malloc("bluetooth-device@%p", (void*) > u->hsp.sco_source); > - pa_shared_remove(u->core, k); > - pa_xfree(k); > - } > - > if (u->a2dp.buffer) > pa_xfree(u->a2dp.buffer); > > --
There is a similar policy in BlueZ already for this and it is configurable via /etc/bluetooth/audio.conf, so I don't think hardcoding this on PA would do any better. -- Luiz Augusto von Dentz Computer Engineer _______________________________________________ pulseaudio-discuss mailing list pulseaudio-discuss@mail.0pointer.de https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss