[pulseaudio-discuss] How to change profile of bluetooth headset for different applications?

Tanu Kaskinen tanuk at iki.fi
Thu May 26 05:08:48 PDT 2011


On Mon, 2011-05-23 at 18:18 +0100, Colin Guthrie wrote:
> How about this:
> 
> Define a new card property similar in concept to
> PA_PROP_DEVICE_INTENDED_ROLES ("device.intended_roles") called
> PA_PROP_DEVICE_INTENDED_PROFILE ("device.intended_profile").
> 
> In bluetooth device, when loading a headset that has both HSP and A2DP,
> populate the device with the following code:
> 
> if (supports_hsp && supports_a2dp)
> {
>   char *k;
> 
>   k = pa_sprintf_malloc("%s.%s", PA_PROP_DEVICE_INTENDED_PROFILE, "music");
>   pa_proplist_sets(card_data.proplist, k, "a2dp");
>   pa_xfree(k);
> 
>   k = pa_sprintf_malloc("%s.%s", PA_PROP_DEVICE_INTENDED_PROFILE, "video");
>   pa_proplist_sets(card_data.proplist, k, "a2dp");
>   pa_xfree(k);
> 
>   k = pa_sprintf_malloc("%s.%s", PA_PROP_DEVICE_INTENDED_PROFILE, "phone");
>   pa_proplist_sets(card_data.proplist, k, "hsp");
>   pa_xfree(k);
> }
> 
> This should result in "pacmd list-cards" dumping a proplist that includes:
> 
>  device.intended_profile.music = a2dp
>  device.intended_profile.video = a2dp
>  device.intended_profile.phone = hsp
> 
> 
> 
> Then a separate module (module-intended-profiles?) could take care of
> listening quite generically for streams landing on sink and do the
> following logic:
> 
> 
> if (!si->sink || !si->sink->card)
> 	return PA_HOOK_OK;
> 
> char *role = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_ROLE);
> if (!role)
> 	return PA_HOOK_OK;
> 
> char *k = pa_sprintf_malloc("%s.%s", PA_PROP_DEVICE_INTENDED_PROFILE, role);
> pa_card *card = si->sink->card;
> char *profile = pa_proplist_gets(card->proplist, k);
> pa_xfree(k);
> if (!profile)
> 	return PA_HOOK_OK;
> 
> if (!pa_streq(card->active_profile, profile)) {
>    /* Save the current profile for later restoration */
>    ...
> 
>    if (pa_card_set_profile(card, profile, FALSE) < 0)
>    /* Find the sink of this card as the above call will likely have
> changed it */
>    sink = pa_idxset_first(card->sinks, NULL);
> 
>    pa_sink_input_move_to(si, sink, FALSE);
> }
> 
> 
> This code is then completely generic. I'm not 100% sure how well this
> will work in practice as there may be some nasty races etc. but I think
> this general approach could work... Perhaps others (i.e. Tanu :D) have
> better suggestions?

If the priority lists would exist already, the module deciding the
routing could examine the stream properties and pick the sink+port with
the highest priority that can be made available - if the sink+port isn't
immediately available, but can be made available, then the routing
module would change the profile and port as needed.

But the priority lists are not available. I believe the logic that you
propose is otherwise good, except that I don't see how the stream could
"land" on the bluetooth (a2dp) sink automatically on phone calls.
module-bluetooth-device tags only hsp sinks with the phone tag, not a2dp
sinks, so module-intended-roles can't do the required magic. If the hsp
sink doesn't exist because the a2dp profile is selected, I don't think
there's currently any logic to route the stream to the bluetooth sink.
If, however, by some magic the phone stream would be routed to the a2dp
sink, then I think your proposal would work fine.

For better suggestions, I don't think I have any. Except that use the
policy framework - Lin posted from an intel.com address, so I assume he
or she (sorry, I don't know Chinese names) is working on Meego, and I've
thought that Meego got the policy framework from Maemo. In Maemo the
routing is handled by module-policy-enforcement (which gets the command
to enable the bluetooth-hsp routing mode from the policy framework), and
it works pretty nicely for this kind of use cases.

-- 
Tanu




More information about the pulseaudio-discuss mailing list