[GH-ISSUE #523] Playback crashes when switching users and specifying --device #336

Closed
opened 2026-02-27 19:30:05 +03:00 by kerem · 13 comments
Owner

Originally created by @benblasco on GitHub (Sep 17, 2020).
Original GitHub issue: https://github.com/librespot-org/librespot/issues/523

Description

Running librespot with the following command:
ENTRYPOINT /root/.cargo/bin/librespot --name="NUC LibreSpot Speaker" --bitrate=320 --zeroconf-port=49999 --device="hdmi:CARD=PCH,DEV=0" --initial-volume=75 -v

Steps to reproduce:

  1. Start librespot as above
  2. Connect and play some music as Spotify user X (via Android phone client). Music plays without issue
  3. Stop playback (or don't, result is same)
  4. Attempt to connect to play some music as Spotify user Y (via iPad in this case), application crashes with error:
    No output sink matching 'hdmi:CARD=PCH,DEV=0' found.

The problem does not occur if I don't specify the output device with the --device flag, and users can "hijack" each other with no problem. However not specifying --device means sound output is through the device's headphone jack, which is not what I want.

Questions that will contribute to identifying the issue:

  1. Is the problem a flaw in the way the code is implemented in librespot when interpreting the --device flag or something in the way that ALSA works?
  2. What is the default backend librespot uses when none is specified? This is not documented in the "options" page linked here: https://github.com/librespot-org/librespot/wiki/Options

Logs attached below:
librespot_log_working.txt
librespot_log_crashing.txt

Please let me know if there's any additional info I can provide as I do not want to waste anybody's time. I would also be more than happy to contribute to the community with documentation updates etc. so I can play my part!

Originally created by @benblasco on GitHub (Sep 17, 2020). Original GitHub issue: https://github.com/librespot-org/librespot/issues/523 **Description** Running librespot with the following command: `ENTRYPOINT /root/.cargo/bin/librespot --name="NUC LibreSpot Speaker" --bitrate=320 --zeroconf-port=49999 --device="hdmi:CARD=PCH,DEV=0" --initial-volume=75 -v` Steps to reproduce: 1. Start librespot as above 2. Connect and play some music as Spotify user X (via Android phone client). Music plays without issue 3. Stop playback (or don't, result is same) 4. Attempt to connect to play some music as Spotify user Y (via iPad in this case), application crashes with error: `No output sink matching 'hdmi:CARD=PCH,DEV=0' found.` The problem does not occur if I don't specify the output device with the --device flag, and users can "hijack" each other with no problem. However not specifying --device means sound output is through the device's headphone jack, which is not what I want. Questions that will contribute to identifying the issue: 1. Is the problem a flaw in the way the code is implemented in librespot when interpreting the --device flag or something in the way that ALSA works? 2. What is the default backend librespot uses when none is specified? This is not documented in the "options" page linked here: [https://github.com/librespot-org/librespot/wiki/Options](url) Logs attached below: [librespot_log_working.txt](https://github.com/librespot-org/librespot/files/5236701/librespot_log_working.txt) [librespot_log_crashing.txt](https://github.com/librespot-org/librespot/files/5236702/librespot_log_crashing.txt) Please let me know if there's any additional info I can provide as I do not want to waste anybody's time. I would also be more than happy to contribute to the community with documentation updates etc. so I can play my part!
kerem 2026-02-27 19:30:05 +03:00
  • closed this issue
  • added the
    bug
    A-Alsa
    labels
Author
Owner

@benblasco commented on GitHub (Sep 17, 2020):

For additional reference, I am running librespot in a self-built container based on a minimal Fedora 32 image, and am running it with podman rather than Docker. I am also happy to contribute a how-to on this to the community!

<!-- gh-comment-id:693950924 --> @benblasco commented on GitHub (Sep 17, 2020): For additional reference, I am running librespot in a self-built container based on a minimal Fedora 32 image, and am running it with podman rather than Docker. I am also happy to contribute a how-to on this to the community!
Author
Owner

@JasonLG1979 commented on GitHub (Sep 17, 2020):

2. What is the default backend librespot uses when none is specified? This is not documented in the "options" page linked here: https://github.com/librespot-org/librespot/wiki/Options

It will use the system's default device. Which in your case I guess is the headphone jack. If I had to guess it has to do with not properly releasing the sink. The default device works fine I'm guessing because it's routed though ALSA's software mixer, Dmix. Specifying a device directly doesn't go though any sort of mixer so basically it takes total control of the device. Nothing else can open the device. Something is going sideways when you're changing users/accounts.

You can try changing the default device by editing /etc/asound.conf and see if that helps. In your case I think your best best is to just tell Dmix to use your HDMI port as your default device and not use the raw device.

Use the output of aplay -l to find your device.

Here is an example output from one of my Pi Zero's with a USB DAC connected to it.

**** List of PLAYBACK Hardware Devices ****
card 0: Headphones [bcm2835 Headphones], device 0: bcm2835 Headphones [bcm2835 Headphones]
  Subdevices: 8/8
  Subdevice #0: subdevice #0
  Subdevice #1: subdevice #1
  Subdevice #2: subdevice #2
  Subdevice #3: subdevice #3
  Subdevice #4: subdevice #4
  Subdevice #5: subdevice #5
  Subdevice #6: subdevice #6
  Subdevice #7: subdevice #7
card 1: DAC [USB Audio DAC], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

If I want ALSA/Dmix to use the DAC as the default device I would add this to /etc/asound.conf:

defaults.pcm.card 1
defaults.ctl.card 1

Dmix also resamples everything to 48 kHz by default. If you'd like to avoid unnecessary resampling you can add is:

defaults.pcm.dmix.rate 44100
<!-- gh-comment-id:694225176 --> @JasonLG1979 commented on GitHub (Sep 17, 2020): > 2\. What is the default backend librespot uses when none is specified? This is not documented in the "options" page linked here: [https://github.com/librespot-org/librespot/wiki/Options](url) It will use the system's default device. Which in your case I guess is the headphone jack. If I had to guess it has to do with not properly releasing the sink. The default device works fine I'm guessing because it's routed though ALSA's software mixer, Dmix. Specifying a device directly doesn't go though any sort of mixer so basically it takes total control of the device. Nothing else can open the device. Something is going sideways when you're changing users/accounts. You can try changing the default device by editing ```/etc/asound.conf``` and see if that helps. In your case I think your best best is to just tell Dmix to use your HDMI port as your default device and not use the raw device. Use the output of ``` aplay -l``` to find your device. Here is an example output from one of my Pi Zero's with a USB DAC connected to it. ``` **** List of PLAYBACK Hardware Devices **** card 0: Headphones [bcm2835 Headphones], device 0: bcm2835 Headphones [bcm2835 Headphones] Subdevices: 8/8 Subdevice #0: subdevice #0 Subdevice #1: subdevice #1 Subdevice #2: subdevice #2 Subdevice #3: subdevice #3 Subdevice #4: subdevice #4 Subdevice #5: subdevice #5 Subdevice #6: subdevice #6 Subdevice #7: subdevice #7 card 1: DAC [USB Audio DAC], device 0: USB Audio [USB Audio] Subdevices: 1/1 Subdevice #0: subdevice #0 ``` If I want ALSA/Dmix to use the DAC as the default device I would add this to ```/etc/asound.conf```: ``` defaults.pcm.card 1 defaults.ctl.card 1 ``` Dmix also resamples everything to 48 kHz by default. If you'd like to avoid unnecessary resampling you can add is: ``` defaults.pcm.dmix.rate 44100 ```
Author
Owner

@JasonLG1979 commented on GitHub (Sep 17, 2020):

If you need to dig deeper to specify a device and/or subdevice /etc/asound.conf would look something like this:

defaults.pcm.card INT   # Card number (integer)
defaults.ctl.card INT   # Card number (integer)

pcm.rawdevice {
    type hw
    card INT          # Card number (integer)
    device INT        # Device number (integer, default 0)
    subdevice INT     # Subdevice number (integer, default -1: first available)
}

pcm.dmixer {
    type dmix
    ipc_key 1024
    ipc_perm 0666
    slave {
        pcm "rawdevice"
        rate 44100
        format S16_LE
    }
    bindings {
        0 0
        1 1
    }
}

pcm.softvol {
    type softvol
    slave.pcm "dmixer"
    control {
        name "PCM"
        card INT          # Card number (integer)
        device INT        # Device number (integer, default 0)
        subdevice INT     # Subdevice number (integer, default -1: first available)
    }
}

pcm.!default {
    type plug
    slave.pcm "softvol"
}

That should get you 16 bit 44.1 kHz output with software mixing and software volume on whatever you configure pcm.rawdevice and pcm.softvol.control to be.

<!-- gh-comment-id:694245830 --> @JasonLG1979 commented on GitHub (Sep 17, 2020): If you need to dig deeper to specify a device and/or subdevice ```/etc/asound.conf``` would look something like this: ``` defaults.pcm.card INT # Card number (integer) defaults.ctl.card INT # Card number (integer) pcm.rawdevice { type hw card INT # Card number (integer) device INT # Device number (integer, default 0) subdevice INT # Subdevice number (integer, default -1: first available) } pcm.dmixer { type dmix ipc_key 1024 ipc_perm 0666 slave { pcm "rawdevice" rate 44100 format S16_LE } bindings { 0 0 1 1 } } pcm.softvol { type softvol slave.pcm "dmixer" control { name "PCM" card INT # Card number (integer) device INT # Device number (integer, default 0) subdevice INT # Subdevice number (integer, default -1: first available) } } pcm.!default { type plug slave.pcm "softvol" } ``` That should get you 16 bit 44.1 kHz output with software mixing and software volume on whatever you configure ```pcm.rawdevice``` and ```pcm.softvol.control``` to be.
Author
Owner

@JasonLG1979 commented on GitHub (Sep 17, 2020):

If you're having trouble matching hdmi:CARD=PCH,DEV=0 to:

        card INT          # Card number (integer)
        device INT        # Device number (integer, default 0)
        subdevice INT     # Subdevice number (integer, default -1: first available)

You can use the output of cat /proc/asound/card*/pcm*/sub*/hw_params while listening to some music with librespot with --device="hdmi:CARD=PCH,DEV=0" The output should be the same order as aplay -l, hdmi:CARD=PCH,DEV=0 should be the device that's not closed.

<!-- gh-comment-id:694267801 --> @JasonLG1979 commented on GitHub (Sep 17, 2020): If you're having trouble matching ```hdmi:CARD=PCH,DEV=0``` to: ``` card INT # Card number (integer) device INT # Device number (integer, default 0) subdevice INT # Subdevice number (integer, default -1: first available) ``` You can use the output of ```cat /proc/asound/card*/pcm*/sub*/hw_params``` while listening to some music with librespot with ```--device="hdmi:CARD=PCH,DEV=0"``` The output should be the same order as ```aplay -l```, ```hdmi:CARD=PCH,DEV=0``` should be the device that's not closed.
Author
Owner

@benblasco commented on GitHub (Sep 18, 2020):

Hi @JasonLG1979,

Firstly, thank you for taking the time to send such a detailed reply. I really appreciate it! Let me address some of what you have said in the messages...

It will use the system's default device. Which in your case I guess is the headphone jack. If I had to guess it has to do with not properly releasing the sink. The default device works fine I'm guessing because it's routed though ALSA's software mixer, Dmix. Specifying a device directly doesn't go though any sort of mixer so basically it takes total control of the device. Nothing else can open the device. Something is going sideways when you're changing users/accounts.

So I don't actually know which backend librespot uses by default. That's one thing that I need to dig into further, and perhaps update the documentation. However I think you have hit the nail on the head in saying that in specifying the device directly, I am taking direct control of the device. However I still think that librespot is doing something incorrectly in trying to access the device a second time rather than cleaning up after itself when the second user takes over the connection.

You can try changing the default device by editing /etc/asound.conf and see if that helps. In your case I think your best best is to just tell Dmix to use your HDMI port as your default device and not use the raw device.

Yep, this is my next step, and I will report back on the results. The initial problem is that my asound.conf is currently empty! This could get tricky. Updates to come...

<!-- gh-comment-id:694679530 --> @benblasco commented on GitHub (Sep 18, 2020): Hi @JasonLG1979, Firstly, thank you for taking the time to send such a detailed reply. I really appreciate it! Let me address some of what you have said in the messages... > It will use the system's default device. Which in your case I guess is the headphone jack. If I had to guess it has to do with not properly releasing the sink. The default device works fine I'm guessing because it's routed though ALSA's software mixer, Dmix. Specifying a device directly doesn't go though any sort of mixer so basically it takes total control of the device. Nothing else can open the device. Something is going sideways when you're changing users/accounts. So I don't actually know which _backend_ librespot uses by default. That's one thing that I need to dig into further, and perhaps update the documentation. However I think you have hit the nail on the head in saying that in specifying the device directly, I am taking direct control of the device. However I still think that librespot is doing something incorrectly in trying to access the device a second time rather than cleaning up after itself when the second user takes over the connection. > You can try changing the default device by editing /etc/asound.conf and see if that helps. In your case I think your best best is to just tell Dmix to use your HDMI port as your default device and not use the raw device. Yep, this is my next step, and I will report back on the results. The initial problem is that my asound.conf is currently empty! This could get tricky. Updates to come...
Author
Owner

@JasonLG1979 commented on GitHub (Sep 18, 2020):

@eraser215

I don't actually know which backend librespot uses by default.

This says that Rodio is the default backend. For a headless Linux system I'd just use the alsa backend and talk directly to ALSA instead of though some abstraction layer. Backends are compile time options. So you may not have the alsa backend. I'm not sure with what options the binary you're using was compiled with? You can find out really quick by running librespot with --backend alsa.

I still think that librespot is doing something incorrectly in trying to access the device a second time rather than cleaning up after itself when the second user takes over the connection.

That's kinda what it looks like to me to but I'm not an expert in ALSA nor Rust so I can't say for sure.

<!-- gh-comment-id:694711073 --> @JasonLG1979 commented on GitHub (Sep 18, 2020): @eraser215 > I don't actually know which backend librespot uses by default. [This](https://github.com/librespot-org/librespot#additional-dependencies) says that Rodio is the default backend. For a headless Linux system I'd just use the alsa backend and talk directly to ALSA instead of though some abstraction layer. Backends are compile time options. So you may not have the alsa backend. I'm not sure with what options the binary you're using was compiled with? You can find out really quick by running librespot with ``` --backend alsa```. > I still think that librespot is doing something incorrectly in trying to access the device a second time rather than cleaning up after itself when the second user takes over the connection. That's kinda what it looks like to me to but I'm not an expert in ALSA nor Rust so I can't say for sure.
Author
Owner

@ashthespy commented on GitHub (Sep 18, 2020):

So I don't actually know which backend librespot uses by default.

Looking at your logs, you are on rodio

[librespot_playback::audio_backend::rodio] Using rodio sink

I'm not sure with what options the binary you're using was compiled with? You can find out really quick by running librespot with --backend alsa.

You could also use the the --backend ? flag to list what backends are available.

<!-- gh-comment-id:694746050 --> @ashthespy commented on GitHub (Sep 18, 2020): > So I don't actually know which _backend_ librespot uses by default. Looking at your logs, you are on `rodio` ``` [librespot_playback::audio_backend::rodio] Using rodio sink ``` > I'm not sure with what options the binary you're using was compiled with? You can find out really quick by running librespot with ` --backend alsa`. You could also use the the [`--backend ?` flag](https://github.com/librespot-org/librespot/wiki/Options) to list what backends are available.
Author
Owner

@JasonLG1979 commented on GitHub (Sep 18, 2020):

You could also use the the --backend ? flag to list what backends are available.

That don't work for me at least with the version complied from raspotify, neither does -h. Both just throw error: Required option 'name' missing and gives a list of the options.

<!-- gh-comment-id:694758891 --> @JasonLG1979 commented on GitHub (Sep 18, 2020): > You could also use the the [`--backend ?` flag](https://github.com/librespot-org/librespot/wiki/Options) to list what backends are available. That don't work for me at least with the version complied from raspotify, neither does ```-h```. Both just throw ```error: Required option 'name' missing``` and gives a list of the options.
Author
Owner

@JasonLG1979 commented on GitHub (Sep 18, 2020):

My guess is the binary is complied without debugging maybe?

<!-- gh-comment-id:694760547 --> @JasonLG1979 commented on GitHub (Sep 18, 2020): My guess is the binary is complied without debugging maybe?
Author
Owner

@JasonLG1979 commented on GitHub (Sep 18, 2020):

Nope. Apparently your command line args are messed up to get the expected result I have to do librespot -n dummy --backend ?

Then I get:

Available Backends : 
- alsa (default)
- pipe
- subprocess
<!-- gh-comment-id:694763332 --> @JasonLG1979 commented on GitHub (Sep 18, 2020): Nope. Apparently your command line args are messed up to get the expected result I have to do ```librespot -n dummy --backend ?``` Then I get: ``` Available Backends : - alsa (default) - pipe - subprocess ```
Author
Owner

@JasonLG1979 commented on GitHub (Sep 18, 2020):

IMHO you shouldn't have to pass a name if you're using ?.

<!-- gh-comment-id:694764799 --> @JasonLG1979 commented on GitHub (Sep 18, 2020): IMHO you shouldn't have to pass a name if you're using ?.
Author
Owner

@JasonLG1979 commented on GitHub (Sep 18, 2020):

I don't know Rust but this seems to imply that name is a required argument, the only required argument in fact. It should probably be turned into a soft requirement and parsed after the args that take a ?. Meaning when you hit a ? you break and output whatever and you don't care about name but if you don't and there's no name you fail.

<!-- gh-comment-id:694770994 --> @JasonLG1979 commented on GitHub (Sep 18, 2020): I don't know Rust but [this](https://github.com/librespot-org/librespot/blob/7626a700366bca5e985e77f4a746a1a05cc94e31/src/main.rs#L101) seems to imply that name is a required argument, the only required argument in fact. It should probably be turned into a soft requirement and parsed after the args that take a ?. Meaning when you hit a ? you break and output whatever and you don't care about name but if you don't and there's no name you fail.
Author
Owner

@roderickvd commented on GitHub (Jun 14, 2021):

Closing this after no further replies. Feel free to reopen if this still an issue with librespot and not your configuration. Principally connecting from different users and switching between them works fine on librespot.

<!-- gh-comment-id:860568514 --> @roderickvd commented on GitHub (Jun 14, 2021): Closing this after no further replies. Feel free to reopen if this still an issue with `librespot` and not your configuration. Principally connecting from different users and switching between them works fine on `librespot`.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/librespot#336
No description provided.