[alsa-devel] [pulseaudio-discuss] Using UCM with PulseAudio
tanuk at iki.fi
Fri Jun 15 14:11:27 CEST 2012
On Fri, 2012-06-15 at 08:23 +0530, Arun Raghavan wrote:
> I've been working on porting PulseAudio to Android on the OMAP4-based
> Galaxy Nexus, and have recently looking at the policy-bits. The basic
> porting has been greatly simplified with Wei Feng's work to renew
> PulseAudio UCM integration and Liam's help with fixing up some of the
> UCM config for the Galaxy Nexus. I am, however, facing some trouble
> mapping how the hardware is used to how UCM presents it (or, perhaps,
> the UCM-PA mapping does).
> Some simplified background: the devices of interest on the OMAP4 SoC are
> the main hifi PCM which can be routed to various outputs, the modem PCM
> which is not used for actual output but to enable use of the modem
> during calls, and the tones PCM which is intended to be used for playing
> ringtones, aiui.
Sorry for hijacking the thread. The following wall of text won't help
Arun with his immediate problems, but I wanted to share my thoughts
about the planned routing system in pulseaudio and how OMAP4-style
hardware affects it.
I asked in IRC for a clarification about what "is not used for actual
output but to enable use of the modem during calls" means. Arun means
that opening the modem playback PCM opens a direct audio path from the
modem to the earpiece. Pulseaudio doesn't see the audio data at all.
There's a corresponding capture PCM that opens a direct audio path to
the other direction.
This sort of hardware causes trouble for the planned routing system, at
least as I have envisioned it to behave. My vision has been that the
routing logic in pulseaudio would enable and disable ports based on the
streams that exist and their properties. In the OMAP4 case, there aren't
any streams created when a cellular call starts, and therefore the
routing logic doesn't know that it should do something.
Arun has made an "Android policy module", which I suppose activates the
VoiceCall profile when a call starts and prevents the associated sink
and source from suspending even though they appear to be idle. In the
brave new generic routing policy world, the ports/profiles should not be
touched by anything else than the generic routing logic. Therefore,
Arun's solution will have to be eventually replaced somehow.
As I described, my vision for the routing logic falls short with OMAP4,
if there are no streams associated with the cellular audio. So, what's
the solution? One solution would be to create virtual streams for the
in-hardware audio paths. Another would be to introduce entirely new
concepts in pulseaudio for the in-hardware audio paths.
Regarding the virtual streams solution, it's still unclear what would
trigger the virtual streams to be created. I think they should be
created by module-alsa-card when the relevant ports are activated, but
what activates the ports, if the routing system only does anything when
streams are created? The cellular adaptation module should tell the
routing system that "a call is starting, it would be nice to open the
call audio path now". I was hoping that the virtual stream solution
would avoid adding any further complexity to the routing system, but it
seems that the routing system must anyway be aware of the special
in-hardware audio paths so that other modules can request them to be
So, maybe it's not worth the effort to create virtual streams, since
they don't actually help with the routing.
After spending a while thinking about this, my proposal is that the
routing logic should play with more abstract inputs and outputs than
streams and ports. All streams and ports, and the cellular modem that is
not directly accessible by Pulseaudio, would be just inputs and outputs
from the routing system point of view.
For example, when a music player creates a new playback stream, the
server-side stream implementation would create a new input and register
it in the routing system. After that, the stream implementation would
submit a "routing request" to the routing system: "connect input id:4 to
somewhere". The application didn't specify where the stream should be
routed, so based on the routing request properties (like media role),
the routing system would select the best output that is available.
Routing requests would exist as long as they are needed. In case of
normal streams, that would be as long as the stream exists. If it
becomes impossible to fulfill the request at some point, the stream gets
Routing requests would have a priority - in the music player's case, the
priority would probably be derived from the stream media role. Phone
stream routing requests would have a higher priority.
Another example: there's a cellular call on an OMAP4 platform. The
cellular adaptation module notices that, and creates two routing
requests: "connect input type:cellular_modem to somewhere" and "connect
output type:cellular_modem to somewhere". The alsa card would have
created, based on the UCM data, an input and an output with label
"type:cellular_modem". Those would have very limited routing options:
for example, the cellular modem input might be routable only to the
earpiece or the main speaker. module-alsa-card would inform the routing
system about the limitations, and the routing system would pick the best
alternative from the two available choices.
On some other platform where the cellular modem audio interface is
directly accessible, "type:cellular_modem" would point to an input or
output that is implemented by a normal port. I don't know if UCM
provides the information about whether the VoiceCall PCMs implement a
real audio interface or are they just a hack to enable the in-hardware
audio path. If that information is not available, I'd say that it's then
something that needs to be fixed.
After the routing system has decided what input will be routed to what
output, it will have to somehow make the connection happen. The problem
is that only the alsa module knows how to connect the cellular modem to
the earpiece. Maybe the input and output structs could have a type that
said whether the input or output is a stream, a port, or something
custom. If it's something custom, the struct would have a function
pointer for doing the connection, otherwise normal stream connection
code can be used.
More information about the Alsa-devel