package com.marverenic.music.player;
import android.graphics.Bitmap;
import com.marverenic.music.data.store.ReadOnlyPreferenceStore;
import com.marverenic.music.model.Song;
import java.util.List;
import rx.Observable;
import rx.Single;
/**
* A support interface for connecting the application UI to the media player. This interface defines
* basic commands and information sent and received from the player. Any data received from the
* player can be obtained through various get methods in this interface as observable streams. Any
* observable stream should always be kept up-to-date unless it is infeasible to do so.
*/
public interface PlayerController {
/**
* Gets error messages from the service that can be displayed on the UI
* @return An observable stream of user-presentable error messages
*/
Observable<String> getError();
/**
* Gets information messages from the service that can be displayed on the UI
* @return An observable stream of user-presentable info messages
*/
Observable<String> getInfo();
/**
* Generates a snapshot of the current playback state (useful for state restoration and undoing
* edits to the playback state)
* @return A single up-to-date player state
* @see #restorePlayerState(PlayerState) To restore this state
*/
Single<PlayerState> getPlayerState();
/**
* Restores a snapshot of a previous playback state. Any data in this player state will
* overwrite the current playback state
* @param restoreState The state to be restored
* @see #getPlayerState() To create a state to be restored
*/
void restorePlayerState(PlayerState restoreState);
/**
* Permanently ends music playback. This should only be called when exiting the application or
* when music playback will never be used for the rest of the lifetime of the app.
*/
void stop();
/**
* Skips to the next song in the queue according to the currently applied repeat settings.
*/
void skip();
/**
* Restarts the currently playing song if it is more than a couple of seconds into playback or
* if the current song is at the beginning of the queue, otherwise skips to the previous song
* in the queue.
*
* If the current song is at the beginning of the queue, this method will always restart it
* from the beginning, unless repeat all is enabled, in which case it will wrap around to the
* beginning of the last song in the queue.
*
* @see #updatePlayerPreferences(ReadOnlyPreferenceStore) for more information on this behavior
*/
void previous();
/**
* Pauses music if it is currently playing, or plays music if it is currently paused.
*/
void togglePlay();
/**
* Starts or resumes music playback. If music is already playing, this method does nothing.
*/
void play();
/**
* Pauses music playback. If music is already paused or stopped, this method does nothing.
*/
void pause();
/**
* Updates the settings used by the music player. Settings updated include equalizer, shuffle,
* and repeat settings. All settings are handled by the player as described below.
*
* <p>
* Equalizers are maintained internally automatically. When available and enabled with
* {@code preferenceStore.getEqualizerEnabled()}, the music player will bind and maintain
* the equalizer with settings obtained from {@code preferenceStore.getEqualizerSettings()}.
* </p>
*
* <p>
* Shuffle states are maintained internally. When shuffle is toggled and updated with this
* method, the music player will generate or restore the appropriate shuffled or original linear
* queue and continue playback seamlessly.
* </p>
*
* <p>
* Repeat settings will affect the behavior of song playback when a song finishes. With
* repeat all enabled, the queue will loop around when the last song completes. The behavior of
* {@link #skip()} and {@link #previous()} are also changed so that they will loop around the
* ends of the queue instead of their default behavior of pausing playback and restarting the
* current song unconditionally when at the end and beginning of the queue, respectively. With
* repeat one enabled, the current song will be replayed once it finishes. With repeat disabled,
* playback will end once the last song in the queue finishes. Both repeat one and repeat none
* don't affect the behavior of {@link #skip()} and {@link #previous()}.
* </p>
*
* @param preferenceStore The preferences to apply to the media player.
*/
void updatePlayerPreferences(ReadOnlyPreferenceStore preferenceStore);
/**
* Replaces the current queue. Playback will start from the beginning of {@code newPosition}.
* If shuffle is enabled, {@code newQueue} will be randomized, but playback will still start at
* the song at {@code newQueue.get(newPosition)} before the shuffle is applied.
* @param newQueue The replacement queue
* @param newPosition The index in the queue to start playback from
* @see #editQueue(List, int) If there is a small modification to the queue instead of an entire
* replacement to the queue
*/
void setQueue(List<Song> newQueue, int newPosition);
/**
* Empties the now playing queue and stops music playback.
*/
void clearQueue();
/**
* Skips to a different song in the queue.
* @param newPosition The song index in the queue to skip to.
*/
void changeSong(int newPosition);
/**
* Modifies the current queue. Unlike {@link #setQueue(List, int)}, this method will not
* reshuffle the current queue if shuffle is enabled.
* @param queue The replacement queue
* @param newPosition The index in the queue to start playback from
*/
void editQueue(List<Song> queue, int newPosition);
/**
* Enqueues a song to play after the current song. This method does nothing to prevent
* duplicates from being added to the queue.
* @param song The song to be played next.
*/
void queueNext(Song song);
/**
* Enqueues a group of songs to be played after the current song. Songs are enqueued in the
* same order they are passed in as. This method does nothing to prevent duplicate items from
* being added to the queue.
* @param songs The songs to be played next.
*/
void queueNext(List<Song> songs);
/**
* Enqueues a song at the end of the now playing queue. This method does nothing to prevent
* duplicates from being added to the queue.
* @param song The song to be added at the end of the queue.
*/
void queueLast(Song song);
/**
* Enqueues a group of songs at the end of the now playing queue. This method does nothing to
* prevent duplicate items from being added to the queue.
* @param songs The songs to be added at the end of the queue.
*/
void queueLast(List<Song> songs);
/**
* Seek to a new position within the currently playing track
* @param position The position (in milliseconds since the start of the current song)
* to seek to.
*/
void seek(int position);
/**
* @return Whether or not music is currently being played. A value of {@code true} in the
* observable stream means that music is playing, a value of {@code false} means it is
* not playing (nothing else is guaranteed about the state of music playback).
*/
Observable<Boolean> isPlaying();
/**
* @return The currently playing song as an observable stream.
*/
Observable<Song> getNowPlaying();
/**
* @return The queue as an observable stream. This value is updated whenever the queue changes,
* including for changes caused by toggling shuffle.
*/
Observable<List<Song>> getQueue();
/**
* @return The index of the currently playing song in the queue as an observable stream.
*/
Observable<Integer> getQueuePosition();
/**
* @return The current seek position in the current song as an observable stream. This value is
* kept up-to-date, but may only be updated every 100 ms or so to preserve battery life.
*/
Observable<Integer> getCurrentPosition();
/**
* @return The duration of the currently playing song as an observable stream.
*/
Observable<Integer> getDuration();
/**
* Gets the current shuffle status of the music player. This may be different from the
* application if {@link #updatePlayerPreferences(ReadOnlyPreferenceStore)} isn't called
* correctly.
* @return The current shuffle state as an observable stream. A value of {@code true} means that
* shuffle is enabled, and {@code false} means that it is disabled.
*/
Observable<Boolean> isShuffleEnabled();
/**
* Gets the current repeat mode. This will be a number greater than 1 if Multi-Repeat is enabled
* (with the value representing the number of times the song will be played back-to back), or
* one of either {@link MusicPlayer#REPEAT_NONE}, {@link MusicPlayer#REPEAT_ONE},
* or {@link MusicPlayer#REPEAT_ALL}
* @return The current repeat mode
* @see #updatePlayerPreferences(ReadOnlyPreferenceStore) To set the repeat mode to one of
* the standard repeat modes
* @see #setMultiRepeatCount(int) To set the multi-repeat count
*/
Observable<Integer> getRepeatMode();
/**
* Enables Multi-Repeat. With Multi-Repeat enabled, the current song will be played back-to-back
* {@code count} times. When the next song starts (either because the song was skipped or
* because the counter reached 0), Multi-Repeat will be disabled and the previous repeat mode
* will be reapplied.
* @param count The number of times to repeat the current song back-to-back.
*/
void setMultiRepeatCount(int count);
/**
* Gets the ending timestamp of the currently set sleep timer. When
* {@link System#currentTimeMillis()} exceeds this value, music playback will be paused.
* @return An observable stream of sleep timer ending timestamps. If the sleep timer is
* disabled, a timestamp in the past (normally {@code 0}) will be passed.
*/
Observable<Long> getSleepTimerEndTime();
/**
* Sets a new or updates an existing sleep timer to pause music at a certain timestamp.
* @param timestampInMillis The time (in milliseconds since the Unix epoch) to pause music
* playback. This value will be compared against
* {@link System#currentTimeMillis()}
* @see #disableSleepTimer() To disable this sleep timer
*/
void setSleepTimerEndTime(long timestampInMillis);
/**
* Ends any previously set sleep timer without triggering it.
* @see #setSleepTimerEndTime(long) To enable a sleep timer
*/
void disableSleepTimer();
/**
* Gets the embedded album artwork of the now playing song
* @return An observable stream of bitmaps for album artwork. If there is no embedded artwork,
* or if it can't be loaded, then {@code null} will be passed in the stream.
*/
Observable<Bitmap> getArtwork();
}