22
33import org .apache .log4j .Logger ;
44import org .jetbrains .annotations .NotNull ;
5+ import org .jetbrains .annotations .Nullable ;
56import xyz .gianlu .librespot .common .Utils ;
67import xyz .gianlu .librespot .common .proto .Spirc ;
78import xyz .gianlu .librespot .core .Session ;
9+ import xyz .gianlu .librespot .mercury .MercuryClient ;
10+ import xyz .gianlu .librespot .mercury .MercuryRequests ;
811import xyz .gianlu .librespot .mercury .model .TrackId ;
912import xyz .gianlu .librespot .player .tracks .PlaylistProvider ;
1013import xyz .gianlu .librespot .player .tracks .StationProvider ;
@@ -206,8 +209,8 @@ private void updatedTracks(@NotNull Spirc.Frame frame) {
206209 state .update (frame );
207210 String context = frame .getState ().getContextUri ();
208211
209- if (context .startsWith ("spotify:station:" )) tracksProvider = new StationProvider (session , state .state , frame );
210- else tracksProvider = new PlaylistProvider (session , state .state , frame , conf );
212+ if (context .startsWith ("spotify:station:" )) tracksProvider = new StationProvider (session , state .state );
213+ else tracksProvider = new PlaylistProvider (session , state .state , conf );
211214
212215 state .setRepeat (frame .getState ().getRepeat ());
213216 state .setShuffle (frame .getState ().getShuffle ());
@@ -332,8 +335,18 @@ private void handleNext() {
332335 int newTrack = tracksProvider .getNextTrackIndex (true );
333336 boolean play = true ;
334337 if (newTrack >= state .getTrackCount ()) {
335- newTrack = 0 ;
336- play = state .getRepeat ();
338+ if (state .getRepeat ()) {
339+ newTrack = 0 ;
340+ play = true ;
341+ } else {
342+ if (conf .autoplayEnabled ()) {
343+ loadAutoplay ();
344+ return ;
345+ } else {
346+ newTrack = 0 ;
347+ play = false ;
348+ }
349+ }
337350 }
338351
339352 state .setPlayingTrackIndex (newTrack );
@@ -343,6 +356,31 @@ private void handleNext() {
343356 loadTrack (play );
344357 }
345358
359+ private void loadAutoplay () {
360+ String context = state .getContextUri ();
361+ if (context == null ) {
362+ LOGGER .fatal ("Cannot load autoplay with null context!" );
363+ state .setStatus (Spirc .PlayStatus .kPlayStatusStop );
364+ stateUpdated ();
365+ return ;
366+ }
367+
368+ try {
369+ MercuryRequests .StationsWrapper json = session .mercury ().sendSync (MercuryRequests .getStationFor (context ));
370+ state .update (json );
371+
372+ state .setPositionMs (0 );
373+ state .setPositionMeasuredAt (System .currentTimeMillis ());
374+
375+ tracksProvider = new StationProvider (session , state .state );
376+ loadTrack (true );
377+
378+ LOGGER .debug (String .format ("Loading context for autoplay, uri: %s" , json .uri ()));
379+ } catch (IOException | MercuryClient .MercuryException e ) {
380+ e .printStackTrace ();
381+ }
382+ }
383+
346384 private void handlePrev () {
347385 if (getPosition () < 3000 ) {
348386 state .setPlayingTrackIndex (tracksProvider .getPrevTrackIndex (true ));
@@ -389,6 +427,8 @@ public interface Configuration {
389427 boolean logAvailableMixers ();
390428
391429 int initialVolume ();
430+
431+ boolean autoplayEnabled ();
392432 }
393433
394434 private class StateWrapper {
@@ -398,6 +438,11 @@ private class StateWrapper {
398438 this .state = state ;
399439 }
400440
441+ @ Nullable
442+ String getContextUri () {
443+ return state .getContextUri ();
444+ }
445+
401446 @ NotNull
402447 Spirc .PlayStatus getStatus () {
403448 return state .getStatus ();
@@ -421,6 +466,18 @@ void setShuffle(boolean shuffle) {
421466
422467 void update (@ NotNull Spirc .Frame frame ) {
423468 state .setContextUri (frame .getState ().getContextUri ());
469+
470+ state .setPlayingTrackIndex (frame .getState ().getPlayingTrackIndex ());
471+ state .clearTrack ();
472+ state .addAllTrack (frame .getState ().getTrackList ());
473+ }
474+
475+ void update (@ NotNull MercuryRequests .StationsWrapper json ) {
476+ state .setContextUri (json .uri ());
477+
478+ state .setPlayingTrackIndex (0 );
479+ state .clearTrack ();
480+ state .addAllTrack (json .tracks ());
424481 }
425482
426483 long getPositionMeasuredAt () {
0 commit comments