[GH-ISSUE #848] Underrun with onevent script #427

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

Originally created by @dubo-dubon-duponey on GitHub (Sep 19, 2021).
Original GitHub issue: https://github.com/librespot-org/librespot/issues/848

Originally assigned to: @roderickvd on GitHub.

Hi,

I recently added an onevent handler to my rig (rpi3).
Since then, I'm getting a significant amount of:

ALSA lib pcm.c:8545:(snd_pcm_recover) underrun occurred

That seems to be related to my event handler script (which is basically retrieving artwork then pushing that on a framebuffer).

Assuming my underrun problem(s) is indeed because of my script, this makes we wonder: is the call to the script blocking from librespot?

If the answer is "yes", is there a reason for it to be that way?

Originally created by @dubo-dubon-duponey on GitHub (Sep 19, 2021). Original GitHub issue: https://github.com/librespot-org/librespot/issues/848 Originally assigned to: @roderickvd on GitHub. Hi, I recently added an onevent handler to my rig (rpi3). Since then, I'm getting a significant amount of: `ALSA lib pcm.c:8545:(snd_pcm_recover) underrun occurred` That seems to be related to my event handler script (which is basically retrieving artwork then pushing that on a framebuffer). Assuming my underrun problem(s) is indeed because of my script, this makes we wonder: is the call to the script blocking from librespot? If the answer is "yes", is there a reason for it to be that way?
kerem 2026-02-27 19:30:33 +03:00
  • closed this issue
  • added the
    audio
    label
Author
Owner

@roderickvd commented on GitHub (Sep 20, 2021):

Yes, it's now blocking:

github.com/librespot-org/librespot@e27992a754/src/player_event_handler.rs (L84-L88)

Although I can't phantom every use case of what an event script might do, I don't think there's any particular functional reason. Try to remove the wait and see what happens.

Anyone who feels it should block?

<!-- gh-comment-id:923115578 --> @roderickvd commented on GitHub (Sep 20, 2021): Yes, it's now blocking: https://github.com/librespot-org/librespot/blob/e27992a754b840e9c4591ebd32838cadaf51ebe8/src/player_event_handler.rs#L84-L88 Although I can't phantom every use case of what an event script might do, I don't think there's any particular functional reason. Try to remove the `wait` and see what happens. Anyone who feels it *should* block?
Author
Owner

@dubo-dubon-duponey commented on GitHub (Sep 20, 2021):

Thanks.
Meanwhile I changed my script to perform its operations asynchronously and it seems to fix my underrun issues.
I'll confirm with removing the wait.

(and obviously my vote is for "non-blocking" :-))

<!-- gh-comment-id:923124159 --> @dubo-dubon-duponey commented on GitHub (Sep 20, 2021): Thanks. Meanwhile I changed my script to perform its operations asynchronously and it seems to fix my underrun issues. I'll confirm with removing the wait. (and obviously my vote is for "non-blocking" :-))
Author
Owner

@roderickvd commented on GitHub (Oct 4, 2021):

And, have you tried without the wait?

<!-- gh-comment-id:933753210 --> @roderickvd commented on GitHub (Oct 4, 2021): And, have you tried without the `wait`?
Author
Owner

@dubo-dubon-duponey commented on GitHub (Oct 4, 2021):

On it now, and will send a PR if everything checks out.

Would love to have this for 0.3 of course. Apologies for the delay here.

<!-- gh-comment-id:933867968 --> @dubo-dubon-duponey commented on GitHub (Oct 4, 2021): On it now, and will send a PR if everything checks out. Would love to have this for 0.3 of course. Apologies for the delay here.
Author
Owner

@dubo-dubon-duponey commented on GitHub (Oct 4, 2021):

@roderickvd did more reading.

As far as I can tell:

The line linked over here ^ appears to be just for sink events, which do not seem to be emitted by default. Also, blocking sink events was added by @kaymes at #449 and there was / is apparently a legitimate use case for it, outlined in #406.

On the other hand, it appears that run_program_on_events is not blocking (though my rust skills are limited, so...)

Then it's not clear to me why I'm getting underruns - but it also does not seem to be related to github.com/librespot-org/librespot@e27992a754/src/player_event_handler.rs (L84-L88)

<!-- gh-comment-id:933938719 --> @dubo-dubon-duponey commented on GitHub (Oct 4, 2021): @roderickvd did more reading. As far as I can tell: The line linked over here ^ appears to be just for sink events, which do not seem to be emitted by default. Also, *blocking* sink events was added by @kaymes at #449 and there was / is apparently a legitimate use case for it, outlined in #406. On the other hand, it appears that run_program_on_events is not blocking (though my rust skills are limited, so...) Then it's not clear to me why I'm getting underruns - but it also does not seem to be related to https://github.com/librespot-org/librespot/blob/e27992a754b840e9c4591ebd32838cadaf51ebe8/src/player_event_handler.rs#L84-L88
Author
Owner

@kaymes commented on GitHub (Oct 5, 2021):

The sink events are the only ones that are blocking. They are intended to allow a script to free the sink before librespot opens it. E.g. another player must be stopped before librespot can claim the audio device. So it must be blocking. The blocking events are only emitted if you give "--emit-sink-events". So not giving this argument won't emit any blocking events.

For your use case you probably want your script to react to the "changed" and "started" player events. One of them is triggered whenever a new track is loaded. So your script should look at the "PLAYER_EVENT" environment variable and only do work if it contains "changed" or "started".
You could also listen for the "playing" event.

See here for a description of the events (except for the sink event which is handled a different way).
github.com/librespot-org/librespot@e27992a754/playback/src/player.rs (L92)

<!-- gh-comment-id:933948971 --> @kaymes commented on GitHub (Oct 5, 2021): The sink events are the only ones that are blocking. They are intended to allow a script to free the sink before librespot opens it. E.g. another player must be stopped before librespot can claim the audio device. So it must be blocking. The blocking events are only emitted if you give "--emit-sink-events". So not giving this argument won't emit any blocking events. For your use case you probably want your script to react to the "changed" and "started" player events. One of them is triggered whenever a new track is loaded. So your script should look at the "PLAYER_EVENT" environment variable and only do work if it contains "changed" or "started". You could also listen for the "playing" event. See here for a description of the events (except for the sink event which is handled a different way). https://github.com/librespot-org/librespot/blob/e27992a754b840e9c4591ebd32838cadaf51ebe8/playback/src/player.rs#L92
Author
Owner

@dubo-dubon-duponey commented on GitHub (Oct 5, 2021):

Thanks @kaymes

Yeah, so, the (underruns) issue I was facing was when using a script handling the player events (confirming that I was not consuming sink-events).

We initially thought the calls were blocking, but since this is not the case for player events...
It's not clear to me why I got these underruns...

<!-- gh-comment-id:933954133 --> @dubo-dubon-duponey commented on GitHub (Oct 5, 2021): Thanks @kaymes Yeah, so, the (underruns) issue I was facing was when using a script handling the player events (confirming that I was *not* consuming sink-events). We initially thought the calls were blocking, but since this is not the case for player events... It's not clear to me why I got these underruns...
Author
Owner

@kaymes commented on GitHub (Oct 5, 2021):

Maybe it's as simple as your script using the network too much so you get a buffer underrun?

<!-- gh-comment-id:933970204 --> @kaymes commented on GitHub (Oct 5, 2021): Maybe it's as simple as your script using the network too much so you get a buffer underrun?
Author
Owner

@dubo-dubon-duponey commented on GitHub (Oct 5, 2021):

Maybe it's as simple as your script using the network too much so you get a buffer underrun?

That could be of course (or any other form or resource exhaustion given it's a RPI).
But then, the script merely retrieves cover art from Spotify using curl (the machine is using ethernet, with a decent internet connection).

I think we can close this issue for now - I do not have a good repro and no confirmed explanation unfortunately, so it's not actionable...

Thank you both for taking the time though. Appreciate that.

<!-- gh-comment-id:933973073 --> @dubo-dubon-duponey commented on GitHub (Oct 5, 2021): > Maybe it's as simple as your script using the network too much so you get a buffer underrun? That could be of course (or any other form or resource exhaustion given it's a RPI). But then, the script merely retrieves cover art from Spotify using curl (the machine is using ethernet, with a decent internet connection). I think we can close this issue for now - I do not have a good repro and no confirmed explanation unfortunately, so it's not actionable... Thank you both for taking the time though. Appreciate that.
Author
Owner

@roderickvd commented on GitHub (Oct 5, 2021):

OK. I'll close for now. Two leads you might pursue for your underrun issue:

  1. Is your sound card on USB? I think that up to RPi 3B+ the USB bus and Ethernet card share a path and have to compete;
  2. How big are those covers? Probably not big, but if they are... RPi's are known to be blocking when doing I/O writes.

Thanks @kaymes for chiming in. If at some point a use case pops up for asynchronous sink events (which I could well phantom) then we could add an advanced command line option for doing sync or async.

<!-- gh-comment-id:934103911 --> @roderickvd commented on GitHub (Oct 5, 2021): OK. I'll close for now. Two leads you might pursue for your underrun issue: 1. Is your sound card on USB? I think that up to RPi 3B+ the USB bus and Ethernet card share a path and have to compete; 2. How big are those covers? Probably not big, but if they are... RPi's are known to be blocking when doing I/O writes. Thanks @kaymes for chiming in. If at some point a use case pops up for asynchronous sink events (which I could well phantom) then we could add an advanced command line option for doing sync or async.
Author
Owner

@kaymes commented on GitHub (Oct 5, 2021):

@roderickvd, there are plenty of other events that fire async when playback starts/stops, so listening to the correct subset of those should cover you already.

<!-- gh-comment-id:934106636 --> @kaymes commented on GitHub (Oct 5, 2021): @roderickvd, there are plenty of other events that fire async when playback starts/stops, so listening to the correct subset of those should cover you already.
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#427
No description provided.