55import xyz .gianlu .librespot .common .Utils ;
66import xyz .gianlu .librespot .common .proto .Spirc ;
77import xyz .gianlu .librespot .core .Session ;
8+ import xyz .gianlu .librespot .mercury .model .TrackId ;
89import xyz .gianlu .librespot .spirc .FrameListener ;
910import xyz .gianlu .librespot .spirc .SpotifyIrc ;
1011
1112import java .io .IOException ;
12- import java .util .*;
1313
1414/**
1515 * @author Gianlu
@@ -18,18 +18,18 @@ public class Player implements FrameListener, TrackHandler.Listener {
1818 private static final Logger LOGGER = Logger .getLogger (Player .class );
1919 private final Session session ;
2020 private final SpotifyIrc spirc ;
21- private final Spirc . State . Builder state ;
21+ private final StateWrapper state ;
2222 private final PlayerConfiguration conf ;
2323 private final CacheManager cacheManager ;
24+ private TracksProvider tracksProvider ;
2425 private TrackHandler trackHandler ;
2526 private TrackHandler preloadTrackHandler ;
26- private long shuffleSeed = 0 ;
2727
2828 public Player (@ NotNull PlayerConfiguration conf , @ NotNull CacheManager .CacheConfiguration cacheConfiguration , @ NotNull Session session ) {
2929 this .conf = conf ;
3030 this .session = session ;
3131 this .spirc = session .spirc ();
32- this .state = initState ();
32+ this .state = new StateWrapper ( initState () );
3333
3434 try {
3535 this .cacheManager = new CacheManager (cacheConfiguration );
@@ -40,16 +40,6 @@ public Player(@NotNull PlayerConfiguration conf, @NotNull CacheManager.CacheConf
4040 spirc .addListener (this );
4141 }
4242
43- private static int [] getShuffleExchanges (int size , long seed ) {
44- int [] exchanges = new int [size - 1 ];
45- Random rand = new Random (seed );
46- for (int i = size - 1 ; i > 0 ; i --) {
47- int n = rand .nextInt (i + 1 );
48- exchanges [size - 1 - i ] = n ;
49- }
50- return exchanges ;
51- }
52-
5343 public void playPause () {
5444 handlePlayPause ();
5545 }
@@ -137,8 +127,8 @@ public void frame(@NotNull Spirc.Frame frame) {
137127 }
138128
139129 private void handlePlayPause () {
140- if (state .getStatus () == Spirc .PlayStatus .kPlayStatusPlay ) handlePause ();
141- else if (state .getStatus () == Spirc .PlayStatus .kPlayStatusPause ) handlePlay ();
130+ if (state .isStatus ( Spirc .PlayStatus .kPlayStatusPlay ) ) handlePause ();
131+ else if (state .isStatus ( Spirc .PlayStatus .kPlayStatusPause ) ) handlePlay ();
142132 }
143133
144134 private void handleSetVolume (int volume ) {
@@ -169,58 +159,34 @@ private void handleVolumeUp() {
169159 }
170160
171161 private void stateUpdated () {
172- spirc .deviceStateUpdated (state );
162+ spirc .deviceStateUpdated (state . state );
173163 }
174164
175165 private int getPosition () {
176166 int diff = (int ) (System .currentTimeMillis () - state .getPositionMeasuredAt ());
177167 return state .getPositionMs () + diff ;
178168 }
179169
180- private void shuffleTracks () {
181- shuffleSeed = session .random ().nextLong ();
182-
183- List <Spirc .TrackRef > tracks = new ArrayList <>(state .getTrackList ());
184- if (state .getPlayingTrackIndex () != 0 ) {
185- Collections .swap (tracks , 0 , state .getPlayingTrackIndex ());
186- state .setPlayingTrackIndex (0 );
187- }
188-
189- int size = tracks .size () - 1 ;
190- int [] exchanges = getShuffleExchanges (size , shuffleSeed );
191- for (int i = size - 1 ; i > 1 ; i --) {
192- int n = exchanges [size - 1 - i ];
193- Collections .swap (tracks , i , n + 1 );
194- }
195-
196- state .clearTrack ();
197- state .addAllTrack (tracks );
198- }
199-
200- private void unshuffleTracks () {
201- List <Spirc .TrackRef > tracks = new ArrayList <>(state .getTrackList ());
202- if (state .getPlayingTrackIndex () != 0 ) {
203- Collections .swap (tracks , 0 , state .getPlayingTrackIndex ());
204- state .setPlayingTrackIndex (0 );
205- }
206-
207- int size = tracks .size () - 1 ;
208- int [] exchanges = getShuffleExchanges (size , shuffleSeed );
209- for (int i = 2 ; i < size ; i ++) {
210- int n = exchanges [size - i - 1 ];
211- Collections .swap (tracks , i , n + 1 );
212- }
213-
214- state .clearTrack ();
215- state .addAllTrack (tracks );
216- }
217-
218170 private void handleShuffle () {
219171 if (state .getShuffle ()) shuffleTracks ();
220172 else unshuffleTracks ();
221173 stateUpdated ();
222174 }
223175
176+ private void shuffleTracks () {
177+ if (tracksProvider instanceof PlaylistProvider )
178+ ((PlaylistProvider ) tracksProvider ).shuffleTracks (session .random ());
179+ else
180+ LOGGER .warn ("Cannot shuffle TracksProvider: " + tracksProvider );
181+ }
182+
183+ private void unshuffleTracks () {
184+ if (tracksProvider instanceof PlaylistProvider )
185+ ((PlaylistProvider ) tracksProvider ).unshuffleTracks ();
186+ else
187+ LOGGER .warn ("Cannot unshuffle TracksProvider: " + tracksProvider );
188+ }
189+
224190 private void handleSeek (int pos ) {
225191 state .setPositionMs (pos );
226192 state .setPositionMeasuredAt (System .currentTimeMillis ());
@@ -229,10 +195,12 @@ private void handleSeek(int pos) {
229195 }
230196
231197 private void updatedTracks (@ NotNull Spirc .Frame frame ) {
232- state .setPlayingTrackIndex (frame .getState ().getPlayingTrackIndex ());
233- state .clearTrack ();
234- state .addAllTrack (frame .getState ().getTrackList ());
235- state .setContextUri (frame .getState ().getContextUri ());
198+ state .update (frame );
199+ String context = frame .getState ().getContextUri ();
200+
201+ if (context .startsWith ("spotify:station:" )) tracksProvider = new StationProvider (session , state .state , frame );
202+ else tracksProvider = new PlaylistProvider (state .state , frame );
203+
236204 state .setRepeat (frame .getState ().getRepeat ());
237205 state .setShuffle (frame .getState ().getShuffle ());
238206 if (state .getShuffle ()) shuffleTracks ();
@@ -272,7 +240,7 @@ public void endOfTrack(@NotNull TrackHandler handler) {
272240 @ Override
273241 public void preloadNextTrack (@ NotNull TrackHandler handler ) {
274242 if (handler == trackHandler ) {
275- Spirc . TrackRef next = state . getTrack ( getQueuedTrack (false ));
243+ TrackId next = tracksProvider . getTrackAt ( tracksProvider . getNextTrackIndex (false ));
276244
277245 preloadTrackHandler = new TrackHandler (session , cacheManager , conf , this );
278246 preloadTrackHandler .sendLoad (next , false , 0 );
@@ -304,14 +272,14 @@ private void handleLoad(@NotNull Spirc.Frame frame) {
304272 private void loadTrack (boolean play ) {
305273 if (trackHandler != null ) trackHandler .close ();
306274
307- Spirc . TrackRef ref = state . getTrack ( state . getPlayingTrackIndex () );
308- if (preloadTrackHandler != null && preloadTrackHandler .isTrack (ref )) {
275+ TrackId id = tracksProvider . getCurrentTrack ( );
276+ if (preloadTrackHandler != null && preloadTrackHandler .isTrack (id )) {
309277 trackHandler = preloadTrackHandler ;
310278 preloadTrackHandler = null ;
311279 trackHandler .sendSeek (state .getPositionMs ());
312280 } else {
313281 trackHandler = new TrackHandler (session , cacheManager , conf , this );
314- trackHandler .sendLoad (ref , play , state .getPositionMs ());
282+ trackHandler .sendLoad (id , play , state .getPositionMs ());
315283 state .setStatus (Spirc .PlayStatus .kPlayStatusLoading );
316284 }
317285
@@ -326,7 +294,7 @@ private void loadTrack(boolean play) {
326294 }
327295
328296 private void handlePlay () {
329- if (state .getStatus () == Spirc .PlayStatus .kPlayStatusPause ) {
297+ if (state .isStatus ( Spirc .PlayStatus .kPlayStatusPause ) ) {
330298 if (trackHandler != null ) trackHandler .sendPlay ();
331299 state .setStatus (Spirc .PlayStatus .kPlayStatusPlay );
332300 state .setPositionMeasuredAt (System .currentTimeMillis ());
@@ -335,7 +303,7 @@ private void handlePlay() {
335303 }
336304
337305 private void handlePause () {
338- if (state .getStatus () == Spirc .PlayStatus .kPlayStatusPlay ) {
306+ if (state .isStatus ( Spirc .PlayStatus .kPlayStatusPlay ) ) {
339307 if (trackHandler != null ) trackHandler .sendPause ();
340308 state .setStatus (Spirc .PlayStatus .kPlayStatusPause );
341309
@@ -349,7 +317,7 @@ private void handlePause() {
349317 }
350318
351319 private void handleNext () {
352- int newTrack = getQueuedTrack (true );
320+ int newTrack = tracksProvider . getNextTrackIndex (true );
353321 boolean play = true ;
354322 if (newTrack >= state .getTrackCount ()) {
355323 newTrack = 0 ;
@@ -365,26 +333,7 @@ private void handleNext() {
365333
366334 private void handlePrev () {
367335 if (getPosition () < 3000 ) {
368- List <Spirc .TrackRef > queueTracks = new ArrayList <>();
369- Iterator <Spirc .TrackRef > iter = state .getTrackList ().iterator ();
370- while (iter .hasNext ()) {
371- Spirc .TrackRef track = iter .next ();
372- if (track .getQueued ()) {
373- queueTracks .add (track );
374- iter .remove ();
375- }
376- }
377-
378- int current = state .getPlayingTrackIndex ();
379- int newIndex ;
380- if (current > 0 ) newIndex = current - 1 ;
381- else if (state .getRepeat ()) newIndex = state .getTrackCount () - 1 ;
382- else newIndex = 0 ;
383-
384- for (int i = 0 ; i < queueTracks .size (); i ++)
385- state .getTrackList ().add (newIndex + 1 + i , queueTracks .get (i ));
386-
387- state .setPlayingTrackIndex (newIndex );
336+ state .setPlayingTrackIndex (tracksProvider .getPrevTrackIndex (true ));
388337 state .setPositionMs (0 );
389338 state .setPositionMeasuredAt (System .currentTimeMillis ());
390339
@@ -397,16 +346,6 @@ private void handlePrev() {
397346 }
398347 }
399348
400- private int getQueuedTrack (boolean consume ) {
401- int current = state .getPlayingTrackIndex ();
402- if (state .getTrack (current ).getQueued ()) {
403- if (consume ) state .removeTrack (current );
404- return current ;
405- }
406-
407- return current + 1 ;
408- }
409-
410349 public interface PlayerConfiguration {
411350 @ NotNull
412351 StreamFeeder .AudioQuality preferredQuality ();
@@ -415,4 +354,69 @@ public interface PlayerConfiguration {
415354
416355 float normalisationPregain ();
417356 }
357+
358+ private class StateWrapper {
359+ private final Spirc .State .Builder state ;
360+
361+ StateWrapper (@ NotNull Spirc .State .Builder state ) {
362+ this .state = state ;
363+ }
364+
365+ @ NotNull
366+ Spirc .PlayStatus getStatus () {
367+ return state .getStatus ();
368+ }
369+
370+ void setStatus (@ NotNull Spirc .PlayStatus status ) {
371+ state .setStatus (status );
372+ }
373+
374+ boolean isStatus (@ NotNull Spirc .PlayStatus status ) {
375+ return status == getStatus ();
376+ }
377+
378+ boolean getShuffle () {
379+ return state .getShuffle ();
380+ }
381+
382+ void setShuffle (boolean shuffle ) {
383+ state .setShuffle (shuffle && (tracksProvider == null || tracksProvider .canShuffle ()));
384+ }
385+
386+ void update (@ NotNull Spirc .Frame frame ) {
387+ state .setContextUri (frame .getState ().getContextUri ());
388+ }
389+
390+ long getPositionMeasuredAt () {
391+ return state .getPositionMeasuredAt ();
392+ }
393+
394+ void setPositionMeasuredAt (long ms ) {
395+ state .setPositionMeasuredAt (ms );
396+ }
397+
398+ int getPositionMs () {
399+ return state .getPositionMs ();
400+ }
401+
402+ void setPositionMs (int pos ) {
403+ state .setPositionMs (pos );
404+ }
405+
406+ boolean getRepeat () {
407+ return state .getRepeat ();
408+ }
409+
410+ void setRepeat (boolean repeat ) {
411+ state .setRepeat (repeat && (tracksProvider == null || tracksProvider .canRepeat ()));
412+ }
413+
414+ void setPlayingTrackIndex (int i ) {
415+ state .setPlayingTrackIndex (i );
416+ }
417+
418+ int getTrackCount () {
419+ return state .getTrackCount ();
420+ }
421+ }
418422}
0 commit comments