[pulseaudio-discuss] [PATCH 6/6] ucm: Add support for "JackHWMute"

Tanu Kaskinen tanu.kaskinen at linux.intel.com
Wed Apr 1 00:59:50 PDT 2015


On Wed, 2015-04-01 at 09:13 +0200, David Henningsson wrote:
> 
> On 2015-03-31 19:32, Tanu Kaskinen wrote:
> > On Mon, 2015-03-30 at 09:54 +0200, David Henningsson wrote:
> >>
> >> On 2015-02-12 14:11, Tanu Kaskinen wrote:
> >>> "JackHWMute" is a UCM device value that, if set, indicates that the
> >>> jack of the device mutes some other device at the hardware or driver
> >>> level. A common example would be a headphone jack that mutes built-in
> >>> speakers. PulseAudio should show such auto-muted devices as
> >>> unavailable.
> >>>
> >>> Previously there was only a simple relationship: each UCM device was
> >>> related to one jack and vice versa. Now each device is still related
> >>> to exactly one jack, but each jack can be related to two devices: one
> >>> that the jack enables, and one that the jack disables (mutes).
> >>
> >> Sorry for chiming in this late, but...
> >>
> >> Can we instead duplicate the jack, like we do for non-UCM, and set
> >> jack->state_plugged -> PA_AVAILABLE_NO / jack->state_unplugged ->
> >> PA_AVAILABLE_YES for the HWMute jack functionality?
> >
> > I suppose that's possible. I dislike that, because it means that the
> > jack object doesn't actually represent a jack at all, not even a jack
> > kcontrol. Instead, it represents the association between a device and a
> > jack kcontrol. But if you prefer to do it that way, I'll do it that way.
> 
> I'd hate to tell a person to start from scratch again just based on my 
> preference - Arun, what do you think?
> 
> > Some background on why I wrote the patch as I did: I would like to have
> > only one jack object per physical jack, but that's unfortunately not
> > possible, because there may be multiple jack kcontrols per physical
> > jack, and AFAIK there's no API to find out about related jack kcontrols.
> > The next best thing would be to have one jack object for each jack
> > kcontrol, but I decided that since I'm anyway going to have to give up
> > on the "one jack object per physical jack" ideal, maybe it's better to
> > just use the model that UCM uses. In UCM, jacks are per-device things
> > (meaning that each device has to repeat the jack configuration if there
> > are multiple devices using the same jack), so I created one jack per UCM
> > device. Now you want to further increase the duplication, with the
> > benefit that the jack model in the UCM code would match the traditional
> > mixer code, at the cost of introducing a mismatch with the underlying
> > UCM model. I can live with that.
> 
> I'm trying to understand how this description fits with your actual 
> patch, but I'm having troubles understanding how the objects fit together.
> 
> First, you add both "port" and "pa_alsa_ucm_port" structs. What's the 
> difference? Also, both contain pointers to variable called "core_port". 
> Does this also mean there are non-core ports? What's the difference 
> between a "core_port" and "non-core ports"?

Sorry, pa_alsa_ucm_port shouldn't be there, it's not used for anything.
Apparently I thought at some point that I'd need to export the ucm port
struct outside alsa-ucm.c.

> Second, a pa_alsa_ucm_device has an array of pa_alsa_ucm_ports,

It actually has an array of port structs, the comment in the header is
wrong.

> and a 
> pa_alsa_ucm_port has an array of pa_alsa_ucm_devices. I have a hard time 
> understanding this, could you give a realistic example where there is 
> more than one port per device that in turn has more than one device per 
> port?

The UCM port generator creates "combination ports" that consist of
multiple devices. I'm not sure what's the real-world need for that, but
I'd guess the point is to support use cases where audio should be played
to both headphones and internal speakers (a ringtone would be one
example). So, the system could have these ports:

headphones
speakers
headphones+speakers

The headphones device will have association to two ports, and the
headphones+speakers port will have association to two devices.

> Third, JackHWMute per UCM documentation says something like "this jack 
> mutes another device". If the availability of ucm devices are solely set 
> by the jack (right?), then this is effectively a ucm_device to 
> ucm_device connection, where you can set one ucm_device's availability 
> based solely on the other ucm_device. I don't really see why you need to 
> add these crossreference port structs at all.

In case of a combination port, the availability of the port is based on
the availability of all devices of that port. So when the availability
of one device changes, we must iterate over all devices in the port
before we know whether the port should change its availability. That's
where the port struct becomes useful, as it answers the question "what
devices are relevant for the port availability".

> > Another thing: you said jack->state_unplugged would set the state to
> > PA_AVAILABLE_YES, but in the traditional mixer config speakers are set
> > to state PA_AVAILABLE_UNKNOWN when headphones are unplugged. Do you
> > think it should be different with UCM?
> 
> Sorry, I'll correct myself. It would be better to toggle between NO and 
> UNKNOWN, for consistency. That said; I'd want the non-UCM stuff ideally 
> to toggle between NO and YES too, but that's a different discussion.
> 
> >> It looks like this would enable us to share code between UCM and non-UCM
> >> code paths instead of duplicating similar functionality.
> >>
> >> Also, we would then get automatic support for use cases like "Line Out"
> >> which should only be available if both a) "Line Out Jack" is plugged in
> >> and b) "Headphone Jack" is unplugged.
> >
> > In my patch I decided to not support a situation where one jack makes a
> > device available and another jack makes it unavailable, because of the
> > ambiguity. If we want to support the use case you mention, I guess the
> > UCM spec should explicitly say that JackHWMute overrides JackControl,
> > otherwise we'd be relying on undefined behaviour.
> 
> Actually I'd say it's an "and" relation rather than one overrides the 
> other; i e, the device is available only if (JackControl.plugged_in && 
> !JackHWMute.plugged_in).

Yes, that's what I had in mind, but I didn't express it clearly. By
overriding I meant that when JackHWMute is plugged in, that overrides
the JackControl state. If JackHWMute is not plugged in, that doesn't
override anything.

-- 
Tanu



More information about the pulseaudio-discuss mailing list