[pulseaudio-discuss] [PATCH] alsa-ucm: setting default active port based on jacks state

Felipe Tonello eu at felipetonello.com
Fri Aug 30 09:54:58 PDT 2013


Hi David,

On Fri, Aug 30, 2013 at 6:00 AM, David Henningsson
<david.henningsson at canonical.com> wrote:
> On 08/28/2013 07:15 PM, Felipe Tonello wrote:
>> Hi David,
>>
>> On Wed, Aug 28, 2013 at 5:38 AM, David Henningsson
>> <david.henningsson at canonical.com> wrote:
>>> On 08/27/2013 07:06 PM, Felipe Tonello wrote:
>>>> Hi David,
>>>>
>>>> On Tue, Aug 27, 2013 at 12:27 AM, David Henningsson
>>>> <david.henningsson at canonical.com> wrote:
>>>>> On 08/26/2013 08:15 PM, Felipe F. Tonello wrote:
>>>>>> From: "Felipe F. Tonello" <eu at felipetonello.com>
>>>>>>
>>>>>> This fixes a bug when switching profiles under ALSA UCM. If a jack, hence a
>>>>>> port, was previsouly active, when PA performed a profile switch, the jack
>>>>>> would continue to be available but not active.
>>>>>>
>>>>>> This patche ensures that it activates a port if a jack is previously connected.
>>>>>
>>>>> Thanks,
>>>>> but I'm not sure this is the right way to do it.
>>>>>
>>>>> It feels like setting the active port is more like something for a
>>>>> policy module (e g module-switch-on-port-available), rather than being
>>>>> hardcoded in the module itself.
>>>>
>>>> With today's implementation it doesn't work, since if you switch
>>>> profiles the jack won't change its state, so
>>>> module-switch-on-port-available will not notice that.
>>>>
>>>> What it could be done is to ensure when you create a sink/source, to
>>>> report jack state, but this is a local function in alsa-module-card.
>>>> It would need more hack to make it work.
>>>>
>>>> Also, this is not hardcode the port, since the sink/source it self
>>>> does that, it checks if someone else set active_port before, otherwise
>>>> sets itself.
>>>>
>>>> IHMO this patch is less intrusive.
>>>
>>> Even if a jack is available, it does not mean that the port should be
>>> activated, unless you have a policy module saying so. It's the policy
>>> module that causes port switches in the first place.
>>
>> Ok. Then IMO the policy module should say so :) Because as a user, it
>> doesn't make sense when it's listening to a music with a headphone and
>> then when it places a call the sound goes to the speaker.
>
> OTOH, if you're playing back through the speaker, and make a call, you
> likely want the sound to switch, to go through the earpiece speaker
> instead of the main speaker.
>
> And where do you want your ringtone if you have headphones plugged in?
> Perhaps through both the headphones and your speaker?
>
> Etc. It's not that simple - which is why I want this functionality in
> policy modules rather than hard coded.

Ok, it makes sense. But to be realistic, PA doesn't support Voice Call
mode smoothly anyway. At least when using ALSA UCM.

Then module-switch-on-port-available, probably find_best_port(),
should be more smart about choosing ports. It should use
sink/source->active_port just as an hint, testing other stuff (like is
a jack connected?) and if no other port was found, use active_port.

>
>>
>>>
>>> There are already hooks for new sink/sources in
>>> module-switch-on-port-available which fill in the port that should be
>>> initially selected.
>>
>> Sorry about that. I'm currently using v3.0 and there was no such implementation.
>>
>>>
>>> Now that I've read your patch again, it looks like you're only making an
>>> initial suggestion for active_port, which later should get overwritten
>>> by module-switch-on-port-available or module-device-restore, so I don't
>>> understand why your patch makes a difference at all?
>>
>> It makes the difference because the sink will select as active_port
>> the one with higher priority. In most ALSA UCM cases this will be the
>> Speaker. So with this "hint" the module-switch-on-port-available and
>> others will check for sink/source->active_port before and select it if
>> it still active, if not, then will iterate trough the list of ports.
>>
>> OBS: The current implementation will still not work. (to be cont...)
>>
>> static pa_device_port *new_sink_source(pa_hashmap *ports, const char *name) {
>>
>>     void *state;
>>     pa_device_port *i, *p = NULL;
>>
>>     if (!ports)
>>         return NULL;
>>     if (name)
>>         p = pa_hashmap_get(ports, name);
>>     if (!p)
>>         PA_HASHMAP_FOREACH(i, ports, state)
>>             if (!p || i->priority > p->priority)
>>                 p = i;
>>     if (!p)
>>         return NULL;
>>     if (p->available != PA_AVAILABLE_NO)
>>         return NULL;
>>
>>     pa_assert_se(p = find_best_port(ports));
>>     return p;
>> }
>>
>> (cont...)
>>
>> Because this function, which is called by the new sink/source call
>> back, gets the port the correct, based on the active_port name, it
>> calls for find_best_port(ports) which overwrites the previous port.
>
> But only if that port is currently unavailable (PA_AVAILABLE_NO), which
> is the key point here.
>
>> This find_best_port() only checks for availability and priority. So
>> the "hint" here doesn't work at all.
>>
>> Some comments about this function:
>>  - This assert at the end doesn't make sense. Because if it's possible
>> to return NULL if no port was active, why we will abort the program if
>> find_best_port doesn't find any port as well?
>
> find_best_port will always find a port, otherwise the port has
> disappeared between "if (!p) return NULL" and the call to find_best_port.

Well, why not return NULL as the other statements then? :)

>
>>  - This PA_HASHMAP_FOREACH is totally redundant since find_best_port
>> does the same.
>>
>> I think this function could be something like:
>>
>> static pa_device_port *new_sink_source(pa_hashmap *ports, const char *name) {
>>
>>     pa_device_port *i, *p = NULL;
>>
>>     if (!ports)
>>         return NULL;
>>     if (name)
>>         p = pa_hashmap_get(ports, name);
>>     if (!p || p->available != PA_AVAILABLE_NO)
>>         p = find_best_port(ports);
>
> Do you mean "if (!p || p->available == PA_AVAILABLE_NO)" here?

Yes :)

>
>>
>>     return p;
>> }
>>
>>>
>>> (And pa_alsa_ucm_set_active_port should be named
>>> pa_alsa_ucm_get_preferred_port or something like that, because the name
>>> is currently misleading.)
>>
>> I agree.
>>
>> Let me know if you want anything else? Because I can send a patch set
>> having both fixes.
>
> But if we have a working module-switch-on-port-available, we don't need
> any hint from the alsa module. Right?

Yes, I think. So at a first point I would like to add jack support in
module-switch-on-port-available. I know that are probably much other
use cases, but those can be added later, right? We just need to do
something that can easily scale.

What I suggest, like I said above, is to use active_port as a hint
only. It will check for other policies, such as jack is connected, and
then make a decision. What do you think?

Felipe Tonello


More information about the pulseaudio-discuss mailing list