Pulse Audio binding

@Gwen → Test are progressing.

I discovered an interesting test case for you. (I hope :D)

  1. System up and running, fine.
  2. PulseAudio Server falls (USB soundcard disconnection)
  3. OH logs are showing a disconnection, and show trials to reconnect but…

No rules using sound are working anymore (normal you would say… yes but…) no logs showing exception or issue with the rules, the rules are simply not ran, without any mention in the logs.

Hello and thanks for the quick reply.
I’ll try to explain it a little more precisely.
I use S.E.P.I.A as a voice assistant and want to redirect its voice output to my Sonos boxes.

I have a Respeaker Core V2 on which the assistant runs. However, the sound output is not very pleasant.
The first idea was Babelpod to send the sound to the speakers. But Babelpod doesn’t bring any sound and will probably not be further developed either.
The second idea was to send the sound to openHAB via Bluetooth and forward it to the speakers with openHAB, but the Bluetooth binding slows down the Raspi on the openHAB already running a lot.
The third idea is to get the pulse audio server running on the Raspi and then redirect the sound to the Sonos boxes.

I hope I could explain it a little better.
The server runs system-wide, the port is queried and the module also runs.
But as I have now understood it is due to the current binding and I should rather wait for 3.1.0. So far right?

kind regards

The pulseaudio binding, as of the current stable 3.0.1 version, is able to control a pulseaudio server. By control, I mean monitoring sink / output, muting, changing volume level (and maybe switching some application sound from one available sink to another ? I’mt not sure about that)
The next version (3.1.0) will be able to send sound (mp3 / wav) to a pulseaudio server, from the openhab “play sound action”, or the TTS action. I stress this : they are the only sounds that openhab can send. It cannot send arbitrary sound from other source.

So, I think the binding will not help you sending sound from s.e.p.i.a. to your sonos system.

1 Like

Thanks for the interesting answer, but I think my main problem is getting the Pulseaudio server up and running. I can’t find instructions on how to do this anywhere. I only find parts of the internet and everyone writes something different. I’m not completely inexperienced with Linux now, but I don’t know how to look any further. Unfortunately, the documentation on the binding does not describe how to set up the server.
Sorry for my bad english. :frowning:

The binding will not work until the pulseaudio server is working correctly and working for the user you run openHAB as.

no it does not, nor should it, that is beyond the scope of the documentation for an add-on. The binding is made to control the server… once it is running on your host.
The biggest hurtle I ran into was trying to get pulseaudio to work correctly on Debian. Basically, my host was a new Dell desktop. The driver for the sound (which was onboard the motherboard) was not open source and therefore not included in Debian. No amount of research on google could get it working. Wipe the drive and tried Mint linux instead and it worked out of the blocks

1 Like

I’m testing pulseaudio binding with openHAB 3.2.0.M1.
For me, almost everything works properly.
openHAB is running on a Ubuntu 20.04 VM with pulseaudio 13.99.1 running in system mode.
I paired a bluetooth speaker and I register the sink in openHAB and I’m able to play sound through it in console or in rules.
However, I found a little quirk…
Using a playSound action in a DSL rule with volume, doesn’t work as it should. Either the sink changes volume for ~ 1 sec. and reverts or it doesn’t change at all.
Example action:

playSound("pulseaudio:sink:951732ff44:bluez_sink_88_C6_26_28_A4_B0_a2dp_sink", "dingdong.mp3", new PercentType(50))

Looks like a problem with pulseaudio rather then openHAB and/or the binding itself.
pulseaudio log shows that the change volume command is received:

Aug 10 10:47:17 openhab pulseaudio[66478]: Created 28 "TCP/IP client from 127.0.0.1:40314"
Aug 10 10:47:17 openhab pulseaudio[66478]: The reference volume of sink bluez_sink.88_C6_26_28_A4_B0.a2dp_sink changed from front-left: 13107 /  20% / -41.94 dB,   front-right: 13107 /  20% / -41.94 dB to front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB.
Aug 10 10:47:17 openhab pulseaudio[66478]: Storing volume/mute for device+port sink:bluez_sink.88_C6_26_28_A4_B0.a2dp_sink:headset-output.
Aug 10 10:47:17 openhab pulseaudio[66478]: CLI got EOF from user.
Aug 10 10:47:17 openhab pulseaudio[66478]: Freed 28 "TCP/IP client from 127.0.0.1:40314"
Aug 10 10:47:17 openhab pulseaudio[66478]: TCP connection accepted by tcpwrap.
Aug 10 10:47:17 openhab pulseaudio[66478]: Created 29 "TCP/IP client from 127.0.0.1:40316"
Aug 10 10:47:17 openhab pulseaudio[66478]: CLI got EOF from user.
Aug 10 10:47:17 openhab pulseaudio[66478]: Freed 29 "TCP/IP client from 127.0.0.1:40316"
Aug 10 10:47:17 openhab pulseaudio[66478]: TCP connection accepted by tcpwrap.
Aug 10 10:47:17 openhab pulseaudio[66478]: Created 30 "TCP/IP client from 127.0.0.1:40320"
Aug 10 10:47:18 openhab pulseaudio[66478]: CLI got EOF from user.
Aug 10 10:47:18 openhab pulseaudio[66478]: Freed 30 "TCP/IP client from 127.0.0.1:40320"
Aug 10 10:47:18 openhab pulseaudio[66478]: TCP connection accepted by tcpwrap.
Aug 10 10:47:18 openhab pulseaudio[66478]: Created 31 "Simple client (TCP/IP client from 127.0.0.1:49062)"
Aug 10 10:47:18 openhab pulseaudio[66478]: Not restoring device for stream sink-input-by-application-name:Simple client (TCP/IP client from 127.0.0.1:49062), because already set to 'bluez_sink.88_C6_26_28_A4_B0.a2dp_sink'.
Aug 10 10:47:18 openhab pulseaudio[66478]: Negotiated format: pcm, format.sample_format = "\"s16le\""  format.rate = "44100"  format.channels = "2"
Aug 10 10:47:18 openhab pulseaudio[66478]: Sink bluez_sink.88_C6_26_28_A4_B0.a2dp_sink becomes busy, resuming.
Aug 10 10:47:18 openhab pulseaudio[66478]: Acquiring transport /org/bluez/hci0/dev_88_C6_26_28_A4_B0/sep1/fd1
Aug 10 10:47:18 openhab pulseaudio[66478]: Transport /org/bluez/hci0/dev_88_C6_26_28_A4_B0/sep1/fd1 acquired: fd 42
Aug 10 10:47:18 openhab pulseaudio[66478]: Transport /org/bluez/hci0/dev_88_C6_26_28_A4_B0/sep1/fd1 resuming
Aug 10 10:47:18 openhab pulseaudio[66478]: Stream properly set up, we're ready to roll!
Aug 10 10:47:18 openhab pulseaudio[66478]: bluez_sink.88_C6_26_28_A4_B0.a2dp_sink: suspend_cause: IDLE -> (none)
Aug 10 10:47:18 openhab pulseaudio[66478]: bluez_sink.88_C6_26_28_A4_B0.a2dp_sink: state: SUSPENDED -> IDLE
Aug 10 10:47:18 openhab pulseaudio[66478]: Sink bluez_sink.88_C6_26_28_A4_B0.a2dp_sink becomes idle, timeout in 5 seconds.
Aug 10 10:47:18 openhab pulseaudio[66478]: bluez_sink.88_C6_26_28_A4_B0.a2dp_sink.monitor: suspend_cause: IDLE -> (none)
Aug 10 10:47:18 openhab pulseaudio[66478]: bluez_sink.88_C6_26_28_A4_B0.a2dp_sink.monitor: state: SUSPENDED -> IDLE
Aug 10 10:47:18 openhab pulseaudio[66478]: Sink bluez_sink.88_C6_26_28_A4_B0.a2dp_sink becomes idle, timeout in 5 seconds.
Aug 10 10:47:18 openhab pulseaudio[66478]: memblockq requested: maxlength=33554432, tlength=0, base=4, prebuf=0, minreq=1 maxrewind=0
Aug 10 10:47:18 openhab pulseaudio[66478]: memblockq sanitized: maxlength=33554432, tlength=33554432, base=4, prebuf=0, minreq=4 maxrewind=0
Aug 10 10:47:18 openhab pulseaudio[66478]: Created input 1 "(null)" on bluez_sink.88_C6_26_28_A4_B0.a2dp_sink with sample spec s16le 2ch 44100Hz and channel map front-left,front-right
Aug 10 10:47:18 openhab pulseaudio[66478]:     application.name = "Simple client (TCP/IP client from 127.0.0.1:49062)"
Aug 10 10:47:18 openhab pulseaudio[66478]:     simple-protocol.peer = "TCP/IP client from 127.0.0.1:49062"
Aug 10 10:47:18 openhab pulseaudio[66478]:     module-stream-restore.id = "sink-input-by-application-name:Simple client (TCP/IP client from 127.0.0.1:49062)"
Aug 10 10:47:18 openhab pulseaudio[66478]: memblockq requested: maxlength=88200, tlength=88200, base=4, prebuf=18446744073709551615, minreq=8820 maxrewind=0
Aug 10 10:47:18 openhab pulseaudio[66478]: memblockq sanitized: maxlength=88200, tlength=88200, base=4, prebuf=79384, minreq=8820 maxrewind=0
Aug 10 10:47:18 openhab pulseaudio[66478]: bluez_sink.88_C6_26_28_A4_B0.a2dp_sink: state: IDLE -> RUNNING
Aug 10 10:47:18 openhab pulseaudio[66478]: Dropped redundant event due to change event.
Aug 10 10:47:18 openhab pulseaudio[66478]: Storing volume/mute/device for stream sink-input-by-application-name:Simple client (TCP/IP client from 127.0.0.1:49062).
Aug 10 10:47:18 openhab pulseaudio[66478]: Interface org.PulseAudio.Ext.StreamRestore1.RestoreEntry added for object /org/pulseaudio/stream_restore1/entry68
Aug 10 10:47:18 openhab pulseaudio[66478]: Transport /org/bluez/hci0/dev_88_C6_26_28_A4_B0/sep1/fd1 state: idle -> playing
Aug 10 10:47:18 openhab pulseaudio[66478]: Setting card bluez_card.88_C6_26_28_A4_B0 profile a2dp_sink to availability status yes
Aug 10 10:47:18 openhab pulseaudio[66478]: Setting port headset-output to status yes
Aug 10 10:47:18 openhab pulseaudio[66478]: Dropped redundant event due to change event.
Aug 10 10:47:18 openhab pulseaudio[66478]: Resuming sink bluez_sink.88_C6_26_28_A4_B0.a2dp_sink because its transport state changed to playing
Aug 10 10:47:18 openhab pulseaudio[66478]: Properties changed in transport /org/bluez/hci0/dev_88_C6_26_28_A4_B0/sep1/fd1
Aug 10 10:47:18 openhab pulseaudio[66478]: Requesting rewind due to end of underrun.
Aug 10 10:47:18 openhab pulseaudio[66478]: TCP connection accepted by tcpwrap.
Aug 10 10:47:18 openhab pulseaudio[66478]: Created 32 "TCP/IP client from 127.0.0.1:40328"
Aug 10 10:47:18 openhab pulseaudio[66478]: The reference volume of sink bluez_sink.88_C6_26_28_A4_B0.a2dp_sink changed from front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB to front-left: 13107 /  20% / -41.94 dB,   front-right: 13107 /  20% / -41.94 dB.
Aug 10 10:47:18 openhab pulseaudio[66478]: Storing volume/mute for device+port sink:bluez_sink.88_C6_26_28_A4_B0.a2dp_sink:headset-output.
Aug 10 10:47:18 openhab pulseaudio[66478]: CLI got EOF from user.
Aug 10 10:47:18 openhab pulseaudio[66478]: Freed 32 "TCP/IP client from 127.0.0.1:40328"

So, happy to report that I’m happy to the way it works! :laughing:
After all, I’m the one who asked some 4 years ago to implement the sinks for pulseaudio :smiley:

Hello,

I think I know what happens here.
In the pulseaudio sink, the binding send raw audio data to a socket handled by the pulseaudio server. When all the raw data has been sent, the binding returns to OpenHAB.
And then OpenHAB restore the volume to the previous value.
But if the pulseaudio server consumes audio data faster than it plays it, the binding could return the control to OpenHAB too soon, and OpenHAB thinks it’s finished and restore previous volume value before the end.

The sound I used fade near the end, so I never really noticed the volume change in my tests (in fact I don’t use the property volume in the play action).

I opened a bug and a pull request for the correction (this was waaayyyy more complicated than I initially thought)
I hope it could be available for the 3.2.0 release, but it’s not sure, I don’t know the delay for this kind of merge request.
Meanwhile, I have made a release for the 3.1.0 version.

EDIT : I also fix some issue around the volume level restoration who could have the wrong value.

1 Like

Hello users of the pulseaudio binding.
I think I may have encountered a bug, but it seems odd nobody found it before, so I want to check with other users before filling an issue in github and proposing a pull request.

Does anyone use things of type “sink-input” (not just “sink”, really “sink-input”) ? It can be created but it always show up as “error”. After looking in the code, I found a parameter (undocumented) to enable this type of thing : you have to provide a parameter file for the binding (named pulseaudio.cfg in the service configuration directory), with this key/value :
binding.pulseaudio:sinkInput=true
BUT it still doesn’t work, because the parameter value (“true”) is badly parsed as a string instead of a boolean (at least in my dev environment).

It is possible that I do not set this parameter right.
So, does anyone sucessfully use this “sink-input” ?

I’m replying to myself : I made a patch for a better documentation and a better handling of these “activation” parameters. It will be included in the 3.2 release.

1 Like