PulseAudio on OpenWRT with MPD and other Stuff
First of all, good to be back. Issues with MediaWiki, along with time constraints on fixing it, have prevented new articles from being created.
Anyway, working on several different Routers running OpenWRT 23.05.03 using PulseAudio, MPD (MPC), Bluetooth (BlueZ), and a bunch of other stuff including PulseMixer (works great on OpenWRT, even though the 'required' version is above the version of Python3 available in OpenWRT).
Starting Thoughts
The PulseAudio people are brilliant. But their documentation is a bit questionable. Case in point is the https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/Network/ page. It starts off on a big tangent, then seems to go off on other tangents before addressing the main concepts. That's cool and not a complaint against the PulseAudio people. It's just a little note to let people know who are reading it and just want to get RTP to work that they shouldn't get frustrated. Just keep reading, ignore most of the stuff at the beginning and you'll get there.
A Deep, Deep Hole with PulseAudio at the Very Beginning (on OpenWRT)
The nice people with the OpenWRT project and all their hard work is very much appreciated. But there are also the head scratching (and head exploding) moments too. For instance: How can so much effort be put into something, yet one little item is allowed to (or isn't configured correctly) remain in place that prevents the PulseAudio service from operating properly?
Short Answer: Configure and / or compile the PulseAudio Service in such way that it requires whatever user (including the ROOT User!) be a member of the audio Group. And then don't put that User in the Audio Group as part of the installation. There you go, problem created! And all the work done to include PulseAudio in OpenWRT? Pointless (until the issue is corrected).
The issue? As noted, the root User is not included in the audio Group. Add it in there using groupadd (which in and of itself is interesting to install) or just edit the /etc/group File.
Ready? Let's Install PulseAudio (and dependencies, plus other tools, and see what happens)
Installation of Software
opkg update
opkg install pulseaudio-daemon-avahi pulseaudio-profiles pulseaudio-tools
Do NOT install pulseaudio-daemon (plain), if you want to use Bluetooth to connect to Speakers. The pulseaudio-daemon-avahi contains the necessary bluetooth modules, pulseaudio-daemon (plain) does NOT. One can always disable the avahi service too, without affecting PulseAudio.
Dependencies include some basic ALSA (Advanced Linux Sound Architecture) stuff, but a couple of more items are nice to have for several reason, including testing, so;
opkg install alsa-utils alsa-ucm-conf mpd-full mpd-avahi-service mpc libmpdclient
...and maybe opkg install madplay mpg123 (they don't install any services, so they're just there if you need them)
And some other tools related to hardware: opkg install usbutils pciutils
A nice graphical way to control some aspects of PulseAudio is PulseMixer: https://github.com/GeorgeFilipkin/pulsemixer?tab=readme-ov-file
...but first: opkg install python3 (don't worry that the OpenWRT version of Python 3 is lower than the required version of PulseMixer, as it seems to work fine)
The Errors
Are these the errors referred to earlier as the "show stopper" for PulseAudio. Nope. Just an annoyance that can be fixed.
chown: /dev/mixer: No such file or directory
chown: /dev/dsp: No such file or directory
chmod: /dev/mixer: No such file or directory
chmod: /dev/dsp: No such file or directory
Will this fix it (spoiler alert, NO, so like Frankie said "don't do it")?: opkg install gst1-mod-dvdspu gst1-mod-audiomixer (a bunch of dependencies would be installed too). We'll get to the fix later, let's focus on the "Show Stopper"
The "Show Stopper" for PulseAudio
Issue this command (it is for 'talking' to the PulseAudio Service): pactl list short sinks
The result: Connection failure: Access denied
Why (as noted earlier, but more details and a solution later): The root User (that's right, the ROOT user) doesn't have the privileges to execute the command. WTF!?
How long did it take to figure out and what was the anger level: 10 Page Diatribe DELETED
Solution: Add the root user to the Audio Group: nano /etc/group;
Before: audio:x:29:
After: audio:x:29:root,mpd
Result: It forking works now: pactl list short sinks
There's a bunch of stuff about Cookies (one of PulseAudio's security methods), anonymous authentication, etc., but this is the simplest and works without changing PulseAudio's default configuration.
Bluetooth (AKA Bluez)
Installation
opkg install bluez-daemon bluez-libs bluez-tools bluez-utils bluez-utils-btmon bluez-utils-extra kmod-input-uinput (other dependencies will install too)
...and that's just the basic Bluetooth stuff. It doesn't include the firmware and driver for any specific hardware
Hardware
Bluetooth hardware is fairly inexpensive these days. To 'future-proof' things as much as possible, order hardware with the latest and greatest version of Bluetooth. As of this writing, summer 2024, Bluetooth 5.3 is the contemporary version.
A nice feature to have is a removable antenna. There are more compact devices that don't have removable antennas. And if you want super cheap device, step down to Bluetooth 4.x (still works great with speakers).
Oh, one obnoxious note with Bluez and PulseAudio on OpenWRT is that as of this writing, even though Bluetooth 5.x supports two sets of speakers, just can't make a single controller connect to more than one speaker. Woof!
Example of installing firmware and drivers for Bluetooth Hardware: opkg install rtl8761bu-firmware (bu is the version of the rtl8761 that was designed to work with USB 2.0, so if you're hooking up to a USB 3.0 port, this will work, but according to documentation, won't be optimized. PS: Bluetooth to Speaker will not exceed USB 2.0 speeds).
Example to install Firmware and Drivers: opkg install rtl8761bu-firmware kmod-bluetooth kmod-usb-core kmod-usb2 kmod-usb3 kmod-usb-ohci kmod-usb-uhci kmod-usb-hid kmod-hid kmod-cfg80211
FIRST! (or rather the next thing to do)
Because OpenWRT doesn't include of the Bluez Tools (nope, not Blues Clues), make sure PulseAudio has the Bluetooth Modules loaded up and ready to go!
Crap that Does NOT work
btmgmt "connect" (doesn't exist)
hcitool cc WhatEverMACaddress (doesn't work)
ALSA Related Commands
alsactl : Good for testing basic sound device settings (Top Tip: By default, for whatever reason, the "state" (AKA stored configuration) Directory (/var/lib/alsa) does not exist, so create it.
aplay -D stereoB BeeGees.wav
aplay -D hw:0,0 -c 6 BeeGees.wav -vv : Will show information and a 'meter', along with playing the song.
speaker-test -D hw:0,0 -c 4 --chmap=FL,FR,FC,LFE -t wav : Tests the speaker output (make sure alsa-utils-tests is installed), --chmap "allows for putting things in a different order".
speaker-test -D hw:0,0 -c 8 --chmap=FL,FR,FC,LFE,SL,SR,SL,SR -t wav : For testing 7.1 surround sound, with a catch: Ain't no RL (Rear Left) or RR (Rear Right), there are two SL (Side Left(s)) and two SR (Side Right(s)). Hey, it is what it is. Now you know.
amixer -c 0 sset 'PCM Capture Source' 'Line' : A handy command to change the input of a USB Audio Device that support more than one input / source. Keep in mind the two items in the quotes ( 'PCM Capture Source' and 'Line' ) are potentially unique to every USB Audio Device. How can one get that information? A couple commands (some noted below with details, but for now, just the commands): amixer scontrols (that's two words / commands typed together) and then: amixer -c 0 get 'PCM Capture Source' ( again, modify the item in ' ' (quotes) to the name obtained in the previous command)
alsamixer: shows a text GUI of controls
aplay -l : shows list of sound devices
aplay -L : Shows a list of the various output ports
arecord -l : Shows a list of input / source devices (note, if PulseAudio is running and / or using a device it will show the device as 0, IE, 'unavailable')
arecord -L : Shows a 'limited' list of the input / source devices
amixer scontrols : Shows a 'brief' list of devices
amixer scontents : Shows a detailed list of devices
amixer -c 0 get 'WhatEverNameOfDevice' : 'Gets' the 'capabilities' of an 'item' / device ( WhatEverNameOfDevice can be obtained with the amixer scontents command above)
Example below;
amixer scontrols
Simple mixer control 'Speaker',0
Simple mixer control 'PCM',0
Simple mixer control 'PCM Capture Source',0
Simple mixer control 'Line',0
Simple mixer control 'Mic',0
Simple mixer control 'IEC958 In',0
amixer sdevices
Simple mixer control 'Speaker',0
Capabilities: pvolume pswitch pswitch-joined
Playback channels: Front Left - Front Right - Rear Left - Rear Right - Front Center - Woofer - Side Left - Side Right
Limits: Playback 0 - 197
Mono:
Front Left: Playback 184 [93%] [-2.44dB] [on]
Front Right: Playback 184 [93%] [-2.44dB] [on]
Rear Left: Playback 196 [99%] [-0.19dB] [on]
Rear Right: Playback 196 [99%] [-0.19dB] [on]
Front Center: Playback 196 [99%] [-0.19dB] [on]
Woofer: Playback 196 [99%] [-0.19dB] [on]
Side Left: Playback 196 [99%] [-0.19dB] [on]
Side Right: Playback 196 [99%] [-0.19dB] [on]
Simple mixer control 'PCM',0
Capabilities: cvolume cswitch cswitch-joined
Capture channels: Front Left - Front Right
Limits: Capture 0 - 6928
Front Left: Capture 4096 [59%] [-0.01dB] [on]
Front Right: Capture 4096 [59%] [-0.01dB] [on]
Simple mixer control 'PCM Capture Source',0
Capabilities: enum
Items: 'Mic' 'Line' 'IEC958 In' 'Mixer'
Item0: 'Line'
Simple mixer control 'Line',0
Capabilities: pvolume cvolume pswitch pswitch-joined cswitch cswitch-joined
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 8065 Capture 0 - 6928
Front Left: Playback 4781 [59%] [-5.33dB] [off] Capture 4507 [65%] [1.60dB] [on]
Front Right: Playback 4781 [59%] [-5.33dB] [off] Capture 4507 [65%] [1.60dB] [on]
Simple mixer control 'Mic',0
Capabilities: pvolume cvolume pswitch pswitch-joined cswitch cswitch-joined
Playback channels: Front Left - Front Right
Capture channels: Front Left - Front Right
Limits: Playback 0 - 8065 Capture 0 - 6928
Front Left: Playback 5046 [63%] [-4.30dB] [off] Capture 2451 [35%] [-6.43dB] [on]
Front Right: Playback 5046 [63%] [-4.30dB] [off] Capture 2451 [35%] [-6.43dB] [on]
Simple mixer control 'IEC958 In',0
Capabilities: cswitch cswitch-joined
Capture channels: Mono
Mono: Capture [on]
The above output from the amixer scontrols and amixer sdevices command shows the following;
The 'Speaker' is actually a 7.1 Surround Sound USB Audio Device with several physical AUX / 1/8" / 3.5mm Output Jacks
The 'PCM' is a equates to a "Master Volume" control
The 'PCM Capture Source' is the currently selected input / source (mic, line, or SPDIF)
The 'Line' is represented physically by an AUX / 1/8" / 3.5mm Input Jack ("traditionally" blue)
The 'Mic' is represented physically by an AUX / 1/8" / 3.5mm Input Jack ("traditionally" pink), and on this device, there are actually two physical Jacks, but the software doesn't know this because the Jacks are simply wired in parallel.
The 'IEC958' is represented physically by the SPDIF Jack for a Fiber Optic Cable
...and for this device, the SPDIF output isn't represented to software and apparently is just 'wired' up like a "monitor", where it gets constant full output and cannot be controlled in software (oh, well)
...another oddity of the above specific device, that one wouldn't readily see from the configuration, but becomes apparent in use is that the Line and Mic levels do nothing, but the Capture Source levels do allow for adjustment of levels (oh, well, each sound device will have it's own oddities)
Some WTF? Holes One Can Fall Into
module-detect
In /etc/pulse/system.pa load-module module-detect (Works great, but can also cause some unexpected issues)
Try adding this to the system.pa file: load-module module-alsa-sink device=hw:0,0
...and: Error opening PCM device hw:0: Resource busy, Failed to load module "module-alsa-source" (argument: "device_id=0"): initialization failed.
Why? Because module-detect found it first!
Experiments showed that even loading module-detect after module-alsa-sink still produces an error. So either module-detect always runs first OR module-detect doesn't check and see if an ALSA device is already loaded.
module-native-protocol-unix
If the module-native-protocol-unix isn't loaded ( load-module module-native-protocol-unix ) then the PACTL Command won't work.
The error will be: pa_context_connect() failed: Connection refused
Useful Commands for Testing (from a live file, hence the # Comment Tags)
### Useful Commands for testing stuff;
### /usr/bin/mpd --no-daemon /etc/mpd.conf --verbose
### /usr/bin/pulseaudio --system --disallow-exit --disable-shm --exit-idle-time=-1 --realtime=false --verbose
### bluetoothctl connect FC:58:FA:2E:BA:7C
### bluetoothctl connect F4:4E:FC:EA:3B:33 for the Bluetooth Transceiver Device in Rx Mode
###
### bluetoothctl devices Connected (the C in Connected has to be capitalized)
###
### btmgmt is another command.
###
### btmgmt --index 0 connectable on
### btmgmt bondable on
### btmgmt discov yes
### btmgmt find on OR just plain find
###
### ...after playing with btmgmt, is is very busted on OpenWRT
###
### pactl set-sink-volume bluez_sink.FC_58_FA_2E_BA_7C.a2dp_sink 10%
### alsamixer
### ls /usr/lib/pulse-*/modules/
### pactl list modules short
### pactl list short sinks
###
### pactl info
### pactl list sources short
### pactl load-module module-loopback source=WhatEverNameOfSink
###
### pactl load-module module-loopback source=3 sink=0
### pactl set-sink-volume 0 100%
### pactl set-source-volume 3 100%
### pactl list modules
### pactl list sink-inputs
###
### pacmd is a command too
###
### /usr/bin/pulseaudio --system --disallow-exit --disable-shm --exit-idle-time=-1 --verbose
### /usr/bin/pulseaudio --system --disallow-exit --disable-shm --exit-idle-time=-1 --verbose --log-level=debug --log-target=stderr
### /usr/bin/pulseaudio --system --disallow-exit --disable-shm --exit-idle-time=-1 -vvvvvv --log-level=debug --log-target=stderr
###
### Device F4:4E:FC:EA:3B:33 BT17
### Device FC:58:FA:2E:BA:7C Gemini GHSI-W650BT
###
### aplay WhatEverSongAsLongAsItIs.WAV <-- PulseAudio service must be stopped! (same for sox)
###
### hcitool dev
### hciconfig -a
###
### ...inside of bluetoothctl
###### list (to show bluetooth controllers)
###### devices
######
###### select... one of the following;
###### 5C:F3:70:9C:2B:20 ( ASUS 4.0 )
###### 8A:88:4B:80:F5:CB ( RealTek 5.3 )
######
######
######
### mpc -h password@10.100.100.47 lsplaylist
### mpc -h password@10.100.100.47 playlist
### mpc -h password@10.100.100.47 add
### mpc -h password@10.100.100.47 del
### mpc -h password@10.100.100.47 clear
### mpc -h password@10.100.100.47 load
### mpc -h password@10.100.100.47 save
### mpc -h password@10.100.100.47 status
### mpc -h password@10.100.100.47 current (current song playing)
### mpc -h password@10.100.100.47 queued (next song up)
### mpc -h password@10.100.100.47
### mpc -h password@10.100.100.47
### mpc -h password@10.100.100.47
### mpc -h password@10.100.100.47 update ("Update" the fact there are new songs in the physical directory. After adding song to physical directory, can't play or add to playlist without UPDATE)
###
### opkg install bluez-daemon bluez-libs bluez-tools bluez-utils bluez-utils-btmon bluez-utils-extra kmod-input-uinput
### opkg install pulseaudio-daemon-avahi pulseaudio-profiles pulseaudio-tools
### opkg install mpd-avahi-service mpd-full mpc libmpdclient
### opkg install alsa-lib alsa-ucm-conf alsa-utils gst1-mod-alsa
###
### opkg install rtl8761bu-firmware kmod-bluetooth kmod-usb-core kmod-usb2 kmod-usb3 kmod-usb-ohci kmod-usb-uhci kmod-usb-hid kmod-hid kmod-cfg80211
###
### opkg install shadow-groupadd shadow-useradd shadow-usermod
### usermod
### ...OR: nano /etc/group: audio:x:29:root,mpd
###
### opkg install coreutils-stat procps-ng-pgrep (for the bt-reconnect service)
###
### Files to modify (from previously configured devices): /etc/init.d/pulseaudio, /etc/pulse/system.pa, /etc/mpd.conf, asound.conf (maybe)
### ^^^ Remember to adjust the source sinks and bluetooth sinks for devices
### Configuration Services and Scripts (by me): /etc/init.d/bt-reconnect, /etc/bluetooth.sh, /etc/pulse/pulseaudio.sh