Pulse Audio binding

Adding this line to the file /etc/pulse/default.pa and a restart of the host system seems to have gotten pulseaudio binding working for me. I can now control the volume of the system audio from OpenHAB
thanks everyone for help

1 Like

This worked for me!!! Great thanks you saved me XD. Worked hours on geting pi to output sound…

How were you able to get a sink to output the playsound(doorbell.mp3)? I only have the system speaker sink…which is not working

It’s been so long since I done this I barely remember now. It could be a permissions issue, they’re common in Linux. Also if you’re using a Pi, make sure it’s a powered speaker and config.txt is setup to output to audio jack.

Hello,

I made a PR which allow the binding to expose an audio sink Thing as an audio sink in openHAB terminology (allowing sound action to play directly against the sink). This send raw audio data to a pulseaudio server. Could also be a remote one the network (this is the main use case I think).

For this, I used the simple protocol (sending raw audio to a port linked to a sink).
So you have to use the pulseaudio module-simple-protocol-tcp server side, which will, once loaded, listen on a port and forward everything to the sink you have configured when loading the module.

pactl load-module module-simple-protocol-tcp sink=<sink_name> port=4711
(The binding now auto load the relevant module on the pulseaudio server)

The binding use the existing Thing “Audio Sink” and extends it by allowing it to connect to the simple protocol port and broadcast raw audio (you need to activate the function in the thing configuration)

I made a test release, testing welcome. The JAR seems OK for 3.1.0 and 3.0.1.

1 Like

Ok, so, Here I am :slight_smile:

The plugin is installed, the previous thing definition are deleted, but I’m not able to make sure I removed the previous version of the bundle, as I’m running OH in Docker, I didn’t find the folder where are placed the different bindings… So, quick help to remove the old one might be appreciate :wink: )

With the new bundle, I succesfully created the bridge which is now “Online”

Meanwhile, after creating the Sink, It’s still “offline”. I’m suspecting the “port” definition to be wrong

I basically re-used the same as the PA Bridge, but I’m maybe wrong there…

For the Sink definition, NOTHING appeared in the logs of KARAF. Seems strange…

Voilà, I’m getting the following logs : (strange as I can use the server from another server)

18:58:38.851 [DEBUG] [.pulseaudio.internal.PulseaudioClient] - reading sinks
18:58:39.355 [DEBUG] [.pulseaudio.internal.PulseaudioClient] - Pulseaudio server 192.168.1.7: 0 modules and 0 items updated

Hello (again) :slight_smile: ,

The “Simple Protocol Port” option is just a “preference”. It means that the binding will try to load the “module-simple-protocol-tcp”, on the destination pulse audio server, on this port first (it will not even bother to try if it found it running on another port). And if it’s not OK (ports already taken, etc), it will try another port (3 attempts)
Besides, the openhab audio sink functionality with simple-protocol, working or not, doesn’t change the status “ONLINE” or “OFFLINE” of the sink thing.
So the issue is somewhere else, the sink thing is not configured properly.
For the sink to be ONLINE, the bridge must find a sink on the pulse audio server with the exact same name.

Could you please check the result of the following command on your rapsberry pi :

pactl list sinks

And this is the same command, but it uses the cli-protocol on port 4712 to get the sink information. This way we check the proper configuration of the module-cli-protocol-tcp :

echo “list-sinks” | netcat localhost 4712

These two commands should return the same output, and you should see the sink(s) available on the rasbperry. The “name: <sink_name>” is the relevant information here

Then, you have to check if, on openhab, you defined the sink thing with the EXACT same name

Hey Gwen, all,

I put in the following section some infos to resume my setup, that will give you a better understanding where I am.

Environment

Everything runs in EsxI, why you’ll maybe notice “full computer” for only “a capability”.

  • Linux machine on Debian 9, running docker, let’s call this machine Server*
    ** In this machine, several containers running, between them, OpenHab 3, let’s call it DockOH

  • Linux machine on Debian 10, running pulseaudio only, serves as PA, let’s call it PulseAudioServer

The Server connects natively via PulseAudio, as a client to PulseAudioServer, sound is working fine, and played to the PA

The DockOH, as a container, does not have access to the soundcard, why I’m trying to get access to a decentralized PulseAudio, in order to backup and maintain my setup more easily, without cheating the docker environment (like mapping /dev/snd, giving privileges,…)
The DockOH has your new binding running in it, launching connection to PulseAudioServer

On PulseAudioServer, I tried the following :

  • Tried the "echo “list-sinks, …”, the command opens something and don’t close – nothing in the logs

  • Netcat localhost and send raw data manually, typing “list-sinks” manually in the terminal. The connection closes after sending 18 characters, regardless the way I enter it (in bulk, or one by one). The logs of PulseAudio sends me the following :
    *pstream.c: Received SHM frame on a socket where SHM is disabled.*
    and then closes the connection with the following
    [pulseaudio] client.c: Freed 63 "Native client (TCP/IP client from 127.0.0.1:55758)"
    [pulseaudio] protocol-native.c: Connection died.

(salme behavior with Telnet on port 4712)

I found this : PulseAudio discussion on Narkive Forum, but this didn’t help to go further.

I don’t think the error is coming from the lack of SHM (Shared Memory), this error comes as the command is too large for the buffer, and it request Share memory space to just receive it properly. I don’t understand why the client can connect perfectly from a “regular” pulseaudio client (Server) but that I can’t access it with another one. The connection dies everytime…

For now, still searching, will update the post if I find something else.

could you please share your /etc/pulse/* files ?
Really wondering what I did wrong here

For info, I also tried to sniff the TCP traffic while trying the echo “list-sinks” | netcat…
Here it is : tcpdump for PulseAudio | netcat connection - Pastebin.com

Hello,

I will explain the process, what the pulse audio binding does, on the hope it helps you debugging your issue.

On the system receiving the sound to play, your pulseaudio server must first load the module-cli-protocol-tcp. On most system, it is done by command line, for example :

pactl load-module module-cli-protocol-tcp port=4712

(the port arg is optional) (the terminal should return an integer id. It could also return an error message if it is already loaded. You can unload it with the unload-module command argument)

or more definitively by adding a line in a pulseaudio configuration file. On my sound system (a raspberry pi running pulseaudio in system wide mode), it is done by adding the following line to the file /etc/pulseaudio/system.pa :

load-module module-cli-protocol-tcp

This is the only step required to use the pulseaudio binding. This is the only modification I made on my pulseaudio system.
When the module is loaded (either by command line, or at startup with the configuration file), it opens a TCP socket (usually on port 4712), and any process connecting to it can control the pulseaudio server as if it has command line access.
(This is why I made you try the netcat command : it connects to the module-cli-protocol-tcp and send a simple list command).

So the openhab pulseaudio bridge thing try to connect to this port (this is the “Port” property of the bridge thing). If it can connect, the bridge is marked “ONLINE”. BUT it does’t verify further. It is, as far as I can tell, only a “ok the tcp connection is done” —> ONLINE. If another process is listening on this 4712 port, it will says “ONLINE”.

And I think that is the case here : the module-cli-protocol-tcp is NOT listening on 4712. This is why you cannot issue command by netcat, and this is why the pulseaudio binding does not found any sink, as you can see in your logs (when it says 0 sink found).
Could it be the native protocole module listening on 4712 ? It could explain your strange log with native / shm issue…

Note : the “simple protocol port” on the sink thing is another port entirely. It is completely optional, but it is NOT the same thing.
Your issue seems to be with the bridge “Port” property, and it has to match the port arg with the “load-module module-cli-protocol-tcp” command.

Hey Gwen,

The bridge “appears” well connected, look below. But…

In the PulseAudio Logs, I see that the connection dies, I don’t know why… Look the following logs

[pulseaudio] protocol-native.c: Client authenticated anonymously.
[pulseaudio] client.c: Freed 9 “Native client (TCP/IP client from 192.168.1.4:52670)”
[pulseaudio] protocol-native.c: Connection died.

and the pulseaudio server is well listening on port 4712, I can telnet the port, I see an answer, but the PulseAudio server does not interpret anything, so I guess an issue with my PA config, I’ll try to reinstall Debian 10 and start from a fresh install.

The binding tries, in loop, to connect with my PA server, each time, the connection dies…

I: [pulseaudio] protocol-native.c: Client authenticated anonymously.
I: [pulseaudio] client.c: Freed 18 “Native client (TCP/IP client from 192.168.1.4:52758)”
I: [pulseaudio] protocol-native.c: Connection died.
I: [pulseaudio] socket-server.c: TCP connection accepted by tcpwrap.
I: [pulseaudio] client.c: Created 19 “Native client (TCP/IP client from 192.168.1.4:52760)”
I: [pulseaudio] protocol-native.c: Client authenticated anonymously.
I: [pulseaudio] client.c: Freed 19 “Native client (TCP/IP client from 192.168.1.4:52760)”
I: [pulseaudio] protocol-native.c: Connection died.
I: [pulseaudio] socket-server.c: TCP connection accepted by tcpwrap.
I: [pulseaudio] client.c: Created 20 “Native client (TCP/IP client from 192.168.1.4:52772)”
I: [pulseaudio] protocol-native.c: Client authenticated anonymously.
I: [pulseaudio] client.c: Freed 20 “Native client (TCP/IP client from 192.168.1.4:52772)”
I: [pulseaudio] protocol-native.c: Connection died.
I: [pulseaudio] socket-server.c: TCP connection accepted by tcpwrap.
I: [pulseaudio] client.c: Created 21 “Native client (TCP/IP client from 192.168.1.4:52774)”
I: [pulseaudio] protocol-native.c: Client authenticated anonymously.
I: [pulseaudio] client.c: Freed 21 “Native client (TCP/IP client from 192.168.1.4:52774)”
I: [pulseaudio] protocol-native.c: Connection died.
I: [pulseaudio] socket-server.c: TCP connection accepted by tcpwrap.
I: [pulseaudio] client.c: Created 22 “Native client (TCP/IP client from 192.168.1.4:52792)”
I: [pulseaudio] protocol-native.c: Client authenticated anonymously.
I: [pulseaudio] client.c: Freed 22 “Native client (TCP/IP client from 192.168.1.4:52792)”
I: [pulseaudio] protocol-native.c: Connection died.
I: [pulseaudio] socket-server.c: TCP connection accepted by tcpwrap.
I: [pulseaudio] client.c: Created 23 “Native client (TCP/IP client from 192.168.1.4:52794)”
I: [pulseaudio] protocol-native.c: Client authenticated anonymously.
I: [pulseaudio] client.c: Freed 23 “Native client (TCP/IP client from 192.168.1.4:52794)”
I: [pulseaudio] protocol-native.c: Connection died.
I: [pulseaudio] socket-server.c: TCP connection accepted by tcpwrap.
I: [pulseaudio] client.c: Created 24 “Native client (TCP/IP client from 192.168.1.4:52806)”
I: [pulseaudio] protocol-native.c: Client authenticated anonymously.
I: [pulseaudio] client.c: Freed 24 “Native client (TCP/IP client from 192.168.1.4:52806)”
I: [pulseaudio] protocol-native.c: Connection died.
I: [pulseaudio] socket-server.c: TCP connection accepted by tcpwrap.
I: [pulseaudio] client.c: Created 25 “Native client (TCP/IP client from 192.168.1.4:52808)”
I: [pulseaudio] protocol-native.c: Client authenticated anonymously.
I: [pulseaudio] client.c: Freed 25 “Native client (TCP/IP client from 192.168.1.4:52808)”
I: [pulseaudio] protocol-native.c: Connection died.

Yes, this is what I said :
The bridge says ONLINE. But in order to announce “ONLINE”, it just has to be “TCP connected” to a socket. It doesn’t matter what process is listening on the other side. It will tell ONLINE but it won’t be OK.

I think that your pulseaudio NATIVE module (or another process) is listening on port 4712, the port openhab is trying to connect to (or whatever port is set in the “Port” parameter of the openhab bridge thing)
But the openhab pulseaudio binding needs to connect to the CLI module. Not NATIVE.

I suggest that you unload and reload modules by command line, and that you force port :

pactl unload-module module-cli-protocol-tcp
pactl unload-module module-native-protocol-tcp
pactl load-module module-cli-protocol-tcp port=4712
pactl load-module module-native-protocol-tcp port=4713

Then :

pactl list modules

Should show the two modules properly loaded, with the port argument.

Then I bet openhab should be able to connect to the CLI module on port 4712 (Port parameter on the bridge thing)

1 Like

Héhé, Thanks Gwen, indeed, I totally missed that I needed TWO different modules…
Now, loaded, it works and I can map the sink inside openhab.

Well, I had some bugs in the beginning, pulseaudio even crashed, but this is not reproductible for now, the sink is working and mapped. I can do a “Audio Play Mp3” in Karaf, and that does the work
as soon as I see more, I’ll let you know

Thans for your help

Just in case, for clarification : openhab just need the “module-cli-protocol-tcp” on the pulseaudio server it is connecting to.
The “module-native-protocol-tcp” is, as far as I understand, needed for your other service(s) connecting to your “PulseAudioServer”.

I’m glad it works for you now. :slight_smile:

1 Like

Hey Gwen :slight_smile:

Thanks once again, making my follow-up, maybe some interresting stuff to mention in the doc, about the pulse audio server, I would even be glad to help you in writing it, or to review it when done, to improve readiness and be hollistic with the informations.

My use case is the “door bell” case, connected through KNX-Binding to catch the trigeer, and then launching a rule playing a sound (and some other stuff, telegram, notifs,…)

The connection went well all the day yesterday. But Pulseaudio crashed during the night, reason is not clear, apparently, the server simply stopped because nothing to do, I restarted the server with verbose mode very high “-vvvvv” adding the “disallow-exit” argument.

Wait and see, otherwise, just restarting the server sufficed to restart the connection and sound, was “a bit” long for the first sound, but quicker afterwards. I’m thinking about playing a small “beeep” everyhours to keep track of the connection…

Keeping updated.

I never noticed this kind of pulseaudio server crash at my home. Seems a little bit strange if it is a “normal” behaviour. I don’t think openhab is responsible though.

Yes the first sound played after a connection closed (whatever the reaseon) is a bit longer (and even a bit glitchy, with some kind of speedup or something), as it needs to query the pulseaudio server for the simple-module information and restart a tcp socket. Afterwards the connection is maintained, and thus the other sounds played are very responsive.
To fix this kind of lagguy behaviour, I should implement a “watchdog” or something like this, plus a increasing delay retry counter, to periodically check the connection and reconnect as soon a problem is detected. But i’m not sure it is worth the hassle, as a disconnection should be rather rare.

Thanks for testing, I’m happy to see that it is working on another setup than mine.

Hello, I’m already in the right place and I hope you can help me.

What I want to build is to replace the default audio source in OH3 with pulse audio.
Then I want to send the audio signal from my voice assistant to the Pulseaudio server via the network and then send it to a smart speaker via OH. At least that’s the idea. But I can’t get the binding to work so that I can test whether my idea works.

The binding always has the status: INITIALIZING. As described here, I added the: load-module module-cli-protocol-tcp to the default.pa, restarted rpi, but the binding does not go online.

Does anyone have a working guide on how to get this to work? Everyone says something different here and you only ever find fragments.

Thank you for your help

Hello,

I don’t understand what you are trying to do. You want openhab to act as a sort of “rebound” ? Getting audio source from somewhere and sending it elsewhere ? If so, the pulsaudio binding is not a tool for this use case. It can not “get” sound, it can only send sound to a pulseaudio server by executing the “play sound action” (and only with the 3.1.0-snapshot beta release).
Can you please be more specific about your smart speaker and voice assistant ?

Anyway, I may have misunderstood your need. So, in order to help you setting up the binding, can you check this command on your raspberry pi (if it is indeed the system you want openhab to connect to) :

pactl list modules

If your “module-cli-protocol-tcp” is correctly loaded on your pi, you should see it in the list.

And with this command, you should see if your pulseaudio is listening on the 4712 port :

sudo netstat -antuple | grep 4712

(Should return something like

tcp 0 0 0.0.0.0:4712 0.0.0.0:* LISTEN 111 13433 352/pulseaudio)

Is your pulseaudio server running as a system wide service, or launching as a user service ? I’m asking because the default is “as a user service” and it requires you to log in to be properly launched.

Can you also give the content of the openhab log when you stop/start the pulseaudio bridge thing ?

@Smarthome-Creator → Just to be sure, be careful you’re using the last dev version, not the one in the current official repository.

Sharing what Gwen shared with me earlier…

  • Install this test release for the pulse audio binding OR wait for the official openhab 3.1.0 release and install the binding normally. Disclaimer : this is a test release, and I didn’t have any feedback from other tester. It works for me :wink:
  • As per the documentation is saying, you need a running pulseaudio server with the module module-cli-protocol-tcp loaded. This is where you want the sound to be played. You DON’T NEED to have pulse audio on the openhab machine. In fact, your openhab instance could even be on a Windows machine.
    In my case, my openhab is a PC server and I play sound on a raspberry pi over the network.
  • Create a pulse audio bridge for openhab to connect to your pulse audio server (see documentation)
  • Create or use the auto detection feature to add an “audio sink” thing (see documentation)
    Activate the functionnality “Create an Audio Sink with simple-protocol-tcp” in the newly create thing configuration
  • Use the openhab play sound functionnality. You should be able to choose the pulse audio sink as a destination.