Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shairport-sync-docker not finding sound card running on latest Libreelec #12

Open
iVolt1 opened this issue Jul 18, 2021 · 37 comments
Open

Comments

@iVolt1
Copy link

iVolt1 commented Jul 18, 2021

Hi Mike. I am trying to get shairport-sync-docker running on the latest Libreelec 10 beta running on Linux 5.10.41 x86_64 GNU/Linux on a Wyse thin client 5060 AMD GX-424 SOC Radeon R5E graphics.

No matter what I try for hw:X,X on the command line I get these _snd_pcm_hw_open errors in the Portainer log for shairport-sync as soon as I start playing to the instance.

ALSA lib pcm_hw.c:1829:(_snd_pcm_hw_open) Invalid value for card
ALSA lib pcm_hw.c:1829:(_snd_pcm_hw_open) Invalid value for card
ALSA lib pcm_hw.c:1829:(_snd_pcm_hw_open) Invalid value for card,

Per the aplay -l output below this command line should work for the HDMI interface:

docker run -d --restart unless-stopped --net host --device /dev/snd mikebrady/shairport-sync -- -d hw:0,3

I have tried every combination I could think of for hw:X,X for either sound device with no luck.

Any assistance you can provide is greatly appreciated. It will be nice to get the home theater sound in sync with the five other shairport-sync instances running in the house. Please let me know if there is anything else I can provide.

Thanks!

LibreELEC:~ # aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: HDMI [HDA ATI HDMI], device 3: HDMI 0 [HDMI 0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: HDMI [HDA ATI HDMI], device 7: HDMI 1 [HDMI 1]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: Generic [HD-Audio Generic], device 0: ALC231 Analog [ALC231 Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
LibreELEC:~ # aplay -L
null
    Discard all samples (playback) or generate zero samples (capture)
myoutput
    My Output with softvol
hdmi:CARD=HDMI,DEV=0
    HDA ATI HDMI, HDMI 0
    HDMI Audio Output
hdmi:CARD=HDMI,DEV=1
    HDA ATI HDMI, HDMI 1
    HDMI Audio Output
default:CARD=Generic
    HD-Audio Generic, ALC231 Analog
    Default Audio Device
sysdefault:CARD=Generic
    HD-Audio Generic, ALC231 Analog
    Default Audio Device
front:CARD=Generic,DEV=0
    HD-Audio Generic, ALC231 Analog
    Front output / input
surround21:CARD=Generic,DEV=0
    HD-Audio Generic, ALC231 Analog
    2.1 Surround output to Front and Subwoofer speakers
surround40:CARD=Generic,DEV=0
    HD-Audio Generic, ALC231 Analog
    4.0 Surround output to Front and Rear speakers
surround41:CARD=Generic,DEV=0
    HD-Audio Generic, ALC231 Analog
    4.1 Surround output to Front, Rear and Subwoofer speakers
surround50:CARD=Generic,DEV=0
    HD-Audio Generic, ALC231 Analog
    5.0 Surround output to Front, Center and Rear speakers
surround51:CARD=Generic,DEV=0
    HD-Audio Generic, ALC231 Analog
    5.1 Surround output to Front, Center, Rear and Subwoofer speakers
surround71:CARD=Generic,DEV=0
    HD-Audio Generic, ALC231 Analog
    7.1 Surround output to Front, Center, Side, Rear and Woofer speakers

ALSA lib pcm_hw.c:1829:(_snd_pcm_hw_open) Invalid value for card,

@mikebrady
Copy link
Owner

Thanks for the post. If you run $ shairport-sync -h, what does it list at the end for alsa hardware output devices?

@iVolt1
Copy link
Author

iVolt1 commented Jul 19, 2021

Hi Mike,

I didn't think to run the container with the -h and look in the log. It did output to the log, but nothing very specific, just

Available audio backends:
alsa (default)
pipe
stdout

Saving the log and opening it in notepad allowed it to get past most of the special character copy and paste problems in the log.

As a check that I am doing things right, I setup debian 10, docker, and shairport-sync-docker on another computer and everything worked as expected.

Here is alsamixer output for the hdmi:

LibreELECWyse:~ # alsamixer -m
lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq AlsaMixer v1.2.4 qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk
x Card: HDA ATI HDMI F1: Help x
x Chip: ATI R6xx HDMI F2: System information x
x View: F3:[Playback] F4: Capture F5: All F6: Select sound card x
x Item: S/PDIF Esc: Exit x
x x
x x
x lqqk lqqk x
x xOOx xOOx x
x mqqj mqqj x
x < S/PDIF >S/PDIF 1

docker run -d --restart unless-stopped --net host --device /dev/snd
mikebrady/shairport-sync -h

Available mDNS backends:

i\

Available audio backends:
alsa (default)
pipe
stdout

y

Thanks!

@mikebrady
Copy link
Owner

Thanks. I'm afraid I can not make sense of that at all.
This is what comes out of a Raspberry Pi:

...
Available mDNS backends: 
    avahi

Available audio backends:
    alsa (default)
    pipe

Settings and options for the audio backend "alsa":
    -d output-device    set the output device, default is "default".
    -c mixer-control    set the mixer control name, default is to use no mixer.
    -m mixer-device     set the mixer device, default is the output device.
    -i mixer-index      set the mixer index, default is 0.
    hardware output devices:
      "hw:Headphones"
      "hw:sndrpihifiberry"

Settings and options for the audio backend "pipe":
    specify the pathname of the pipe to write to.

You can see that it gives the names of the devices. It's by no means infallible, but might offer a guide. It is troubling that you can't get a clean output -- there should be no special characters in it.

HDMI devices sometimes do not provide a 44,100 frames per second capability (which Shairport Sync must have), only 48,000 fps -- I wonder if that is the problem.

@iVolt1
Copy link
Author

iVolt1 commented Jul 19, 2021

I will look into the frames per second capability. I should have mentioned it is a displayport++ port with an adapter to hdmi. It has worked well with every other audio I have played through it so far. It also has a front headphone jack as you saw from the aplay output. It would be nice get that jack working as a proof of concept, but the intent is use the hdmi cable to the reciever. The Wyse 5060 should be fast enough your Airplay2 project which I am also going to start testing on another box.

Have you heard of anyone having success with shairport-sync-docker on Libreelec?

Also, I didn't copy far enough and didn't see the 'hardware output devices:' line in the log since it was appended to the prior line. It shows no hardware output devices.

Thanks again!

Settings and options for the audio backend "alsa":
-d output-device set the output device, default is "default".
-c mixer-control set the mixer control name, default is to use no mixer.
-m mixer-device set the mixer device, default is the output device.
-i mixer-index set the mixer index, default is 0. hardware output devices:

Settings and options for the audio backend "pipe":
specify the pathname of the pipe to write to.
There are no settings or options for the audio backend "stdout".
There are no settings or options for the audio backend "dummy".

@iVolt1
Copy link
Author

iVolt1 commented Jul 19, 2021

Looking at this thread https://forums.linuxmint.com/viewtopic.php?f=90&t=349665&sid=e57211f93906b6b1f64a78a784765649&start=20 , I was able gather some more hdmi hardware info.
It looks like 44100 is mentioned and maybe something else stands out here.

Playing a flac on the Kodi music screen:
LibreELECWyse:~ # cat /proc/asound/card0/pcm3p/sub0/hw_params
access: RW_INTERLEAVED
format: S32_LE
subformat: STD
channels: 2
rate: 44100 (44100/1)
period_size: 464
buffer_size: 8816

Code info:
LibreELECWyse:~ # cat /proc/asound/card0/codec#0
Codec: ATI R6xx HDMI
Address: 0
AFG Function Id: 0x1 (unsol 0)
Vendor Id: 0x1002aa01
Subsystem Id: 0x00aa0100
Revision Id: 0x100500
No Modem Function Group found
Default PCM:
rates [0x70]: 32000 44100 48000
bits [0x2]: 16
formats [0x1]: PCM
Default Amp-In caps: N/A
Default Amp-Out caps: N/A
State of AFG node 0x01:
Power states: D0 D3 CLKSTOP EPSS
Power: setting=D0, actual=D0, Clock-stop-OK
GPIO: io=0, o=0, i=0, unsolicited=0, wake=0
Node 0x02 [Audio Output] wcaps 0x221: Stereo Digital Stripe
Device: name="HDMI 0", type="HDMI", device=3
Converter: stream=1, channel=0
Digital: Enabled GenLevel
Digital category: 0x2
IEC Coding Type: 0x0
Node 0x03 [Pin Complex] wcaps 0x400381: Stereo Digital
Control: name="IEC958 Playback Con Mask", index=0, device=0
Control: name="IEC958 Playback Pro Mask", index=0, device=0
Control: name="IEC958 Playback Default", index=0, device=0
Control: name="IEC958 Playback Switch", index=0, device=0
Pincap 0x00000094: OUT Detect HDMI
Pin Default 0x185600f0: [Jack] Digital Out at Int HDMI
Conn = Digital, Color = Unknown
DefAssociation = 0xf, Sequence = 0x0
Pin-ctls: 0x40: OUT
Unsolicited: tag=01, enabled=1
Connection: 1
0x02
Node 0x04 [Audio Output] wcaps 0x221: Stereo Digital Stripe
Converter: stream=0, channel=0
Digital: Enabled
Digital category: 0x0
IEC Coding Type: 0x0
Node 0x05 [Pin Complex] wcaps 0x400381: Stereo Digital
Control: name="IEC958 Playback Con Mask", index=1, device=0
Control: name="IEC958 Playback Pro Mask", index=1, device=0
Control: name="IEC958 Playback Default", index=1, device=0
Control: name="IEC958 Playback Switch", index=1, device=0
Pincap 0x00000094: OUT Detect HDMI
Pin Default 0x185600f0: [Jack] Digital Out at Int HDMI
Conn = Digital, Color = Unknown
DefAssociation = 0xf, Sequence = 0x0
Pin-ctls: 0x40: OUT
Unsolicited: tag=02, enabled=1
Connection: 1
0x04
Node 0x06 [Audio Output] wcaps 0x221: Stereo Digital Stripe
Converter: stream=0, channel=0
Digital:
Digital category: 0x0
IEC Coding Type: 0x0
Node 0x07 [Pin Complex] wcaps 0x400381: Stereo Digital
Pincap 0x00000094: OUT Detect HDMI
Pin Default 0x585600f0: [N/A] Digital Out at Int HDMI
Conn = Digital, Color = Unknown
DefAssociation = 0xf, Sequence = 0x0
Pin-ctls: 0x40: OUT
Unsolicited: tag=00, enabled=0
Connection: 1
0x06

@iVolt1
Copy link
Author

iVolt1 commented Jul 20, 2021

Speaker-test gave good results that I could hear from the left and right channels.

LibreELECWyse:~ # speaker-test -Dhdmi -c 2 -r44100 -l4

speaker-test 1.2.4

Playback device is hdmi
Stream parameters are 44100Hz, S16_LE, 2 channels
Using 16 octaves of pink noise
Rate set to 44100Hz (requested 44100Hz)
Buffer size range from 64 to 7849792
Period size range from 32 to 3924896
Using max buffer size 7849792
Periods = 4
was set period_size = 3924896
was set buffer_size = 7849792
 0 - Front Left
...

@mikebrady
Copy link
Owner

mikebrady commented Jul 20, 2021

Thanks. So, it looks as if the HDMI output can indeed do 44,100 fps, but it looks as if it can't be seen from inside the Docker image. To check that, try running:

# ls -al /proc/asound/

inside the Docker image, and post the output. On the Pi, it looks like this:

pi@RaspberryPi4B:~ $ ls -al /proc/asound/
total 0
dr-xr-xr-x  14 root root 0 Jul 18 08:23 .
dr-xr-xr-x 177 root root 0 Jan  1  1970 ..
dr-xr-xr-x   4 root root 0 Jul 19 17:23 card0
dr-xr-xr-x   4 root root 0 Jul 19 17:23 card1
-r--r--r--   1 root root 0 Jul 19 17:23 cards
-r--r--r--   1 root root 0 Jul 19 17:23 devices
lrwxrwxrwx   1 root root 5 Jul 19 17:23 Headphones -> card0
-r--r--r--   1 root root 0 Jul 19 17:23 modules
dr-xr-xr-x   4 root root 0 Jul 19 17:23 oss
-r--r--r--   1 root root 0 Jul 19 17:23 pcm
dr-xr-xr-x   2 root root 0 Jul 19 17:23 seq
-r--r--r--   1 root root 0 Jul 19 17:23 timers
-r--r--r--   1 root root 0 Jul 19 17:23 version

@iVolt1
Copy link
Author

iVolt1 commented Jul 20, 2021

Yes, it looks like it can't be seen by docker.

Docker engine version:
Version | 19.03.15 (API: 1.40)
Root directory | /storage/.kodi/userdata/addon_data/service.system.docker/docker

LibreELECWyse:~ # docker exec -it   stoic_khayyam  ls -al /proc/asound
total 0
drwxrwxrwt    2 root     root            40 Jul 20 12:10 .
dr-xr-xr-x  181 root     root             0 Jul 20 12:10 ..
LibreELECWyse:~ #

At the libreelec command line:

LibreELECWyse:~ #   ls -al /proc/asound
total 0
dr-xr-xr-x   12 root     root             0 Jul 20 07:24 .
dr-xr-xr-x  179 root     root             0 Jul 20 07:02 ..
lrwxrwxrwx    1 root     root             5 Jul 20 07:24 Generic -> card1
lrwxrwxrwx    1 root     root             5 Jul 20 07:24 HDMI -> card0
dr-xr-xr-x    8 root     root             0 Jul 20 07:24 card0
dr-xr-xr-x    6 root     root             0 Jul 20 07:24 card1
-r--r--r--    1 root     root             0 Jul 20 07:24 cards
-r--r--r--    1 root     root             0 Jul 20 07:24 devices
-r--r--r--    1 root     root             0 Jul 20 07:24 hwdep
-r--r--r--    1 root     root             0 Jul 20 07:24 pcm
-r--r--r--    1 root     root             0 Jul 20 07:24 timers
-r--r--r--    1 root     root             0 Jul 20 07:24 version
LibreELECWyse:~ #

@mikebrady
Copy link
Owner

I should have asked — what version of the Docker image are you using, please?

@iVolt1
Copy link
Author

iVolt1 commented Jul 20, 2021

This what the libreelec devs have in the latest 10.0 beta:
Docker engine version:
Version | 19.03.15 (API: 1.40)
Root directory | /storage/.kodi/userdata/addon_data/service.system.docker/docker

Docker can be install directly from Libreelec addon repository. There is another addon from which containers can be directly added to docker. Installing containers from ssh works as well as I have been doing for shairport-sync-docker.

Ideally shairport-sync-docker would be provided by linuxserver.io in the future.
This is the libreelec page that explains all that:
https://forum.libreelec.tv/thread/6721-linuxserver-io-docker-addons-and-general-docker-info/

Thanks again.

@mikebrady
Copy link
Owner

Thanks. What I was really looking for was the version of the Shairport Sync image itself. I guess the version of Shairport Sync itself would be enough -- you can get it by doing:

# shairport-sync -V

inside the Docker image. Then I can do some checking here.

@iVolt1
Copy link
Author

iVolt1 commented Jul 20, 2021

Oops. Not the latest, but close.

LibreELECWyse:~ # docker exec -it   stoic_khayyam  shairport-sync -V
3.3.7-alac-mbedTLS-Avahi-ALSA-dummy-stdout-pipe-soxr-convolution-metadata-mqtt-dbus-mpris-sysconfdir:/etc

@mikebrady
Copy link
Owner

Thanks. So, a couple of things.

  1. I just ran 3.3.7 in Docker on a Raspberry Pi and it worked fine. However, interestingly,
  2. It would not list the contents of /proc/asound, even though everything worked.
  3. Thus, it may be that your installation would work if only you could pick the right name for the output device. So let's concentrate on that.

Looking at the output of # ls -al /proc/asound from the "native" LibreELECWyse command line, it looks like there are two possible devices:

lrwxrwxrwx    1 root     root             5 Jul 20 07:24 Generic -> card1
lrwxrwxrwx    1 root     root             5 Jul 20 07:24 HDMI -> card0

One would be called "hw:Generic" or alternatively "hw:1", and the other would be called "hw:HDMI" or alternatively "hw:0". They would be the two possibilities I would try, leaving the mixer name and so on commented out in the configuration file. Use alsamixer on the native command line to turn the volume up full on the devices, where possible.

Of course, it is possible that there is something about how Docker is installed on LibreELEC that really does prevent access to the /proc/asound stuff, so this might not work. There is some discussion of these issues on the Internet, but I haven't been following them, I'm afraid.

@iVolt1
Copy link
Author

iVolt1 commented Jul 21, 2021

I will give those card suggestions a try. If that's not working I will follow up with the Libreelec team to see why /proc/asound is not being exposed. Thanks for the great help so far.

@iVolt1
Copy link
Author

iVolt1 commented Jul 24, 2021

Hi Mike. I found two things to make progress with.

  1. This allows the the listing of the alsa directories and the shows the devices with shairport-sync -h, but the device error is still present:
    --privileged
$ docker run -d  --name Wyse --privileged --restart unless-stopped --net host --device /dev/snd mikebrady/shairport-sync -- -d hw:0,3
  1. From https://github.com/phrontizo/roonbridge-rpi :

"Runs as UID 1000, GID 63 (audio on LibreElec). Needs to run as a UID:GID that has rw access to /dev/snd - change as appropriate for your system."

I tried multiple ways to run the container with these permissions but nothing worked. I don't know if these permissions can be added to your container without affecting other uses and users or if there is a way to set those permissions from the docker command line.

Thanks again.

@mikebrady
Copy link
Owner

Thanks -- excellent stuff. I think that you can indeed add a group to the current user in the Docker container. However, there might be a slight problem, so it may take a little experimentation.

So, if you try something like:

docker run -d --restart unless-stopped --net host --device /dev/snd --group-add 63 mikebrady/shairport-sync

It will add group numbered 63 to the groups that the user inside the Docker image will run with.

What might be the "slight problem"? Well, inside the Docker image, Shairport Sync does not run as the initial user -- it runs as an extra user shairport-sync which may not inherit group 63 from the initial user. If that is the case, Shairport Sync will not start up. However, from an experimental point of view, you might still be able to try to execute Shairport Sync interactively as the initial user, just to see if it worked.

If you get the name of the container that you started with the command line above and then, assuming it is still running, do:

$ docker exec -it <container_name> shairport-sync -vu

The -vu is to see a debug log.
This should start as the initial user, with membership of group 63, so it might work. If it does work, we might need to adjust our Docker image to generalise the image.

@iVolt1
Copy link
Author

iVolt1 commented Jul 25, 2021

Hi Mike,

Running:

# docker run -d --name Wyse  --privileged --restart unless-stopped --net host --device /dev/snd --group-add 63 mikebrady/shairport-sync -- -d hw:0,3

Still getting:

ALSA lib pcm_hw.c:1829:(_snd_pcm_hw_open) Invalid value for card

With container running, these are the /etc/group:

On Libreelec:

LibreELECWyse:~ #  cat /etc/group
systemd-journal:x:190:
systemd-timesync:x:191:
systemd-network:x:193:
audio:x:63:
cdrom:x:11:
dialout:x:18:
disk:x:6:
floppy:x:19:
kmem:x:9:
kvm:x:10:
lp:x:7:
render:x:12:
tape:x:33:
tty:x:5:
video:x:39:
utmp:x:22:
input:x:199:
dbus:x:81:
netdev:x:497:
root:x:0:
users:x:100:
nogroup:x:65534:
system:x:430:
avahi:x:495:

In Container:

LibreELECWyse:~ # docker exec -it   Wyse cat /etc/group
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
sys:x:3:root,bin,adm
adm:x:4:root,adm,daemon
tty:x:5:
disk:x:6:root,adm
lp:x:7:lp
mem:x:8:
kmem:x:9:
wheel:x:10:root
floppy:x:11:root
mail:x:12:mail
news:x:13:news
uucp:x:14:uucp
man:x:15:man
cron:x:16:cron
console:x:17:
audio:x:18:
cdrom:x:19:
dialout:x:20:root
ftp:x:21:
sshd:x:22:
input:x:23:
at:x:25:at
tape:x:26:root
video:x:27:root
netdev:x:28:
readproc:x:30:
squid:x:31:squid
xfs:x:33:xfs
kvm:x:34:kvm
games:x:35:
shadow:x:42:
cdrw:x:80:
usb:x:85:
vpopmail:x:89:
users:x:100:games
ntp:x:123:
nofiles:x:200:
smmsp:x:209:smmsp
locate:x:245:
abuild:x:300:
utmp:x:406:
ping:x:999:
nogroup:x:65533:
nobody:x:65534:
avahi:x:86:avahi
messagebus:x:101:messagebus
shairport-sync:x:1000:shairport-sync
docker_audio:x:29:shairport-sync

I tried a lot of other things yesterday as well.

Libreelec does not have tools available for interacting with /etc/group that I have found.

-vu output:

LibreELECWyse:~ # docker exec -it Wyse shairport-sync -vu
         0.000661068 "shairport.c:1729" Started!
         0.000050496 "shairport.c:1756" software version: "3.3.7-alac-mbedTLS-Avahi-ALSA-dummy-stdout-pipe-soxr-convolution-metadata-mqtt-dbus-mpris-sysconfdir:/etc"
         0.000020953 "shairport.c:1762" log verbosity is 1.
         0.000017741 "audio_alsa.c:1015" alsa: alsa_maximum_stall_time of 0.200000 sec.
         0.000040090 "audio_alsa.c:1299" alsa: disable_standby_mode is "never".
         0.000016133 "audio_alsa.c:1303" alsa: disable_standby_mode_silence_threshold is 0.040000 seconds.
         0.000017252 "audio_alsa.c:1305" alsa: disable_standby_mode_silence_scan_interval is 0.004000 seconds.
         0.000017391 "audio_alsa.c:1345" alsa: output device name is "default".
         0.000110003 "shairport.c:1810" disable resend requests is off.
         0.000016623 "shairport.c:1811" diagnostic_drop_packet_fraction is 0.000000. A value of 0.0 means no packets will be dropped deliberately.
         0.000017181 "shairport.c:1815" statistics_requester status is 0.
         0.000014318 "shairport.c:1820" rtsp listening port is 5000.
         0.000013410 "shairport.c:1821" udp base port is 6001.
         0.000013759 "shairport.c:1822" udp port range is 10.
         0.000012991 "shairport.c:1823" player name is "LibreELECWyse".
         0.000013200 "shairport.c:1824" backend is "alsa".
         0.000013410 "shairport.c:1825" run_this_before_play_begins action is "(null)".
         0.000015226 "shairport.c:1826" run_this_after_play_ends action is "(null)".
         0.000014807 "shairport.c:1827" wait-cmd status is 0.
         0.000012991 "shairport.c:1828" run_this_before_play_begins may return output is 0.
         0.000015505 "shairport.c:1829" run_this_if_an_unfixable_error_is_detected action is "(null)".
         0.000015715 "shairport.c:1830" run_this_before_entering_active_state action is  "(null)".
         0.000014527 "shairport.c:1831" run_this_after_exiting_active_state action is  "(null)".
         0.000014947 "shairport.c:1832" active_state_timeout is  10.000000 seconds.
         0.000015575 "shairport.c:1833" mdns backend "(null)".
         0.000012991 "shairport.c:1835" interpolation setting is "auto".
         0.000012851 "shairport.c:1838" interpolation soxr_delay_threshold is 30.
         0.000015715 "shairport.c:1839" resync time is 0.050000 seconds.
         0.000013340 "shairport.c:1840" allow a session to be interrupted: 0.
         0.000015225 "shairport.c:1841" busy timeout time is 120.
         0.000012921 "shairport.c:1842" drift tolerance is 0.001995 seconds.
         0.000014249 "shairport.c:1843" password is "(null)".
         0.000012571 "shairport.c:1844" ignore_volume_control is 0.
         0.000013201 "shairport.c:1848" volume_max_db is not set
         0.000012432 "shairport.c:1849" volume range in dB (zero means use the range specified by the mixer): 0.
         0.000015715 "shairport.c:1851" volume_range_combined_hardware_priority (1 means hardware mixer attenuation is used first) is 0.
         0.000044839 "shairport.c:1855" playback_mode is 0 (0-stereo, 1-mono, 1-reverse_stereo, 2-both_left, 3-both_right).
         0.000016762 "shairport.c:1857" disable_synchronization is 0.
         0.000012642 "shairport.c:1858" use_mmap_if_available is 1.
         0.000012991 "shairport.c:1859" output_format automatic selection is enabled.
         0.000015156 "shairport.c:1863" output_rate automatic selection is enabled.
         0.000014877 "shairport.c:1867" audio backend desired buffer length is 0.200000 seconds.
         0.000015644 "shairport.c:1869" audio_backend_buffer_interpolation_threshold_in_seconds is 0.120000 seconds.
         0.000016344 "shairport.c:1871" audio backend latency offset is 0.000000 seconds.
         0.000015156 "shairport.c:1873" audio backend silence lead-in time is "auto".
         0.000014876 "shairport.c:1877" zeroconf regtype is "_raop._tcp".
         0.000014248 "shairport.c:1878" decoders_supported field is 3.
         0.000013341 "shairport.c:1879" use_apple_decoder is 1.
         0.000013340 "shairport.c:1880" alsa_use_hardware_mute is 0.
         0.000022489 "shairport.c:1884" no special mdns service interface was requested.
         0.000168393 "shairport.c:1887" configuration file name "/etc/shairport-sync.conf" resolves to "/etc/shairport-sync.conf".
         0.000018089 "shairport.c:1894" metadata enabled is 1.
         0.000012432 "shairport.c:1895" metadata pipename is "/tmp/shairport-sync-metadata".
         0.000013270 "shairport.c:1896" metadata socket address is "(null)" port 0.
         0.000016344 "shairport.c:1898" metadata socket packet size is "500".
         0.000013270 "shairport.c:1899" get-coverart is 1.
         0.000012502 "shairport.c:1902" mqtt is disabled.
         0.000012292 "shairport.c:1903" mqtt hostname is (null), port is 1883.
         0.000011943 "shairport.c:1904" mqtt topic is /LibreELECWyse.
         0.000012014 "shairport.c:1905" mqtt will not publish raw metadata.
         0.000011803 "shairport.c:1906" mqtt will not publish parsed metadata.
         0.000013480 "shairport.c:1907" mqtt will not publish cover Art.
         0.000011873 "shairport.c:1908" mqtt remote control is disabled.
         0.000011874 "shairport.c:1912" convolution is 0.
         0.000008730 "shairport.c:1913" convolution IR file is "(null)"
         0.000008940 "shairport.c:1914" convolution max length 8192
         0.000011803 "shairport.c:1915" convolution gain is 0.000000
         0.000012363 "shairport.c:1917" loudness is 0.
         0.000011524 "shairport.c:1918" loudness reference level is -20.000000
         0.000113495 "rtsp.c:1665" metadata pipe name is "/tmp/shairport-sync-metadata".
         0.001747830 "rtsp.c:2887" unable to listen on IPv4 port 5000. The error is: "Address in use".
         0.000059576 "rtsp.c:2887" unable to listen on IPv6 port 5000. The error is: "Address in use".
         0.000021303 "rtsp.c:3018" *fatal error: could not establish a service on port 5000 -- program terminating. Is another instance of Shairport Sync running on this device?
         0.000019137 "shairport.c:1424" emergency exit

Thanks again!

@mikebrady
Copy link
Owner

mikebrady commented Jul 25, 2021

Thanks again. So one slightly wild thing to try is the AirPlay 2 development version. This is a bigger download, but, for development reasons, it doesn't use that extra shairport-sync user, so it would give a more direct read on the situation:

$ docker run -d --restart unless-stopped --net host --device /dev/snd --group-add 63 mikebrady/shairport-sync:unstable-development

I think it's worth a try.

@iVolt1
Copy link
Author

iVolt1 commented Jul 27, 2021

Hi Mike.

It seems it is not taking the -- -d hw:0,3 and other parameters and only looking for the "default" device. I tried a lot of variations beides these:

LibreELECWyse:~ # docker run -d --name WyseAP2 --restart unless-stopped  --privileged  --net host --device /dev/snd --
group-add 63 mikebrady/shairport-sync:unstable-development -- -d hw:0,3 -a WyseAP2 -p 5002
LibreELECWyse:~ # docker run -d --name WyseAP2 --restart unless-stopped  --privi
leged  --net host --device /dev/snd --group-add 63 mikebrady/shairport-sync:unst
able-development -d hw:0,3 -a WyseAP2 -p 5002 --
Connecting from iPhone 7:
1.489125750 "shairport.c:211" "soxr" interpolation has been chosen.
30.733735327 "rtsp.c:2179" Connection 2. Realtime Audio Stream Detected.
ALSA lib pcm_dmix.c:1089:(snd_pcm_dmix_open) unable to open slave
0.007301993 "audio_alsa.c:437" *fatal error: the alsa output_device "default" can not be found.   
Connecting from Tuneblade
1.488304959 "shairport.c:211" "soxr" interpolation has been chosen.
3.044121184 "rtsp.c:3457" Connection 2. AirPlay 1 Audio Stream Detected.
ALSA lib pcm_dmix.c:1089:(snd_pcm_dmix_open) unable to open slave
 0.008927452 "audio_alsa.c:437" *fatal error: the alsa output_device "default" can not be found.
LibreELECWyse:~ # docker exec -it WyseAP2 shairport-sync -h
Usage: shairport-sync [options...]
  or:  shairport-sync [options...] -- [audio output-specific options]

Options:
    -h, --help              show this help.
    -V, --version           show version information.
    -c, --configfile=FILE   read configuration settings from FILE. Default is /etc/shairport-sync.conf.

The following general options are for backward compatibility. These and all new options have settings in the configuration file, by default /etc/shairport-sync.conf:
    -v, --verbose           -v print debug information; -vv more; -vvv lots.
    -p, --port=PORT         set RTSP listening port.
    -a, --name=NAME         set advertised name.
    -L, --latency=FRAMES    [Deprecated] Set the latency for audio sent from an unknown device.
                            The default is to set it automatically.
    -S, --stuffing=MODE set how to adjust current latency to match desired latency, where
                            "basic" inserts or deletes audio frames from packet frames with low processor overhead, and
                            "soxr" uses libsoxr to minimally resample packet frames -- moderate processor overhead.
                            "soxr" option only available if built with soxr support.
    -B, --on-start=PROGRAM  run PROGRAM when playback is about to begin.
    -E, --on-stop=PROGRAM   run PROGRAM when playback has ended.
                            For -B and -E options, specify the full path to the program, e.g. /usr/bin/logger.
                            Executable scripts work, but must have the appropriate shebang (#!/bin/sh) in the headline.
    -w, --wait-cmd          wait until the -B or -E programs finish before continuing.
    -o, --output=BACKEND    select audio output method.
    -m, --mdns=BACKEND      force the use of BACKEND to advertize the service.
                            if no mdns provider is specified,
                            shairport tries them all until one works.
    -r, --resync=THRESHOLD  [Deprecated] resync if error exceeds this number of frames. Set to 0 to stop resyncing.
    -t, --timeout=SECONDS   go back to idle mode from play mode after a break in communications of this many seconds (default 120). Set to 0 never to exit play mode.
    --statistics            print some interesting statistics -- output to the logfile if running as a daemon.
    --tolerance=TOLERANCE   [Deprecated] allow a synchronization error of TOLERANCE frames (default 88) before trying to correct it.
    --password=PASSWORD     require PASSWORD to connect. Default is not to require a password.
    --logOutputLevel        log the output level setting -- useful for setting maximum volume.
    -M, --metadata-enable   ask for metadata from the source and process it.
    --metadata-pipename=PIPE send metadata to PIPE, e.g. --metadata-pipename=/tmp/shairport-sync-metadata.
                            The default is /tmp/shairport-sync-metadata.
    -g, --get-coverart      send cover art through the metadata pipe.
    -u, --use-stderr        log messages through STDERR rather than the system log.

Available mDNS backends:
    avahi

Available audio backends:
    alsa (default)
    pipe
    stdout
    dummy

Settings and options for the audio backend "alsa":
    -d output-device    set the output device, default is "default".
    -c mixer-control    set the mixer control name, default is to use no mixer.
    -m mixer-device     set the mixer device, default is the output device.
    -i mixer-index      set the mixer index, default is 0.
    hardware output devices:
      "hw:Generic"
      "hw:HDMI"

Settings and options for the audio backend "pipe":
    specify the pathname of the pipe to write to.

There are no settings or options for the audio backend "stdout".

There are no settings or options for the audio backend "dummy".

Thanks again.

@mikebrady
Copy link
Owner

Thanks for this. Here is an interesting issue, just concluded, that seems to parallel yours to some extent.

@iVolt1
Copy link
Author

iVolt1 commented Aug 3, 2021

HI Mike. robacst did leave much context for what he did with 'mount /etc/asound.conf:/etc/asound.conf'. I would like to try the same if I knew where to put it and what the syntax is. Do you have some idea?

Thanks again,.

@iVolt1
Copy link
Author

iVolt1 commented Aug 8, 2021

I made a docker container to run speaker-test and did get sound output using Libreelec attached to my 7.1 reciever in both 2 channel and 8 channel so I think it might not be Libreelec blocking acces to the sound card.

Dockerfile:

FROM alpine:3.12

RUN apk --no-cache add alsa-utils

CMD [ "sh" ]
LibreELECWyse:~ # docker run --rm --privileged --device /dev/snd aucdb speaker-test -D hdmi:CARD=HDMI,DEV=0 -c 2 -b544000

speaker-test 1.2.2

Playback device is hdmi:CARD=HDMI,DEV=0
Stream parameters are 48000Hz, S16_LE, 2 channels
Using 16 octaves of pink noise
Rate set to 48000Hz (requested 48000Hz)
Buffer size range from 64 to 8544000
Period size range from 32 to 4272000
Requested buffer time 544000 us
Periods = 4
was set period_size = 6528
was set buffer_size = 26112
0 - Front Left
1 - Front Right
Time per period = 5.453585
0 - Front Left
...

@mikebrady
Copy link
Owner

Fantastic stuff. Now, could you run there speaker test at a rate of 44100, see if it works? I think you'd add -r 44100 to the options...

@iVolt1
Copy link
Author

iVolt1 commented Aug 8, 2021

44100 works too and is audible.

LibreELECWyse:~/.kodi/userdata/dockercdb/alsacdbDf # docker run --rm --privilege
d --device /dev/snd aucdb speaker-test -D hdmi:CARD=HDMI,DEV=0 -c 2 -b544000 -r
44100

speaker-test 1.2.2

Playback device is hdmi:CARD=HDMI,DEV=0
Stream parameters are 44100Hz, S16_LE, 2 channels
Using 16 octaves of pink noise
Rate set to 44100Hz (requested 44100Hz)
Buffer size range from 64 to 7849792
Period size range from 32 to 3924896
Requested buffer time 544000 us
Periods = 4
was set period_size = 4800
was set buffer_size = 24000
 0 - Front Left
 1 - Front Right
Time per period = 5.343581
 0 - Front Left
 1 - Front Right
Time per period = 5.879960
 0 - Front Left
 1 - Front Right

Thanks again.

@mikebrady
Copy link
Owner

That’s good stuff. Can I ask what the aucdb In the command line means please?

@iVolt1
Copy link
Author

iVolt1 commented Aug 8, 2021

Sure. That's the semi-random name of the container made with "docker build -t aucdb ."

@mikebrady
Copy link
Owner

Thanks for the info. Yikes, we might be related. It seems we've been here in Dublin since before 1600. But TBH it's a common enough surname. Let me experiment a little here.

@mikebrady
Copy link
Owner

So, doing a little experiment here, Shairport Sync should accept an output_device = hdmi:CARD=HDMI,DEV=0;, i.e. the same as:

$ aplay -L

returns.

@iVolt1
Copy link
Author

iVolt1 commented Aug 13, 2021

Hi Mike. I tried hdmi:CARD=HDMI,DEV=0 and get the same kind of errors. Running speaker-test with the same device name works fine.

One thing that seems like an anomaly is the PCM mixer is on card 1, not card 0 per amixer -cx whereas aplay implies the hdmi card is card 0.

I looked through the alsa C code for speaker-test and shairport-sync and it seems like maybe they take different code paths getting to or following snd_pcm_open().

I did get the python airplay2 receiver to work in docker with an amixer tweak. More on that below.

Thanks again.

From /storage/.kodi/userdata/dockercdb/shairport-sync.conf:

alsa =
{
        output_device = "hdmi:CARD=HDMI,DEV=0"; // the name of the alsa output device. Use "shairport-sync -h" to discover the names of ALSA hardware devices. Use "alsamixer" or "aplay" to find out the names o>
//      mixer_control_name = "PCM"; // ...
$ docker run -d --restart unless-stopped --net host --volume /storage/.kodi/userdata/dockercdb/shairport-sync.conf:/etc/shairport-sync.conf --device /dev/snd mikebrady/shairport-sync -a DenSystem

ALSA lib pcm.c:2642:(snd_pcm_open_noupdate) Unknown PCM hdmi:CARD=HDMI,DEV=0
ALSA lib conf.c:5148:(snd_config_expand) Unknown parameters CARD=HDMI,DEV=0
ALSA lib pcm.c:2642:(snd_pcm_open_noupdate) Unknown PCM hdmi:CARD=HDMI,DEV=0
ALSA lib conf.c:5148:(snd_config_expand) Unknown parameters CARD=HDMI,DEV=0

Running speaker-test with the same device name works fine:

$ docker exec -it --privileged --device /dev/snd aucdb speaker-test -D hdmi:CARD=HDMI,DEV=0  -c 8 -b544000

FROM 	alpine:3.12

RUN apk --no-cache add alsa-utils

CMD [ "sh" ]


LibreELECWyse:~/.kodi/userdata/dockercdb # amixer --c 0
Simple mixer control 'IEC958',0
  Capabilities: pswitch pswitch-joined
  Playback channels: Mono
  Mono: Playback [on]
Simple mixer control 'IEC958',1
  Capabilities: pswitch pswitch-joined
  Playback channels: Mono
  Mono: Playback [on]
LibreELECWyse:~/.kodi/userdata/dockercdb #
LibreELECWyse:~/.kodi/userdata/dockercdb # amixer --c 1
Simple mixer control 'Master',0
  Capabilities: pvolume pvolume-joined pswitch pswitch-joined
  Playback channels: Mono
  Limits: Playback 0 - 87
  Mono: Playback 87 [100%] [0.00dB] [on]
Simple mixer control 'Headphone',0
  Capabilities: pvolume pswitch
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 87
  Mono:
  Front Left: Playback 87 [100%] [0.00dB] [on]
  Front Right: Playback 87 [100%] [0.00dB] [on]
Simple mixer control 'Speaker',0
  Capabilities: pvolume pswitch pswitch-joined
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 87
  Mono:
  Front Left: Playback 87 [100%] [0.00dB] [on]
  Front Right: Playback 87 [100%] [0.00dB] [on]
Simple mixer control 'PCM',0
  Capabilities: pvolume
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 255
  Mono:
  Front Left: Playback 255 [100%] [0.00dB]
  Front Right: Playback 255 [100%] [0.00dB]
Simple mixer control 'Mic',0
  Capabilities: pvolume pswitch
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 31
  Mono:
  Front Left: Playback 0 [0%] [-34.50dB] [off]
  Front Right: Playback 0 [0%] [-34.50dB] [off]
Simple mixer control 'Mic Boost',0
  Capabilities: volume
  Playback channels: Front Left - Front Right
  Capture channels: Front Left - Front Right
  Limits: 0 - 3
  Front Left: 0 [0%] [0.00dB]
  Front Right: 0 [0%] [0.00dB]
Simple mixer control 'Beep',0
  Capabilities: pvolume pswitch
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 31
  Mono:
  Front Left: Playback 0 [0%] [-34.50dB] [off]
  Front Right: Playback 0 [0%] [-34.50dB] [off]
Simple mixer control 'Capture',0
  Capabilities: cvolume cswitch
  Capture channels: Front Left - Front Right
  Limits: Capture 0 - 31
  Front Left: Capture 0 [0%] [-16.50dB] [off]
  Front Right: Capture 0 [0%] [-16.50dB] [off]
Simple mixer control 'Auto-Mute Mode',0
  Capabilities: enum
  Items: 'Disabled' 'Enabled'
  Item0: 'Enabled'
Simple mixer control 'Loopback Mixing',0
  Capabilities: enum
  Items: 'Disabled' 'Enabled'
  Item0: 'Disabled'
LibreELECWyse:~/.kodi/userdata/dockercdb #

I did get this python airplay2 receiver to run, but sound drops out periodically:

https://github.com/openairplay/airplay2-receiver/tree/master/docker
$ docker run -it --rm --privileged --env AP2IFACE=eth0 --device /dev/snd --net host --volume  /storage/.kodi/userdata/dockercdb/ap2cdbDf/pairings/:/airplay2/pairings/ ap2-receiver

I had to add "-c1" to this line in utils.py in two places to get sound to work since the mixer is on c1, not c0:

//line_pct = subprocess.check_output(["amixer", "get", "PCM"]).splitlines()[-1]
line_pct = subprocess.check_output(["amixer", "-c1", "get", "PCM"]).splitlines()[-1]

    elif subsys == "Linux":
        line_pct = subprocess.check_output(["amixer", "-c1", "get", "PCM"]).splitlines()[-1]
        m = re.search(b"\[([0-9]+)%\]", line_pct)
        if m:
            pct = int(m.group(1))
            if pct < 45:
                pct = 45
        else:
            pct = 50
        vol = interpolate(pct, 45, 100, -30, 0)
    elif subsys == "Windows": ...

@mikebrady
Copy link
Owner

Thanks -- I'd reformatted you post slightly for clarity. I'll take a look at the C code!

@mikebrady
Copy link
Owner

mikebrady commented Aug 14, 2021

Well, I had a look at the C code and speaker-test and shairport-sync don't look terribly different in the way they open the device.

But I did notice that your speaker-test call is for an eight-channel device ("-c 8"). Could you try it with a two-channel device please?

Including a rate request for 44,100 frames per second, this might be something like:

$ docker exec -it --privileged --device /dev/snd aucdb speaker-test -D hdmi:CARD=HDMI,DEV=0  -c 2 -b544000 -r 44100

[Update -- forget this; you've done it already!]

@mikebrady
Copy link
Owner

One other thing I notice is that you tried:

$ docker run -d --restart unless-stopped --net host --volume /storage/.kodi/userdata/dockercdb/shairport-sync.conf:/etc/shairport-sync.conf --device /dev/snd mikebrady/shairport-sync -a DenSystem

and it generated errors, but when you tried:

$ docker exec -it --privileged --device /dev/snd aucdb speaker-test -D hdmi:CARD=HDMI,DEV=0  -c 8 -b544000

it worked. However, in the latter you included the parameter --privileged whereas in the former you omitted it. Would it be worth retrying it with the --privileged parameter included?

@iVolt1
Copy link
Author

iVolt1 commented Aug 14, 2021

Hi Mike. I have done so many permutations I that I did not pay attention to --privileged, but it turns out that is not required after all.

I started by running another instance within the container (shairport-sync -vu ...) using the portainer terminal ash as root for rapid testing and I had success after specifying output_device = "hdmi:CARD=HDMI,DEV=0" and output_format = "S16_LE" in the alsa section. I tried most of the output formats and only that one worked. I had this same output format issue with a DAC on OpenWRT but I am surprised it couldn't do better than S16_LE on an hdmi device.

I then spun up a new local container with output_device = "hdmi:CARD=HDMI,DEV=0" and output_format = "S16_LE" but changed start.sh to run shairport-sync as root and everything started to work, so it is definitely the shairport-sync user not having the access it needs. Running without su-exec works also. I think I tried to go down that path before, but I didn't really have enough in place at the time.

#!/bin/sh
#!/bin/sh

set -e

rm -rf /var/run/dbus.pid
#mkdir -p /var/run/dbus

dbus-uuidgen --ensure
dbus-daemon --system

avahi-daemon --daemonize --no-chroot

#su-exec shairport-sync shairport-sync $@ --does not work
#su-exec root shairport-sync $@ --works
shairport-sync $@ # --works
LibreELECWyse:~/.kodi/userdata/dockercdb/spsrootDf # docker run -d \
  --name spsasroot \
  --net host \
  --volume /storage/.kodi/userdata/dockercdb/shairport-sync.conf:/etc/shairport-sync.conf \
  --device /dev/snd spsroot -a RootSystem

I have a working version now. I think the root cause may be that LibreELEC is so stripped down it does not the concept of users other than root.

Along the way I tried spinning up an OpenWRT container and adding Shairport Sync there, but making a fully working OpenWRT container is more difficult than OpenWRT itself. I was glad to see version 3.3.8 in the latest versions.

Long term it would be great to see shairport-sync made into a binary add-on for Kodi.

I will look into getting shairport-sync added to the LinuxServer.io that packages containers for installation as add-ons in LibreELEC.

I will move forward with testing your AirPlay2 version now that I think I can get it to work.

Thanks again for all your help on this.

@iVolt1
Copy link
Author

iVolt1 commented Aug 14, 2021

One other thing. I tried every combination i could think of to get a hardware mixer with no luck,

@mikebrady
Copy link
Owner

Fantastic stuff, thanks. I've taken the liberty of editing for format and for reference for anyone looking at this thread.

There are implications for the standard Docker image -- mainly it is probably a good idea to drop the idea of a shairport-sync user inside the container. The idea was to offer a small measure of extra security because the shairport-sync user would have fewer privileges, but it seems to just get in the way.

(I might copy out the genealogy stuff if that's okay?)

@iVolt1
Copy link
Author

iVolt1 commented Aug 15, 2021 via email

@danifr
Copy link

danifr commented Mar 27, 2022

Thanks Mike for your work on this. It took me some time to figure out how to make it work on my Pi running ArchLinux (alarm) but now it works great.

Anyway for people not using Debian-based operating systems and who want to keep running it root-less, they just need to figure out the GUI of the audio group of their host operating system (in my case alarm):

[root@alarm ~]# getent group audio | cut -d: -f3
996

Then edit the Dockerfile accordingly:

 # Add the shairport-sync user to the pre-existing audio group, which has ID 29, for access to the ALSA stuff
-RUN    addgroup -g 29 docker_audio && addgroup shairport-sync docker_audio
+RUN    addgroup -g 996 docker_audio && addgroup shairport-sync docker_audio

Don't forget to build a new image after making this change.

it is probably a good idea to drop the idea of a shairport-sync user inside the container.

I support this anyway 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants