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

Audio Playback #49

Closed RESP3CT88 closed 3 years ago

RESP3CT88 commented 3 years ago

I am simply trying to playback a .wav file through my speakers using this API. I want to use PulseAudio to play a wav and not ALSA.

from pulsectl import PulseSimple

ps = PulseSimple()
ps.file_playback('sound.wav')
Traceback (most recent call last):
  File "test.py", line 8, in <module>
    ps = PulseSimple()
  File "/usr/local/lib/python3.8/dist-packages/pulsectl/pulsectl.py", line 993, in __init__
    self.buffer_attr = c.PA_BUFFER_ATTR(c.PA_INVALID, c.PA_INVALID, c.PA_INVALID, c.PA_INVALID, period_size)
TypeError: an integer is required (got type NoneType)

Any ideas what is wrong? Or is there a better way to play audio in python using a sink's name?

mk-fg commented 3 years ago

There's no PulseSimple class in this repository. Pretty sure it's the wrapper from https://github.com/SoundWall/python-pulse-control repo, and you're probably using that fork, so should file an issue there, as that code is obviously was written and maintained by different folks, and I don't know much about it.

Going just by what I know about python, error seem to be that you didn't pass period_size value to that class, which is apparently required, but defaults to None, causing it to be passed as None into that c.PA_BUFFER_ATTR() struct, where - as error says - an integer is required. (you can see that all other values in that stuct are static and hardcoded)

But you should file an issue there, if that repo is maintained, as again, I have no control or any kind of relation to it.

mk-fg commented 3 years ago

With regards to playing wav through this module in general ("this" as in mk-fg/python-pulse-control one, where you filed this issue, not the fork):

As README here says, it's not supported, and is not very useful thing to implement in blocking python code, as you'd have to do relatively intensive stuff fast, or have bad sound artifacts (buffer underruns, causing stuttering, crackle, etc), and with sync code you basically can't do anything else at the time, as that can easily block such performance-critical stuff.

Haven't really tested it though, and maybe modern hw is fast enough to do such stuff anyway, but imo it should at least be wrapped into something like asyncio to be useful, so that you can do other stuff concurrently without uncontrollable GIL switches and such.

mk-fg commented 3 years ago

Also, wrt playing wav from python through pulseaudio:

Just thought to mention, in case you might want to explore alternatives to running sound playback stream from a python code, due to caveats mentioned in prev comment or whatever issues with the module there.

RESP3CT88 commented 3 years ago

Thanks for the thorough answer! I will likely just use paplay or aplay. Sounds complicated to get sound playback from the API.