[GH-ISSUE #247] Fake track repeat #129

Closed
opened 2026-03-02 23:44:48 +03:00 by kerem · 11 comments
Owner

Originally created by @sewnie on GitHub (Sep 7, 2023).
Original GitHub issue: https://github.com/aome510/spotify-player/issues/247

Is your feature request related to a problem? Please describe.
I want to play a song on loop.

Describe the solution you'd like
(when using the local device) to fake repeat the track by re-playing it after it finishes when the loop on single track is enabled.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Currently, Librespot does not support looping a single track once.

Originally created by @sewnie on GitHub (Sep 7, 2023). Original GitHub issue: https://github.com/aome510/spotify-player/issues/247 **Is your feature request related to a problem? Please describe.** I want to play a song on loop. **Describe the solution you'd like** (when using the local device) to fake repeat the track by re-playing it after it finishes when the loop on single track is enabled. **Describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. **Additional context** Currently, Librespot does not support looping a single track once.
kerem 2026-03-02 23:44:48 +03:00
Author
Owner

@sewnie commented on GitHub (Dec 29, 2023):

I believe to make this possible, it would require a custom new 'playback' mode that is not available to Spotify API, as 'repeated once track' behavior is going to be inferred from spotify_player AFAIK.

<!-- gh-comment-id:1871992602 --> @sewnie commented on GitHub (Dec 29, 2023): I believe to make this possible, it would require a custom new 'playback' mode that is not available to Spotify API, as 'repeated once track' behavior is going to be inferred from spotify_player AFAIK.
Author
Owner

@Colonial-Dev commented on GitHub (Apr 6, 2024):

For what it's worth, ncspot (another Rust/librespot based Spotify TUI client) seems to have figured out a hack, although what distinguishes it from this project isn't immediately obvious. I'll try and dig deeper if I can find the time.

<!-- gh-comment-id:2041216079 --> @Colonial-Dev commented on GitHub (Apr 6, 2024): For what it's worth, `ncspot` (another Rust/`librespot` based Spotify TUI client) seems to have figured out a hack, although what distinguishes it from this project isn't immediately obvious. I'll try and dig deeper if I can find the time.
Author
Owner

@aome510 commented on GitHub (Apr 6, 2024):

For what it's worth, ncspot (another Rust/librespot based Spotify TUI client) seems to have figured out a hack, although what distinguishes it from this project isn't immediately obvious. I'll try and dig deeper if I can find the time.

The main difference is that ncspot itself is an Spotify client (for streaming), while spotify_player uses an integrated client from librespot. In other words, it's easier for ncspot to implement the hack as they own the client implementation.

<!-- gh-comment-id:2041220827 --> @aome510 commented on GitHub (Apr 6, 2024): > For what it's worth, `ncspot` (another Rust/`librespot` based Spotify TUI client) seems to have figured out a hack, although what distinguishes it from this project isn't immediately obvious. I'll try and dig deeper if I can find the time. The main difference is that `ncspot` itself is an Spotify client (for streaming), while `spotify_player` uses an integrated client from [librespot](https://github.com/librespot-org/librespot). In other words, it's easier for `ncspot` to implement the hack as they own the client implementation.
Author
Owner

@sewnie commented on GitHub (Apr 6, 2024):

Is it that difficult to just check if the user has 'repeat once' and just replay the song after it ends? Or am I underestimating how difficult it is?

<!-- gh-comment-id:2041230370 --> @sewnie commented on GitHub (Apr 6, 2024): Is it that difficult to just check if the user has 'repeat once' and just replay the song after it ends? Or am I underestimating how difficult it is?
Author
Owner

@aome510 commented on GitHub (Apr 7, 2024):

spotify_player operates on API boundary and streaming client is just an "add-on" compared to ncspot with streaming client as the main component. As a result, the app cannot have any assumption regarding the streaming client's behaviour.

Is it that difficult to just check if the user has 'repeat once' and just replay the song after it ends?

The problem is that you don't know when user has 'repeat once'. The integrated streaming client will automatically switch to repeat context mode as repeat once is not supported. As a result, when you query get-repeat-mode API, the returned mode will be repeat context.

There are different ways to implement the "hack". The easiest one is to start a new "one-track" playback if user wants to change the repeat mode to repeat once. The drawback of this approach is that you will lose the previous context, or you cannot play the previous context when switching to different repeat mode.

Another approach is to add a separate fake track repeat mode and a command to enable/disable the mode. The integrated client can be updated to queue the current song when it is about to end. I would prefer this approach as a workaround for the integrated client's limitation. Can start working on this when I'm free.

<!-- gh-comment-id:2041512063 --> @aome510 commented on GitHub (Apr 7, 2024): `spotify_player` operates on API boundary and streaming client is just an "add-on" compared to `ncspot` with streaming client as the main component. As a result, the app cannot have any assumption regarding the streaming client's behaviour. > Is it that difficult to just check if the user has 'repeat once' and just replay the song after it ends? The problem is that you don't know when user has 'repeat once'. The integrated streaming client will automatically switch to `repeat context` mode as `repeat once` is not supported. As a result, when you query `get-repeat-mode` API, the returned mode will be `repeat context`. There are different ways to implement the "hack". The easiest one is to start a new "one-track" playback if user wants to change the repeat mode to `repeat once`. The drawback of this approach is that you will lose the previous context, or you cannot play the previous context when switching to different repeat mode. Another approach is to add a separate `fake track repeat` mode and a command to enable/disable the mode. The integrated client can be updated to queue the current song when it is about to end. I would prefer this approach as a workaround for the integrated client's [limitation](https://github.com/librespot-org/librespot/issues/19). Can start working on this when I'm free.
Author
Owner

@sewnie commented on GitHub (Apr 16, 2024):

YAYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY

<!-- gh-comment-id:2058108092 --> @sewnie commented on GitHub (Apr 16, 2024): YAYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
Author
Owner

@aome510 commented on GitHub (Apr 16, 2024):

Implemented with #410. @apprehensions can you try the latest master? The command is ToggleFakeTrackRepeatMode with default binding M-r (alt + r). Should see repeat: track (fake) if the fake track repeat mode is enabled.

<!-- gh-comment-id:2058108646 --> @aome510 commented on GitHub (Apr 16, 2024): Implemented with #410. @apprehensions can you try the latest `master`? The command is `ToggleFakeTrackRepeatMode` with default binding `M-r` (alt + r). Should see `repeat: track (fake)` if the fake track repeat mode is enabled.
Author
Owner

@sewnie commented on GitHub (Apr 16, 2024):

It plays the 'fake repeat' track twice, and then plays the next song in queue, then the 'fake repeat' track again.

2024-04-16T03:34:47.982937Z  INFO spotify_player::streaming: Got a new player event: Playing { track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf"), position_ms: 0, duration_ms: 6400 }
2024-04-16T03:34:48.954772Z  INFO spotify_player::client: Retrieving an image from the file: /home/sewn/.cache/spotify-player/image/Putrefaction in Progress-Last Days Of Humanity-cover.jpg
2024-04-16T03:34:49.428103Z  INFO client_request{request=GetCurrentUserQueue}: spotify_player::client: successfully handled the client request, took: 416ms
2024-04-16T03:34:50.012162Z  INFO spotify_player::client::handlers: fake track repeat mode is enabled, add the current track (Allowing the Carvings for Mutual Compassion) to queue
2024-04-16T03:34:50.240719Z  INFO client_request{request=AddTrackToQueue(TrackId("4YkbI4N8UQZ5I5PZ2pRvcf"))}: spotify_player::client: successfully handled the client request, took: 228ms
2024-04-16T03:34:53.881673Z  INFO spotify_player::streaming: Got a new player event: EndOfTrack { track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf") }
2024-04-16T03:34:53.881720Z  INFO spotify_player::streaming: Got a new player event: Changed { old_track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf"), new_track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf") }
2024-04-16T03:34:53.881766Z  INFO spotify_player::streaming: Got a new player event: Playing { track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf"), position_ms: 0, duration_ms: 6400 }
2024-04-16T03:34:55.272983Z  INFO client_request{request=GetCurrentPlayback}: spotify_player::client: successfully handled the client request, took: 255ms
2024-04-16T03:35:00.026055Z  INFO spotify_player::client::handlers: fake track repeat mode is enabled, add the current track (Allowing the Carvings for Mutual Compassion) to queue
2024-04-16T03:35:00.253885Z  INFO client_request{request=AddTrackToQueue(TrackId("4YkbI4N8UQZ5I5PZ2pRvcf"))}: spotify_player::client: successfully handled the client request, took: 227ms
2024-04-16T03:35:00.281555Z  INFO spotify_player::streaming: Got a new player event: EndOfTrack { track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf") }
2024-04-16T03:35:00.281606Z  INFO spotify_player::streaming: Got a new player event: Changed { old_track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf"), new_track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf") }
2024-04-16T03:35:00.281657Z  INFO spotify_player::streaming: Got a new player event: Playing { track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf"), position_ms: 0, duration_ms: 6400 }
2024-04-16T03:35:01.280046Z  INFO client_request{request=GetCurrentPlayback}: spotify_player::client: successfully handled the client request, took: 252ms
2024-04-16T03:35:06.677844Z  INFO spotify_player::streaming: Got a new player event: EndOfTrack { track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf") }
2024-04-16T03:35:06.677972Z  INFO spotify_player::streaming: Got a new player event: Changed { old_track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf"), new_track_id: TrackId("1TA7Pw6JkLjhLyelvv2321") }
2024-04-16T03:35:06.678001Z  INFO spotify_player::streaming: Got a new player event: Playing { track_id: TrackId("1TA7Pw6JkLjhLyelvv2321"), position_ms: 0, duration_ms: 39653 }
2024-04-16T03:35:07.342517Z  INFO client_request{request=GetCurrentPlayback}: spotify_player::client: Retrieving an image from the file: /home/sewn/.cache/spotify-player/image/Putrefaction in Progress-Last Days Of Humanity-cover.jpg
2024-04-16T03:35:07.342625Z  INFO client_request{request=GetCurrentPlayback}: spotify_player::client: successfully handled the client request, took: 308ms
2024-04-16T03:35:08.426592Z  INFO client_request{request=GetCurrentUserQueue}: spotify_player::client: successfully handled the client request, took: 390ms
<!-- gh-comment-id:2058167838 --> @sewnie commented on GitHub (Apr 16, 2024): It plays the 'fake repeat' track twice, and then plays the next song in queue, then the 'fake repeat' track again. ``` 2024-04-16T03:34:47.982937Z INFO spotify_player::streaming: Got a new player event: Playing { track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf"), position_ms: 0, duration_ms: 6400 } 2024-04-16T03:34:48.954772Z INFO spotify_player::client: Retrieving an image from the file: /home/sewn/.cache/spotify-player/image/Putrefaction in Progress-Last Days Of Humanity-cover.jpg 2024-04-16T03:34:49.428103Z INFO client_request{request=GetCurrentUserQueue}: spotify_player::client: successfully handled the client request, took: 416ms 2024-04-16T03:34:50.012162Z INFO spotify_player::client::handlers: fake track repeat mode is enabled, add the current track (Allowing the Carvings for Mutual Compassion) to queue 2024-04-16T03:34:50.240719Z INFO client_request{request=AddTrackToQueue(TrackId("4YkbI4N8UQZ5I5PZ2pRvcf"))}: spotify_player::client: successfully handled the client request, took: 228ms 2024-04-16T03:34:53.881673Z INFO spotify_player::streaming: Got a new player event: EndOfTrack { track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf") } 2024-04-16T03:34:53.881720Z INFO spotify_player::streaming: Got a new player event: Changed { old_track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf"), new_track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf") } 2024-04-16T03:34:53.881766Z INFO spotify_player::streaming: Got a new player event: Playing { track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf"), position_ms: 0, duration_ms: 6400 } 2024-04-16T03:34:55.272983Z INFO client_request{request=GetCurrentPlayback}: spotify_player::client: successfully handled the client request, took: 255ms 2024-04-16T03:35:00.026055Z INFO spotify_player::client::handlers: fake track repeat mode is enabled, add the current track (Allowing the Carvings for Mutual Compassion) to queue 2024-04-16T03:35:00.253885Z INFO client_request{request=AddTrackToQueue(TrackId("4YkbI4N8UQZ5I5PZ2pRvcf"))}: spotify_player::client: successfully handled the client request, took: 227ms 2024-04-16T03:35:00.281555Z INFO spotify_player::streaming: Got a new player event: EndOfTrack { track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf") } 2024-04-16T03:35:00.281606Z INFO spotify_player::streaming: Got a new player event: Changed { old_track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf"), new_track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf") } 2024-04-16T03:35:00.281657Z INFO spotify_player::streaming: Got a new player event: Playing { track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf"), position_ms: 0, duration_ms: 6400 } 2024-04-16T03:35:01.280046Z INFO client_request{request=GetCurrentPlayback}: spotify_player::client: successfully handled the client request, took: 252ms 2024-04-16T03:35:06.677844Z INFO spotify_player::streaming: Got a new player event: EndOfTrack { track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf") } 2024-04-16T03:35:06.677972Z INFO spotify_player::streaming: Got a new player event: Changed { old_track_id: TrackId("4YkbI4N8UQZ5I5PZ2pRvcf"), new_track_id: TrackId("1TA7Pw6JkLjhLyelvv2321") } 2024-04-16T03:35:06.678001Z INFO spotify_player::streaming: Got a new player event: Playing { track_id: TrackId("1TA7Pw6JkLjhLyelvv2321"), position_ms: 0, duration_ms: 39653 } 2024-04-16T03:35:07.342517Z INFO client_request{request=GetCurrentPlayback}: spotify_player::client: Retrieving an image from the file: /home/sewn/.cache/spotify-player/image/Putrefaction in Progress-Last Days Of Humanity-cover.jpg 2024-04-16T03:35:07.342625Z INFO client_request{request=GetCurrentPlayback}: spotify_player::client: successfully handled the client request, took: 308ms 2024-04-16T03:35:08.426592Z INFO client_request{request=GetCurrentUserQueue}: spotify_player::client: successfully handled the client request, took: 390ms ```
Author
Owner

@aome510 commented on GitHub (Apr 16, 2024):

The timing between EndOfTrack events seems too short. Did you seek to the end of the track to test the feature? The queue the current song when it is about to end logic only applies once every 10s to avoid making duplicated requests. That might be the reason why it doesn't work well

<!-- gh-comment-id:2058175941 --> @aome510 commented on GitHub (Apr 16, 2024): The timing between `EndOfTrack` events seems too short. Did you seek to the end of the track to test the feature? The `queue the current song when it is about to end` logic only applies once every 10s to avoid making duplicated requests. That might be the reason why it doesn't work well
Author
Owner

@sewnie commented on GitHub (Apr 16, 2024):

No.. The song I was listening to was 9 seconds (that's grindcore for you, see track I'd) I am unable to test right now but given this I suppose it males sense.

<!-- gh-comment-id:2058183192 --> @sewnie commented on GitHub (Apr 16, 2024): No.. The song I was listening to was 9 seconds (that's grindcore for you, see track I'd) I am unable to test right now but given this I suppose it males sense.
Author
Owner

@aome510 commented on GitHub (Apr 16, 2024):

ahh, super short song won't work with fake repeat mode unfortunately xD.

<!-- gh-comment-id:2058185817 --> @aome510 commented on GitHub (Apr 16, 2024): ahh, super short song won't work with fake repeat mode unfortunately xD.
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/spotify-player#129
No description provided.