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
Skip unplayable tracks instead of stopping #474
Conversation
Looking at the code without testing it, it should work. The only issue I can see is that there won't be gapless playback if tracks are skipped. In case of an unplayable track, the preloading is attempted and fails. And then when the actual playback command comes, another load attempt for the same track is made and fails, too. Then the next track is loaded. Thus there will be a gap for two loading cycles until playback resumes. The issue potentially gets worse if there is more than one track to skip. I don't know how often unplayable tracks occur and how much effort is justified to handle them gaplessly. Doing so is probably a bit more involved because of the required interaction with spirc. |
Please ignore if I'm saying stuping things; I'm just a user not familiar with the code.
@kaymes couldn't it just avoid queuing these tracks?
I've only found this with playlists that I've been doing over the years, where some songs that use to be available aren't any more, but IMHO there's no problem with loosing gapless playback for those. Thanks a lot for this! |
@kaymes I went ahead and patched in the prefetching support as well. On looking at it with a fresh pair of eyes this morning, I feel it can be much more elegant, by just adding a Testing with this |
b5dde82
to
9024409
Compare
@ashthespy is this ready to merge? |
|
@ashthespy at quick glance it doesn't feel quite right. But I don't have time right now. I'll have a closer look tomorrow. |
I just had a look at the code. I didn't actually run it so there is a chance I missed a subtlety somewhere. Just from looking at it I don't think it works as desired. This is how I understand it: Now, when the track actually finishes, the play commands come in as before. Thus the track that is passed to handle_command_load is not the one that has been pre-loaded. Thus it is attempted to load the track that has already been attempted to be loaded in vain. This also has the effect of the preloaded track being discarded. Thus the whole preloading is just lost. Thus gapless playback isn't achieved and we might as well merge the initial version which was a lot simpler. Possible solution I would communicate the failed SpotifyId back to spirc. You could add it as an option to PlayerEvent::TimeToPreloadNextTrack or define a dedicated player event, PlayerEvent::PreloadFailed{spotify_id}. I was also wondering whether get_track_id_to_play_from_playlist can already see which tracks won't be able to load. There is already SpotifyAudioType::NonPlayable which is checked, but maybe there are other fields that could be used to indicate whe |
I just see that I messed up while force pushing, with an incomplete implementation. Sorry for wasting you time.. |
Okay, this should be much simpler - what do you think? Log of a playlist with unavailable tracks[2020-05-13T10:27:36Z DEBUG librespot_connect::spirc] State: context_uri: "spotify:user:xx:playlist:5NcULAQYuqV2tjJZ9R5LRg" index: 0 position_ms: 1284 status: kPlayStatusPause position_
measured_at: 1589365656625 context_description: "Missing the 80s" shuffle: false repeat: false playing_from_fallback: true row: 0 playing_track_index: 0 track {gid: "\320\307\344As\233M\246\
245\210\004\357\220\227\261\317"} track {gid: "4\250\370\013b\371I\352\243W\220$\301\031C~"} track {gid: "\246\307\230\010_@B\005\244\230\240\007L;\274\""} track {gid: "\321\342\356\tL\242C\
370\221\200n\253No:S"} track {gid: "\351\026\363@\201\365NV\207\037\316\037\275+\214\350"} track {gid: "\350\253\035\304\200\353D\251\235\374a'\342,\234;"} track {gid: "\355\367\034\rH]G\374
\214#\026\001\321aj\354"} track {gid: "\327Mo\204\274\206@\257\233\226\030\220\264\022z\317"} track {gid: "\003\207vB\346;N\356\270\225^E\025\014e\371"}
[2020-05-13T10:27:36Z DEBUG librespot_connect::spirc] Frame has 9 tracks
[2020-05-13T10:27:36Z DEBUG librespot_playback::player] command=Load(SpotifyId { id: 277517319773109654597909477525433070031, audio_type: Track }, false, 1284)
[2020-05-13T10:27:36Z TRACE librespot_connect::spirc] Sending status to server: [kPlayStatusLoading]
[2020-05-13T10:27:36Z INFO librespot_playback::player] Loading <Major Tom> with Spotify URI <spotify:track:6lXKNdOsnaLv9LwulZbxNl>
[2020-05-13T10:27:36Z DEBUG librespot_core::audio_key] new AudioKeyManager
[2020-05-13T10:27:36Z DEBUG librespot_audio::fetch] File 112829cc4a3f42cd15fec5a799db37e71d92c7e7 already in cache
[2020-05-13T10:27:36Z DEBUG librespot_playback::player] Normalisation Data: NormalisationData { track_gain_db: -5.529999, track_peak: 1.0630234, album_gain_db: -5.080002, album_peak: 1.19040
81 }
[2020-05-13T10:27:36Z DEBUG librespot_playback::player] Applied normalisation factor: 0.5290541
[2020-05-13T10:27:36Z INFO librespot_playback::player] <Major Tom> (299560 ms) loaded
[2020-05-13T10:27:36Z TRACE librespot_connect::spirc] Sending status to server: [kPlayStatusPause]
[2020-05-13T10:27:36Z TRACE librespot_connect::spirc] ==> kPlayStatusPause
[2020-05-13T10:27:36Z DEBUG librespot_connect::spirc] kMessageTypeNotify "ASHXPS15" 2e4c3f0d6c618cbc37d5ebdd3fcd3a67f0ac6838 227758080 1589365656860 kPlayStatusStop
[2020-05-13T10:27:43Z DEBUG librespot_connect::spirc] kMessageTypePlay "ASHXPS15" 2e4c3f0d6c618cbc37d5ebdd3fcd3a67f0ac6838 227764414 1589365656860 kPlayStatusPause
[2020-05-13T10:27:43Z TRACE librespot_connect::spirc] Sending status to server: [kPlayStatusPlay]
[2020-05-13T10:27:43Z DEBUG librespot_playback::player] command=Play
[2020-05-13T10:27:43Z TRACE librespot_playback::player] == Starting sink ==
[2020-05-13T10:27:43Z TRACE librespot_connect::spirc] ==> kPlayStatusPlay
[2020-05-13T10:27:43Z TRACE librespot_connect::spirc] ==> kPlayStatusPlay
[2020-05-13T10:27:52Z DEBUG librespot_connect::spirc] kMessageTypeSeek "ASHXPS15" 2e4c3f0d6c618cbc37d5ebdd3fcd3a67f0ac6838 227773305 1589365663239 kPlayStatusPlay
[2020-05-13T10:27:52Z TRACE librespot_connect::spirc] Sending status to server: [kPlayStatusPlay]
[2020-05-13T10:27:52Z DEBUG librespot_playback::player] command=Seek(235707)
[2020-05-13T10:27:52Z TRACE librespot_connect::spirc] ==> kPlayStatusPlay
[2020-05-13T10:28:25Z DEBUG librespot_playback::player] command=Preload(SpotifyId { id: 69997192592771872256401199735544300414, audio_type: Track })
[2020-05-13T10:28:25Z DEBUG librespot_playback::player] Preloading track
[2020-05-13T10:28:25Z INFO librespot_playback::player] Loading <White Wedding - Part 1> with Spotify URI <spotify:track:1BmOQ94SgATSokQdOUTj1I>
[2020-05-13T10:28:25Z DEBUG librespot_audio::fetch] File a183491ae799fc29e8751a2073491e3df32b1732 already in cache
[2020-05-13T10:28:25Z DEBUG librespot_playback::player] Normalisation Data: NormalisationData { track_gain_db: -1.4599991, track_peak: 0.82888156, album_gain_db: -6.830002, album_peak: 1.1227702 }
[2020-05-13T10:28:25Z DEBUG librespot_playback::player] Applied normalisation factor: 0.8452789
[2020-05-13T10:28:25Z INFO librespot_playback::player] <White Wedding – Part 1> (214573 ms) loaded
[2020-05-13T10:28:55Z DEBUG librespot_connect::spirc] At track 1 of 9 <"spotify:user:xxxx:playlist:5NcULAQYuqV2tjJZ9R5LRg"> update [false]
[2020-05-13T10:28:55Z DEBUG librespot_playback::player] command=Load(SpotifyId { id: 69997192592771872256401199735544300414, audio_type: Track }, true, 0)
[2020-05-13T10:28:55Z TRACE librespot_connect::spirc] Sending status to server: [kPlayStatusPlay]
[2020-05-13T10:28:55Z TRACE librespot_connect::spirc] ==> kPlayStatusPlay
[2020-05-13T10:28:58Z DEBUG librespot_connect::spirc] kMessageTypeSeek "ASHXPS15" 2e4c3f0d6c618cbc37d5ebdd3fcd3a67f0ac6838 227840016 1589365736156 kPlayStatusPlay
[2020-05-13T10:28:58Z TRACE librespot_connect::spirc] Sending status to server: [kPlayStatusPlay]
[2020-05-13T10:28:58Z DEBUG librespot_playback::player] command=Seek(159565)
[2020-05-13T10:28:58Z TRACE librespot_connect::spirc] ==> kPlayStatusPlay
[2020-05-13T10:29:23Z DEBUG librespot_playback::player] command=Preload(SpotifyId { id: 221688197964708279733893794639650733090, audio_type: Track })
[2020-05-13T10:29:23Z DEBUG librespot_playback::player] Preloading track
[2020-05-13T10:29:23Z INFO librespot_playback::player] Loading <Dancing With Myself - 2001 Digital Remaster> with Spotify URI <spotify:track:54HWkXBa3O7jH4vletYhc6>
[2020-05-13T10:29:23Z WARN librespot_playback::player] <spotify:track:54HWkXBa3O7jH4vletYhc6> is not available
[2020-05-13T10:29:23Z WARN librespot_playback::player] Unable to preload SpotifyId { id: 221688197964708279733893794639650733090, audio_type: Track }
[2020-05-13T10:29:23Z DEBUG librespot_playback::player] Signaling unavilable: 1
[2020-05-13T10:29:23Z DEBUG librespot_connect::spirc] Removing unavailable track_ref at 1
[2020-05-13T10:29:23Z DEBUG librespot_playback::player] command=Preload(SpotifyId { id: 278986938159332447919914684866834152019, audio_type: Track })
[2020-05-13T10:29:23Z DEBUG librespot_playback::player] Preloading track
[2020-05-13T10:29:24Z INFO librespot_playback::player] Loading <Love Is In The Air - Original> with Spotify URI <spotify:track:6o36q5KrEhVKuhAIUQQMkr>
[2020-05-13T10:29:24Z WARN librespot_playback::player] <spotify:track:6o36q5KrEhVKuhAIUQQMkr> is not available
[2020-05-13T10:29:24Z WARN librespot_playback::player] Unable to preload SpotifyId { id: 278986938159332447919914684866834152019, audio_type: Track }
[2020-05-13T10:29:24Z DEBUG librespot_playback::player] Signaling unavilable: 1
[2020-05-13T10:29:24Z DEBUG librespot_connect::spirc] Removing unavailable track_ref at 1
[2020-05-13T10:29:24Z DEBUG librespot_playback::player] command=Preload(SpotifyId { id: 309829287285129375896746820873197685992, audio_type: Track })
[2020-05-13T10:29:24Z DEBUG librespot_playback::player] Preloading track
[2020-05-13T10:29:24Z INFO librespot_playback::player] Loading <The Hustle - Original Mix> with Spotify URI <spotify:track:75PHqzep3Lf11sIYP5ps5q>
[2020-05-13T10:29:24Z WARN librespot_playback::player] <spotify:track:75PHqzep3Lf11sIYP5ps5q> is not available
[2020-05-13T10:29:24Z WARN librespot_playback::player] Unable to preload SpotifyId { id: 309829287285129375896746820873197685992, audio_type: Track }
[2020-05-13T10:29:24Z DEBUG librespot_playback::player] Signaling unavilable: 1
[2020-05-13T10:29:24Z DEBUG librespot_connect::spirc] Removing unavailable track_ref at 1
[2020-05-13T10:29:24Z DEBUG librespot_playback::player] command=Preload(SpotifyId { id: 309269381543406799806960686689866783803, audio_type: Track })
[2020-05-13T10:29:24Z DEBUG librespot_playback::player] Preloading track
[2020-05-13T10:29:24Z INFO librespot_playback::player] Loading <Terra Titanic> with Spotify URI <spotify:track:752q3k1ds8JckA7tIakICn>
[2020-05-13T10:29:24Z DEBUG librespot_audio::fetch] File 2c50f098afa5e06c7581935f0795757e2e559f57 already in cache
[2020-05-13T10:29:24Z DEBUG librespot_playback::player] Normalisation Data: NormalisationData { track_gain_db: -6.9300003, track_peak: 1.1261528, album_gain_db: -5.080002, album_peak: 1.1904081 }
[2020-05-13T10:29:24Z DEBUG librespot_playback::player] Applied normalisation factor: 0.45029798
[2020-05-13T10:29:24Z INFO librespot_playback::player] <Terra Titanic> (274706 ms) loaded
[2020-05-13T10:29:25Z DEBUG librespot_core::session] Session[0] strong=3 weak=3
[2020-05-13T10:29:53Z DEBUG librespot_connect::spirc] At track 2 of 6 <"spotify:user:xxx:playlist:5NcULAQYuqV2tjJZ9R5LRg"> update [true]
[2020-05-13T10:29:53Z DEBUG librespot_playback::player] command=Load(SpotifyId { id: 309269381543406799806960686689866783803, audio_type: Track }, true, 0)
[2020-05-13T10:29:53Z TRACE librespot_connect::spirc] Sending status to server: [kPlayStatusPlay]
[2020-05-13T10:29:53Z TRACE librespot_connect::spirc] ==> kPlayStatusPlay
[2020-05-13T10:30:58Z DEBUG librespot_connect::spirc] kMessageTypeSeek "ASHXPS15" 2e4c3f0d6c618cbc37d5ebdd3fcd3a67f0ac6838 227960169 1589365793816 kPlayStatusPlay
[2020-05-13T10:30:58Z TRACE librespot_connect::spirc] Sending status to server: [kPlayStatusPlay]
[2020-05-13T10:30:58Z DEBUG librespot_playback::player] command=Seek(203285)
[2020-05-13T10:30:58Z TRACE librespot_connect::spirc] ==> kPlayStatusPlay
[2020-05-13T10:31:25Z DEBUG librespot_core::session] Session[0] strong=3 weak=3
[2020-05-13T10:31:40Z DEBUG librespot_playback::player] command=Preload(SpotifyId { id: 316310101284913869989716299886473865964, audio_type: Track })
[2020-05-13T10:31:40Z DEBUG librespot_playback::player] Preloading track
[2020-05-13T10:31:40Z INFO librespot_playback::player] Loading <Don´t Scratch Your Vinyl - Interlude> with Spotify URI <spotify:track:7f26SfPivhnPaZNrO9uOTO>
[2020-05-13T10:31:40Z WARN librespot_playback::player] <spotify:track:7f26SfPivhnPaZNrO9uOTO> is not available
[2020-05-13T10:31:40Z WARN librespot_playback::player] Unable to preload SpotifyId { id: 316310101284913869989716299886473865964, audio_type: Track }
[2020-05-13T10:31:40Z DEBUG librespot_playback::player] Signaling unavilable: 2
[2020-05-13T10:31:40Z DEBUG librespot_connect::spirc] Removing unavailable track_ref at 1
[2020-05-13T10:31:40Z DEBUG librespot_playback::player] command=Preload(SpotifyId { id: 286186087815793034997112511788613794511, audio_type: Track })
[2020-05-13T10:31:40Z DEBUG librespot_playback::player] Preloading track
[2020-05-13T10:31:40Z INFO librespot_playback::player] Loading <Joy - Original> with Spotify URI <spotify:track:6ygJMIdIuX1wDdKsMrAOqH>
[2020-05-13T10:31:40Z DEBUG librespot_audio::fetch] File ea7f60871739f2200659c3071cbae591be736c93 already in cache
[2020-05-13T10:31:40Z DEBUG librespot_playback::player] Normalisation Data: NormalisationData { track_gain_db: -5.92, track_peak: 1.1399819, album_gain_db: -8.17, album_peak: 1.2050169 }
[2020-05-13T10:31:40Z DEBUG librespot_playback::player] Applied normalisation factor: 0.5058247
[2020-05-13T10:31:40Z INFO librespot_playback::player] <Joy> (262169 ms) loaded
[2020-05-13T10:32:10Z DEBUG librespot_connect::spirc] At track 3 of 5 <"spotify:user:xxxxx:playlist:5NcULAQYuqV2tjJZ9R5LRg"> update [true]
[2020-05-13T10:32:10Z DEBUG librespot_playback::player] command=Load(SpotifyId { id: 286186087815793034997112511788613794511, audio_type: Track }, true, 0)
[2020-05-13T10:32:10Z TRACE librespot_connect::spirc] Sending status to server: [kPlayStatusPlay]
[2020-05-13T10:32:10Z TRACE librespot_connect::spirc] ==> kPlayStatusPlay
[2020-05-13T10:32:17Z DEBUG librespot_connect::spirc] kMessageTypeSeek "ASHXPS15" 2e4c3f0d6c618cbc37d5ebdd3fcd3a67f0ac6838 228038354 1589365930728 kPlayStatusPlay
[2020-05-13T10:32:17Z TRACE librespot_connect::spirc] Sending status to server: [kPlayStatusPlay]
[2020-05-13T10:32:17Z DEBUG librespot_playback::player] command=Seek(187869)
[2020-05-13T10:32:17Z TRACE librespot_connect::spirc] ==> kPlayStatusPlay
[2020-05-13T10:32:18Z DEBUG librespot_connect::spirc] kMessageTypeSeek "ASHXPS15" 2e4c3f0d6c618cbc37d5ebdd3fcd3a67f0ac6838 228039879 1589365937181 kPlayStatusPlay
[2020-05-13T10:32:18Z TRACE librespot_connect::spirc] Sending status to server: [kPlayStatusPlay]
[2020-05-13T10:32:18Z DEBUG librespot_playback::player] command=Seek(211914)
[2020-05-13T10:32:18Z TRACE librespot_connect::spirc] ==> kPlayStatusPlay
[2020-05-13T10:32:38Z DEBUG librespot_playback::player] command=Preload(SpotifyId { id: 4691042687902157817597368163352995321, audio_type: Track })
[2020-05-13T10:32:38Z DEBUG librespot_playback::player] Preloading track
[2020-05-13T10:32:38Z INFO librespot_playback::player] Loading <Jezabel - Original> with Spotify URI <spotify:track:06ESLhItfc6xyCZlYwtdmp>
[2020-05-13T10:32:38Z WARN librespot_playback::player] <spotify:track:06ESLhItfc6xyCZlYwtdmp> is not available
[2020-05-13T10:32:38Z WARN librespot_playback::player] Unable to preload SpotifyId { id: 4691042687902157817597368163352995321, audio_type: Track }
[2020-05-13T10:32:38Z DEBUG librespot_playback::player] Signaling unavilable: 3
[2020-05-13T10:32:38Z DEBUG librespot_connect::spirc] Removing unavailable track_ref at 1
[2020-05-13T10:32:38Z DEBUG librespot_playback::player] command=Preload(SpotifyId { id: 277517319773109654597909477525433070031, audio_type: Track })
[2020-05-13T10:32:38Z DEBUG librespot_playback::player] Preloading track
[2020-05-13T10:32:38Z INFO librespot_playback::player] Loading <Major Tom> with Spotify URI <spotify:track:6lXKNdOsnaLv9LwulZbxNl>
[2020-05-13T10:32:38Z DEBUG librespot_audio::fetch] File 112829cc4a3f42cd15fec5a799db37e71d92c7e7 already in cache
[2020-05-13T10:32:38Z DEBUG librespot_playback::player] Normalisation Data: NormalisationData { track_gain_db: -5.529999, track_peak: 1.0630234, album_gain_db: -5.080002, album_peak: 1.1904081 }
[2020-05-13T10:32:38Z DEBUG librespot_playback::player] Applied normalisation factor: 0.5290541
[2020-05-13T10:32:38Z INFO librespot_playback::player] <Major Tom> (299560 ms) loaded
[2020-05-13T10:33:08Z DEBUG librespot_connect::spirc] At track 4 of 4 <"spotify:user:xxxx:playlist:5NcULAQYuqV2tjJZ9R5LRg"> update [true]
[2020-05-13T10:33:08Z DEBUG librespot_playback::player] command=Load(SpotifyId { id: 277517319773109654597909477525433070031, audio_type: Track }, false, 0)
[2020-05-13T10:33:08Z TRACE librespot_playback::player] == Stopping sink ==
[2020-05-13T10:33:08Z TRACE librespot_connect::spirc] Sending status to server: [kPlayStatusPause]
[2020-05-13T10:33:08Z TRACE librespot_connect::spirc] ==> kPlayStatusPause Two questions
@kaymes looks like 6fed8d0 breaks the track cycling - librespot/connect/src/spirc.rs Lines 1155 to 1175 in 0056400
|
Flag them as `NonPlayable` instead of removing them from the queue
Looks like I overlooked to rename the "index" and also pushed an incomplete change. My bad, sorry about that. new_playlist_index makes more sense. The code looks much better now. Only the get_track_index_for_spotify_id() method worries me a little. What happens if the play list contains an unplayable track multiple times?
Regarding removing / marking unplayable: I'd replicate whatever behaviour the official client does. From memory it just skips tracks without removing them. But I could be wrong.
Not the way it is currently implemented. But there's nothing wrong with a little refactoring if you think it's useful. |
504ba87
to
01813cf
Compare
Okay, changed a few more things to make it less janky..
While it worked initially as we were removing each missing instance, the current implementation should cover more bases.
So, It's now a bit involved, to mark it Hopefully when we transition to a |
Just started testing this. It seems to work really well. It can handle multiple blocked tracks in a row, the preloader remembers the unavailable tracks and skips them all in one go (as opposed to the old behaviour of trying to load them one by one until the next available track was encountered) and although I haven't been testing it for long, I haven't been able to get it to break yet. Nice job! The only odd thing I've noticed is that in the debugging messages it looks like the track name is not available:
It's no big deal but I guess if that information isn't there, there's no need to print a blank string. |
Found a bug. If the first song in a playlist is blocked, when you get near the end of the last track in the playlist, it tries to preload the first song, fails because it's unavailable, and then librespot crashes with an assertion failure in spirc.rs:1185:
To reproduce, create a new playlist, add a blocked song as the first one, and a normal song as the second. Start playing the second song, and skip to about 40 seconds before the end. Once you hit 30 seconds from the end the preloader will kick in and the assertion will fail. Note that it only crashes when it tries to preload the blocked first song. If you are skipping songs or all songs in the list are blocked, it won't preload anything and will loop around to the start of the list just fine. |
Ah, that debug assertion is actually counter intuitive in this case - as the index is indeed 0. I am not near my dev machine, but it should work fine when it's compiled in |
Rather than compile in No rush with a fix, it can wait until you've got time to investigate. |
That does indeed make sense - will have a look.. Hopefully this is the last edge case we need to check for ;-) @Malvineous I was trying to be cheeky and search for the unplayable |
Nice job, that fixed the issue! If I read the fix correctly though, the cycle only jumps back to the first song when you're listening to the last song in the playlist. If you're on any other song then it won't jump back? I tried a playlist where both the first and the last song are blocked, and I get the same error:
If I comment out the I guess the search for the next available song should start at the track following the current one no matter what position it is in the playlist, but when it gets to the end of the playlist, then it should loop back to the first song and keep going? It does seem to do this correctly (looping and stopping just prior to the current song) but only if the current song is last in the playlist. Some experiments have also revealed some other possible bugs. If there is an album with only one playable song on it, then even if it does loop around correctly, the preloader is going to stop just before the currently playing song and come up empty handed, having found every other song in the playlist unplayable. This also seems to trigger the assertion failure, as the preloader seems to require finding at least one playable song to get ready. Likewise sometimes I remove songs from the playlist once I have listened to them, occasionally ending up "playing" a playlist composed entirely of blocked songs. In this case the preloader would definitely come up empty handed and presumably complain there too. I think that as well as correctly looping back to the start of the playlist when looking for the next song to play, the preloader should be able to cope with finding no suitable song to preload, and gracefully fall back to the old behaviour without preloading. This way a single-unblocked-song playlist would either loop or stop depending on autorepeat settings, and if it chose to loop, the song would already be cached so the preloading may not be as critical. It would also handle the admittedly rare case of playing a list containing only blocked songs. |
@Malvineous I came across the same issues last evening, forgot to push it..
Now, we first search from |
As long as it doesn't crash or get stuck in a loop when it can't find a suitable next song, then all good :) |
That is the general idea ;-) If there are no further issues will merge this tonight.. |
I haven't tested it. But from reviewing the code I'm worried about what happens when the first and last track of a playlist are the same track which isn't playable and you are playing the second last track without having attempted to play the first one. |
Hmm, your right - instead of handling all these edge cases, and micro optimise this, I guess the simplest way is to scan through the entire playlist each time. Given that we shouldn't encounter unplayable(s) with context/dynamic playlists, and we aren't dealing with couple of thousand tracks in the playlist, it should be fine to just scan through them for each unplayable we encounter. |
FYI I've been using this every day for two weeks now and haven't run into any problems, so I would have no issues if it were merged. Yes there are probably one or two edge cases still there but in my opinion the benefits are worth it. |
@ashthespy are you happy to merge this once you and @kaymes are happy with the code? |
This is what it does now, not had any reports of issues for a few months now from anyone using the plugin - LGTM ;-) |
Restoring the previous behaviour of skipping unplayable tracks.
Not tested the case when a unplayable track is at the end of a playlist though..
@kaymes Do you see any issues?