mk-fg / python-pulse-control

Python high-level interface and ctypes-based bindings for PulseAudio (libpulse)
https://pypi.org/project/pulsectl/
MIT License
170 stars 36 forks source link

Exposing flags from sink inputs and source outputs #74

Closed sbraz closed 2 years ago

sbraz commented 2 years ago

Hi, I wrote a script to move all sinks/sources and it fails on some objects because they have the flag DONT_MOVE. I'd like to skip them but I can't see the flags via pulsectl's API.

Could you please expose this info on PulseSinkInputInfo and PulseSourceOutputInfo objects?

mk-fg commented 2 years ago

Hm, don't think underlying pa_sink_input_info struct has a flags field, and pactl list sink-inputs doesn't seem to show these, so don't know how do you get those in a libpulse client.

Maybe it's a sink flag, and not sink-input's? Where do you see this flag? Also maybe you know how to get it via libpulse, or some client code that checks it?

Will grep the code for it later to see what it's about too.

mk-fg commented 2 years ago

Looking a bit more into it, unfortunate conclusion seem to be that these flags are internal and not exposed to clients via libpulse API.

pactl list sink-inputs does not have those flags, while pacmd list-sink-inputs does. Difference of course is that pacmd sends that command and gets its text output generated by pulseaudio daemon itself, in its cli module (in pa_sink_input_list_to_string of cli-text.c to be precise).

Only ref to these internal pa_sink_input_flags in non-internal module seem to be in protocol-native.c, where these flags can be set for new stream, and even there they're translated in command_create_playback_stream from a dozen dedicated boolean fields (e.g. no_move for PA_SINK_INPUT_DONT_MOVE), instead of exposing that flags field to the client directly.

Then question is whether there's some special method for querying this specific DONT_MOVE flag in libpulse api maybe, and answer seem to be "no" - don't see anything for those flags in introspection api or PROTOCOL, aside from those flags in PA_COMMANDCREATE* routines setting them for new streams.

You can probably ask devs on IRC or in pulseaudio-related channels as to why that is, there's probably a reason why those flags are hidden.

So, given this restriction, I'd probably just try moving things in the code, and catch exception to indicate that stream is immovable for whatever internal reason.

And if this is not good enough, maybe resorting to pulsectl.connect_to_cli() hack is not that bad, though note that this should only work for local pulseaudio (or specially-configured one with cli module listening on tcp), and presumably might be denied on some systems for security reasons (allows to run arbitrary code in pulseaudio daemon context).

Hope that helps, and let me know if you have or will get more info on the subject. There can easily be some nicer workaround that I'm completely blanking on.

sbraz commented 2 years ago

Hi, thanks for the thorough reply.

and catch exception to indicate that stream is immovable for whatever internal reason.

The problem is that the exception is quite generic, so I'm not a fan of this solution. Maybe I'll ask on IRC.

mk-fg commented 2 years ago

Hm, yeah, I think it's probably an issue with CallError not properly having .errno assigned to exceptions, since I think pulse might return something like PA_ERR_NOTSUPPORTED in that specific case vs something else if stream index is missing or on any other problems.