'Twas brillig, and Lin, Mengdong at 23/05/11 16:58 did gyre and gimble: > Is it possible to handle bluetooth profile change within > ?module-bluetooth-device?, instead of unload this module and reloading > it with the new profile argument for the same device? Yeah, this can be changed quite easily. It's already exposed in the API to allow profile changes without reloading the module. > I need my bluetooth headset working under A2DP profile for a music/video > application and switch to HSP profile automatically for a incoming phone > application. I wonder if the ?module-bluetooth-device? can monitor > application change by hooking sink input?s put and unlink event, change > profile accordingly, and create/delete sink or source by itself. Then > ?module-switch-on-connect? can handle sink/source switch and > ?module-cork-music-on-phone? can handle music interrupted by a incoming > call J Yeah, this kind of support is already planned, so it's certainly not beyond the realms of possibility! The policy based configuration goes beyond bluetooth, for example, if we play 5.1 input, perhaps we should change to a 5.1 profile (this is a rather basic example, but when UCM support comes in, this kind of thing will be somewhat commonplace) > My current solution is to monitor application change in > ?module-bluetooth-discover?: when a phone?s input stream is put and > current profile is not HSP, the discover module will unload > ?module-bluetooth-device? and reload it to HSP profile. I wonder if the > bluetooth device module can handle this by itself so unloading and > reloading can be saved. Yes, you can just change the profile (pa_card_set_profile()). The sink itself should ultimately disappear and reappear which may fire other hooks etc, but hopefully that won't get in your way. I'm not 100% sure where this code should go however... I'm not convinced it should be in module-bluetooth-device.... 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? > I have another question, I learned that the internal concept of a single > "default" device can be replaced by priority lists of devices in future > routing (from Colin?s blog: > http://colin.guthr.ie/2010/02/this-is-the-route-to-hell/) > > Can the logic of ?module-switch-on-connect? conflict with the new > routing design? Yes and in fact I've stated as such on http://pulseaudio.org/ticket/706#comment:11 although I will obviously ensure that any functionality it achieves is preserved when implementing more advanced routing options :) > If yes, this means a latest connected Bluetooth headset may not be the > default device for a phone call and changing the profile is not needed. > How can the Bluetooth device module know whether it?s the default device > for an application when this application?s input stream is PUT? Good question! I'm not 100% sure, but I think the approach I outlined above (caveats with races not withstanding) could be the short term solution. We were recently talking about routing to sinks+ports in a discussion on this ML (jack detection related from a week or so back). Ports are sink-level config options and in many ways it may make sense to change from "card profiles" to "sink ports" for the HSP<->A2DP change (although the fact that the sample spec etc. may change may make this a non-option - I don't know enough about BT to say at this stage). We decided that we probably wanted the routing to work in such a way that entries in the priority list would be keyed by the sink+port. This would allow us to use "is jack plugged in" in our routing decisions. e.g. a user may want to use in order of priority 1) his headphones plugged into internal jack 2) USB speakers 3) Internal speakers. Essentially 1 & 3 are the same sink but with different "ports" active. In this case, if it were possible to put the HSP vs A2DP choice into sink ports, then the following may be present in the "phone" priority list: 1. BT+HSP 2. BT+A2DP 3. Speakers If no bluetooth device is present, it'll use the speakers for a "phone" stream. Then you turn you bt headset on and (for arguments sake) it defaults to A2DP. The fact the device has shown up triggers a "reroute" where the routing priority lists are applied to running streams. Thus the phone call is moved to the BT+A2DP sink. Now, the pseudo module I outlined above kicks in (but rather than module-intended-profiles which acts on a card proplist metadata to change a card profile, it becomes module-intended-ports and acts on the sink proplist metadata to change a sink port). This module sees a phone stream on the sink that an "intended port" for phone streams and thus it changes the port for us. This cases BT+A2DP to disappear but BT+HSP to appear. Again a reroute is triggered and now the stream is moved to the BT+HSP sink. So with this approach everything works nicely.... the question is, is it possible? In the short term, I think the card profile changing module is the way to go! HTHs Col -- Colin Guthrie gmane(at)colin.guthr.ie http://colin.guthr.ie/ Day Job: Tribalogic Limited [http://www.tribalogic.net/] Open Source: Mageia Contributor [http://www.mageia.org/] PulseAudio Hacker [http://www.pulseaudio.org/] Trac Hacker [http://trac.edgewall.org/]