UCM: is there a way to act when a device becomes the active one?

Mikhail Gavrilov <[email protected]>
Newsgroups org.alsa-project.alsa-devel
Message-ID <CABXGCsMuopDFyQ88+00wECHTON7tQLAkoGOQvquqpAg+92vDcA@mail.gmail.com>
Hi,

Two problems from one card, and I suspect one missing piece behind
both.

The card is a USB interface with ten playback channels and two
physical outputs, headphones and a phone jack. A UCM profile splits
the ten channels into five stereo outputs, and the desktop shows five,
which is right: they are five independent pairs and different
applications can go to different ones.

The first problem is that they all sound the same. Each physical
output listens to ONE source chosen inside the card -- an internal mix
or a single playback bus -- and that choice is made in the vendor's
control application, which exists for Windows and macOS only. So you
pick "Playback 3/4" in the sound settings, the audio goes into bus
3/4, and you hear whatever the output was last pointed at. Nothing on
the system says why.

A kernel driver for the card's vendor protocol publishes that selector
as an ordinary enumerated control, so the host can set it now. My plan
was to have each of the five outputs point the headphone stage at its
own bus from that device's EnableSequence, so that choosing an output
would mean hearing it.

It does not work, and I think the reason is structural. WirePlumber
enables every device of the verb at once, so all five sequences run at
startup and the last one wins. Choosing an output afterwards is a
change of default sink, which no UCM sequence observes.

The second problem is worse, and it is what makes me write. The card's
analogue volume belongs to the physical output, not to the bus, so all
five devices name the same mixer element. Each sink then remembers its
own volume while the hardware has one: set Playback 1/2 to full, move
to Playback 3/4, and the slider shows something else while the control
still reads 99. The desktop is showing a number that is not true. I
can avoid it by naming the digital per-bus trim instead, but that
attenuates before the converter and throws away resolution, which is
exactly what the analogue stage exists to avoid.

Both come from the same gap, as far as I can see. UCM can say "this
device exists" with EnableSequence, and cannot say "this device is now
the one being used". With that, the profile would point the output at
the right bus and name the analogue element honestly, because only one
device would be active at a time.

So: is there an existing way to express this that I have missed? A
modifier, a property, something on the PipeWire or PulseAudio side
rather than in UCM? I know ports are the usual answer to "choosing an
output switches hardware", but ports come from devices sharing a
mapping, and in alsa-ucm.c the mapping name is built per device, so
five split PCMs are five sinks by construction.

If there is no way, would a per-device sequence that runs on
activation be a reasonable thing to propose? The shape is not specific
to this card: any interface whose outputs are fed from an internal
matrix has it.

Happy to write the patch if the direction is agreeable, and happy to
be told I have the model wrong.

-- 
Thanks,
Mikhail Gavrilov.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.