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

Spotify client show track as playing, when it is still loading on librespot #210

Closed
WhiteHatTux opened this issue Apr 26, 2018 · 8 comments

Comments

@WhiteHatTux
Copy link

WhiteHatTux commented Apr 26, 2018

Environment:
rpi3 with current raspbian and raspotify
Apr 21 21:17:11 raspberrypi librespot[518]: INFO:librespot: librespot (raspotify) cb61e22 (2018-03-23). Built on 2018-03-24. Build ID: uvwePBqN (issue is reproducible with current librespot built from master on Ubuntu 17.10)
Android spotify client
pretty slow internet (2-5MBit/s)

Expected behaviour:

  1. Select a song on spotify client, that is not cached locally
  2. song will start loading
  3. progress bar will stay at 0 until playing starts (behaviour of official app, when buffering)
  4. progress bar in client will then move in accordance with ongoing song

Actual behaviour:

  1. Select a song on spotify client, that is not cached locally
  2. song will start loading
  3. progress bar will start running
  4. music will start at some point (usually between 5 to 15 seconds after starting to play)
  5. for the rest of the song progress bar will be advanced of real song for the time needed for loading the track

I presume this is a problem with my internet connection (network is usually stable, but painfully slow). It only appears on songs that are loaded from internet. Cached songs work as expected. (playing starts immediately)

I started looking into the code and the spotify web api.
Apparently there is currently no way to send state "buffering/loading" to the client.
Current situation causes confusion, because information on app screen (status playing, time running) is not consistent with real situation (status paused, but playing scheduled after loading)
Setting status to pause will cause everybody to think that the play command was not received.

Possible solutions:

  1. Set status to playing and continuously set the current position as 0. Might create a confusing flickering between 0 and 1 seconds.
  2. Set status to playing and once playing actually starts reset it to 0. Would lose the continued mismatch between time and reality once the song starts, but still cause the confusion of why the bar is moving and no music sounding
  3. find the status to send to spotify for buffering (spotify web api doesn't show it, so it might not exist?)

I appreciate any feedback and if possible I would like to get help on fixing this issue in the code by myself. If this is a oneliner, that somebody fixes while reading this, I'm happy to test it.

@fherrera124
Copy link

fherrera124 commented Apr 26, 2018

I think that the web api is useless in this matter, the PlayStatus is an internal state of the Player, so the web api should not allow you to modify it. As far as I could see in the code, changing the state to buffering is something trivial (PlayStatus :: kPlayStatusLoading), the problem is knowing when the stream is ready to be played. And that depends on the audio backend you choose. For example, if you use alsa, you could start adding that functionality in the rust-alsa library.

Some hints:
link1
link2

Then, you would have to make the corresponding modifications in librespot, surely in the player and in some other files, I do not know really.
Take in mind that everything I have written are basic assumptions. I hope some experts here will help you.

@fherrera124
Copy link

fherrera124 commented Apr 29, 2018

Forget what I said about backends. In the Player when start_sink() is executed, you can assume that at that instant the music starts playing. The problem is that in the implementation of both the Spirc and the Player the loading state is nonexistent. So, the solution first requires the addition of such state.

@WhiteHatTux
Copy link
Author

Thank you for the clarifications @elganzua124. I started the creation of the new states and I am starting to get an idea on how this will work. I have now gotten to the point, where I would like to send a status change from player to spirc, but don't know, how to do it correctly, as adding spirc to player would create a circular dependency. So if you or anybody else could outline the communication between player and spirc, that would be greatly appreciated.

@sashahilton00
Copy link
Member

With regards to the loading state, spirc does have support for it

kPlayStatusLoading = 0x3;
but it hasn't been implemented in librespot, most likely due to the fact that the developers have fast internet and didn't need it. Perhaps this would be a useful addition though for places with less bandwidth.

@plietar
Copy link
Contributor

plietar commented May 11, 2018

The main issue is that in librespot the playback logic is split between "Player" and "Spirc".
Spirc sends a message to Player to start a file, and gets a message back once the file is complete.

To fix this you'd have to add a message from the Player to Spirc to indicate when loading is complete.

@WhiteHatTux
Copy link
Author

The problem is that I can't (or don't know how to) create a reference from player to spirc. Spirc already has a reference to player, creating a reference from player to spirc would introduce a circular reference, which afaik should be avoided/be impossible.

@michalfita
Copy link

@roderickvd
Copy link
Member

There's been a lot of development since this, including prefetching and some loading states. Since this was over two years old, I'm closing this for now, but feel free to re-open if it's still an issue.

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

No branches or pull requests

6 participants