[pulseaudio-discuss] Tell me more about pa_simple_new device argument ?

Colin Guthrie gmane at colin.guthr.ie
Fri Dec 17 03:06:36 PST 2010


Hi Serge,

Hope we can help you.

Some comments below:

'Twas brillig, and Serge SMEESTERS at 16/12/10 22:54 did gyre and gimble:
> I'm using well th Simple API ...
>http://0pointer.de/lennart/projects/pulseaudio/doxygen/
> 
> But now, I plane to use two "connexion" for two different sound output
> devices (with multi-threading).
> 
> I'm so looking for device selecting...
> 
> How to discover the available devices ?

Normally, we encourage applications to simply not do this. It is often
better to let the Desktop Environment provide tools that allow the user
to select different devices for all applications - so that the user has
one place to go to make adjustments.

In your case, it's quite a specialist application and thus I think you
have good reason to provide this facility inside your app.

The bad news is that the simple API is not really geared up to provide
that level of control.

Eli already pointed out the introspect stuff that is needed for device
enumeration. You will have to connect using the Async API in order to
get a list of available devices. That said, tou can do this and still
use the simple API for actual playback of audio.

There is another method that may be worth while considering (at least in
the early stages).

PA works on properties. That is each stream has various key/value pairs
associated with it.

For playback streams you can see this data by issuing the command:
 pacmd list-sink-inputs


PA will try and save/restore the device choice of an application so that
if the user moves a stream to a different device. In order to save this
information, it will use a "stream restore id" property on the stream
itself. This is normally calculated automatically from the application name.

As you may appreciate from the above, if an application outputs two
streams (as yours will), then they will both have the same stream
restore id and will thus only ever be able to use the same device which
is totally counter productive in your case!

In order to rectify this, you can setup your own
"module-stream-restore.id" when setting up your streams. This will allow
your application to have the two streams saved independently of each
other (both for volume and device) which is what you want.

Sadly the simple API gives no way to set these properties (it's only
exposed through the Async API) but you can do a little trick to set it:

setenv("PULSE_PROP",
"module-stream-restore.id=sink-input-by-application-name:MyAPP-headphone",
1);

or

setenv("PULSE_PROP",
"module-stream-restore.id=sink-input-by-application-name:MyAPP-tunez", 1);


If you call that before pa_simple_new() then this provides a mechanism
to pass that additional information across to PA. It's not the most
elegant, but at least it works!

See also:
http://pulseaudio.org/wiki/FAQ#WhatenvironmentvariablesdoesPulseAudiocareabout

If you use this approach (rather than using the introspection Eli
mention to enumerate devices and provide your users with a built in
GUI), then the user can use e.g. pavucontrol to move the headphone
stream to the appropriate device. The advantage of doing this, is that
if the user is using USB headphones, and he forgets to plug them in,
when he starts your app he'll get both streams on his main output,
realise he's not plugged in his headphones, plug them in and then the
stream will be automatically moved across by the PA server. This is
something you'd have to handle yourself otherwise and sadly the Simple
API just cannot cope with that. You will have to use the Async API to do
that. You would also have to effectively reimplement a lot of logic
already inside PA for remembering which device is preferred etc. (which
can be hard when dealing with removable devices).




And finally, here is a third possibility! This one is arguably a dirty
trick and I possibly shouldn't even suggest it!

PA has a built in system for automatically picking the right device for
certain types of stream. This is currently done by
module-intended-roles. It will automatically connect a "phone" stream
(e.g. from Skype) to a "headset" or "handset" Sink (e.g. a USB or
Bluetooth headphone system).

If you say your headphone stream is actually a "phone" stream, it should
be automatically matched to a headset device. You would do this via
 setenv("PULSE_PROP", "media.role=phone", 1);

You have to be careful however, as there is also a module in PA that
attempts to "cork" (pause) music when a phone call is in progress. If
you properly identify your music output as a media.role=music, then you
will technically get a problem when running your phone stream!

So this suggesting is probably not one you want to employ but I explain
it in the interests of completeness.



Hopefully I've given you some food for thought as to how you want to do
this.

I suspect that if you app is meant to be used as a full screen system,
then keeping an internal GUI and using introspection is probably best.
And if not, then using the 2nd approach of setting the stream restore id
will probably be the quickest and easiest way of working.

Hope that helps!

> PS:
> I plane to share source code (C++) in when it'll be "good" enough...

Excellent! Good luck!

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/]




More information about the pulseaudio-discuss mailing list