mirror of
https://github.com/librespot-org/librespot.git
synced 2026-04-27 08:15:50 +03:00
[GH-ISSUE #1057] Error and termination when audio interface is removed or not available #497
Labels
No labels
A-Alsa
SpotifyAPI
Tokio 1.0
audio
bug
can't reproduce
compilation
dependencies
duplicate
enhancement
good first issue
help wanted
high priority
imported
imported
invalid
new api
pull-request
question
reverse engineering
wiki
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/librespot#497
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @tweisberger on GitHub (Sep 5, 2022).
Original GitHub issue: https://github.com/librespot-org/librespot/issues/1057
Describe the bug
When the audio device is removed while Spotify connected to
librespotendpoint or when connect while audio interface is not present,librespotterminates.librespotshould handle this gracefully. This requires manual intervention.This use case is using an external DAC connected to USB. When the DAC is set to another input away from USB, it removes the connection. Expected behavior would be to gracefully disconnect from Spotify. Or in the case where the audio device is not present, reject an incoming connection.
To reproduce
Steps to reproduce the behavior 1: _Audio interface is removed after connect: _
librespot).librespotwithsudo librespot --name Livingroom --bitrate 320 --format S16 --mixer softvol --initial-volume 70 --volume-ctrl log --volume-range 60 --autoplay --cache /var/local/www/spotify_cache --disable-audio-cache --backend alsa --device _audioout --onevent /var/local/www/commandw/spotevent.shBehavior 2: Audio interface is not present when connecting :
librespotwithsudo librespot --name Livingroom --bitrate 320 --format S16 --mixer softvol --initial-volume 70 --volume-ctrl log --volume-range 110 --autoplay --cache /var/local/www/spotify_cache --disable-audio-cache --backend alsa --device _audioout --onevent /var/local/www/commandw/spotevent.shLog
Behavior 1 :
[2022-08-31T22:09:38Z WARN librespot_playback::audio_backend::alsa] Error writing from AlsaSink buffer to PCM, trying to recover, ALSA function 'snd_pcm_writei' failed with error 'EIO: I/O error' [2022-08-31T22:09:38Z ERROR librespot_playback::player] Audio Sink Error On Write: <AlsaSink> ALSA function 'snd_pcm_recover' failed with error 'EIO: I/O error' pi@moode:~ $Behavior 2:
[2022-08-31T22:07:05Z TRACE librespot_playback::player] == Starting sink == ALSA lib pcm_hw.c:1829:(_snd_pcm_hw_open) Invalid value for card [2022-08-31T22:07:05Z ERROR librespot_playback::player] Audio Sink Error Connection Refused: <AlsaSink> Device _audioout May be Invalid, Busy, or Already in Use, ALSA function 'snd_pcm_open' failed with error 'ENOENT: No such file or directory' pi@moode:~ $Host
88e64bd(Built on 2022-07-07, Build ID: jEVg9nf8, Profile: release)Connecting Device
Additional context
In the case of moOde,
librespotterminates, and the device becomes unusable until the user connects to the web ui and manually restartslibrespot@JasonLG1979 commented on GitHub (Sep 8, 2022):
This is not a bug. This is a user/consumer error. It is up to moode to:
And
@JasonLG1979 commented on GitHub (Sep 8, 2022):
Ok a further breakdown now that I'm home.
In that case librespot logs an error message and exits with an exit status of 1 indicating an error. This is expected behavior.
The same as above. On
devat least and possibly onmaster(?) librespot does disconnect from Spotify.When librespot is not playing it closes the device and when it starts playing it tries to open the device. We do not monitor the status of devices we are not using and I'm unaware of any plans to do so.
There are blocking sink events you can subscribe to via an onevent script that will allow you to tell when librespot is about to try to open the device and/or has closed the device. In your onevent script you can do whatever you need to do to make sure the device you have told librespot to use actually exists and is available to use.
@JasonLG1979 commented on GitHub (Sep 9, 2022):
You can use
--emit-sink-events --onevent=path/to/my/scriptEvents are sent as environment variables.An example script:
@roderickvd commented on GitHub (Sep 10, 2022):
Principally it is a fair use case as some good DACs indeed may turn off their USB circuitry when switched to another source, to minimize electrical noise.
However does this bug still happen if you stop Spotify first? Then switch input and back, start Spotify playback? From a code review I think that might work.
Otherwise on a failed write we could consider reopening the device one time only, then retry the write.
@JasonLG1979 commented on GitHub (Sep 10, 2022):
It's essentially the equivalent of unplugging a DAC during playback.
If Spotify stops then librespot closes the device. But all these things happen asyc so you would have to stop well in advance to prevent player from pushing bytes to the device.
That's basically what
try_recoverin the ALSA Sink does. If we get the error in player it is fatal to the sink. What I can do is stop the sink and signal a disconnect from player. I just so happen to make that possible in my latest PR, but I still stand by my statement that it's not our responsibility to keep track of devices, that's the job of whatever daemonizes librespot. I will finish up the bits to make it work.Currently the best thing for moode to do is just restart librespot when it happens. That's what systemd does and although it's not elegant it works fine.
@roderickvd commented on GitHub (Sep 10, 2022):
I agree. If it's relatively easy though I guess it'd be a quick win.
@JasonLG1979 commented on GitHub (Sep 10, 2022):
I got you one better. Instead of stopping and disconnecting I made it so that it just tells Spotify we're paused when the sink errors out.
So when a device disappears we just tell Spotify we're paused. While it's gone you can smash play all you want and you'll get a bunch of errors in the log but we won't exit or crash. After the device shows back up if you hit play it continues playback were you left off.
I tested it by unplugging and plugging my DAC and it seems to work pretty well.
@JasonLG1979 commented on GitHub (Sep 10, 2022):
Basically the same thing will happen if a user tells librespot to use an invalid device. We won't exit or crash but you'll get a lot of errors and Spotify will just refuse to play no matter how hard you smash the play button.
@roderickvd commented on GitHub (Sep 10, 2022):
Great idea!
@JasonLG1979 commented on GitHub (Sep 10, 2022):
Ok I added it to that massive PR. Give it a test.
@JasonLG1979 commented on GitHub (Sep 10, 2022):
There is still no way currently to programmatically tell librespot to pause from the outside without using the spotify api though. I've got a REST style command API in the works so users and consumers can tell librespot to do basic commands. I'm thinking all POST's. Info would still be gotten from events.
@roderickvd commented on GitHub (Jan 14, 2023):
Closing this now I think that @JasonLG1979 made quite some effort on this a few months ago.