Merge MediaPlayerController interface & implementation
This commit is contained in:
parent
6943dc5895
commit
402fe961ba
|
@ -73,7 +73,7 @@ public class JukeboxMediaPlayer
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
||||||
// TODO: These create circular references, try to refactor
|
// TODO: These create circular references, try to refactor
|
||||||
private final Lazy<MediaPlayerControllerImpl> mediaPlayerControllerLazy = inject(MediaPlayerControllerImpl.class);
|
private final Lazy<MediaPlayerController> mediaPlayerControllerLazy = inject(MediaPlayerController.class);
|
||||||
private final Downloader downloader;
|
private final Downloader downloader;
|
||||||
|
|
||||||
// TODO: Report warning if queue fills up.
|
// TODO: Report warning if queue fills up.
|
||||||
|
|
|
@ -18,112 +18,595 @@
|
||||||
*/
|
*/
|
||||||
package org.moire.ultrasonic.service;
|
package org.moire.ultrasonic.service;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
import org.koin.java.KoinJavaComponent;
|
||||||
|
import org.moire.ultrasonic.data.ActiveServerProvider;
|
||||||
|
import org.moire.ultrasonic.domain.MusicDirectory;
|
||||||
import org.moire.ultrasonic.domain.MusicDirectory.Entry;
|
import org.moire.ultrasonic.domain.MusicDirectory.Entry;
|
||||||
import org.moire.ultrasonic.domain.PlayerState;
|
import org.moire.ultrasonic.domain.PlayerState;
|
||||||
import org.moire.ultrasonic.domain.RepeatMode;
|
import org.moire.ultrasonic.domain.RepeatMode;
|
||||||
|
import org.moire.ultrasonic.domain.UserInfo;
|
||||||
|
import org.moire.ultrasonic.featureflags.Feature;
|
||||||
|
import org.moire.ultrasonic.featureflags.FeatureStorage;
|
||||||
|
import org.moire.ultrasonic.util.ShufflePlayBuffer;
|
||||||
|
import org.moire.ultrasonic.util.Util;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import kotlin.Lazy;
|
||||||
|
|
||||||
|
import static org.koin.java.KoinJavaComponent.inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface contains all functions which are necessary for the Application UI
|
* The implementation of the Media Player Controller.
|
||||||
|
* This class contains everything that is necessary for the Application UI
|
||||||
* to control the Media Player implementation.
|
* to control the Media Player implementation.
|
||||||
*
|
*
|
||||||
* @author Sindre Mehus
|
* @author Sindre Mehus, Joshua Bahnsen
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public interface MediaPlayerController
|
public class MediaPlayerController
|
||||||
{
|
{
|
||||||
void download(List<Entry> songs, boolean save, boolean autoplay, boolean playNext, boolean shuffle, boolean newPlaylist);
|
private boolean created = false;
|
||||||
|
private String suggestedPlaylistName;
|
||||||
|
private boolean keepScreenOn;
|
||||||
|
|
||||||
void downloadBackground(List<Entry> songs, boolean save);
|
private boolean showVisualization;
|
||||||
|
private boolean autoPlayStart;
|
||||||
|
|
||||||
void setShufflePlayEnabled(boolean enabled);
|
private final Context context;
|
||||||
|
private final Lazy<JukeboxMediaPlayer> jukeboxMediaPlayer = inject(JukeboxMediaPlayer.class);
|
||||||
|
private final Lazy<ActiveServerProvider> activeServerProvider = inject(ActiveServerProvider.class);
|
||||||
|
|
||||||
boolean isShufflePlayEnabled();
|
private final DownloadQueueSerializer downloadQueueSerializer;
|
||||||
|
private final ExternalStorageMonitor externalStorageMonitor;
|
||||||
|
private final Downloader downloader;
|
||||||
|
private final ShufflePlayBuffer shufflePlayBuffer;
|
||||||
|
private final LocalMediaPlayer localMediaPlayer;
|
||||||
|
|
||||||
void shuffle();
|
public MediaPlayerController(Context context, DownloadQueueSerializer downloadQueueSerializer,
|
||||||
|
ExternalStorageMonitor externalStorageMonitor, Downloader downloader,
|
||||||
|
ShufflePlayBuffer shufflePlayBuffer, LocalMediaPlayer localMediaPlayer)
|
||||||
|
{
|
||||||
|
this.context = context;
|
||||||
|
this.downloadQueueSerializer = downloadQueueSerializer;
|
||||||
|
this.externalStorageMonitor = externalStorageMonitor;
|
||||||
|
this.downloader = downloader;
|
||||||
|
this.shufflePlayBuffer = shufflePlayBuffer;
|
||||||
|
this.localMediaPlayer = localMediaPlayer;
|
||||||
|
|
||||||
RepeatMode getRepeatMode();
|
Timber.i("MediaPlayerController constructed");
|
||||||
|
}
|
||||||
|
|
||||||
void setRepeatMode(RepeatMode repeatMode);
|
public void onCreate()
|
||||||
|
{
|
||||||
|
if (created) return;
|
||||||
|
this.externalStorageMonitor.onCreate(this::reset);
|
||||||
|
|
||||||
boolean getKeepScreenOn();
|
setJukeboxEnabled(activeServerProvider.getValue().getActiveServer().getJukeboxByDefault());
|
||||||
|
created = true;
|
||||||
|
|
||||||
void setKeepScreenOn(boolean screenOn);
|
Timber.i("MediaPlayerController created");
|
||||||
|
}
|
||||||
|
|
||||||
boolean getShowVisualization();
|
public void onDestroy()
|
||||||
|
{
|
||||||
|
if (!created) return;
|
||||||
|
externalStorageMonitor.onDestroy();
|
||||||
|
context.stopService(new Intent(context, MediaPlayerService.class));
|
||||||
|
downloader.onDestroy();
|
||||||
|
created = false;
|
||||||
|
|
||||||
void setShowVisualization(boolean showVisualization);
|
Timber.i("MediaPlayerController destroyed");
|
||||||
|
}
|
||||||
|
public synchronized void restore(List<MusicDirectory.Entry> songs, final int currentPlayingIndex, final int currentPlayingPosition, final boolean autoPlay, boolean newPlaylist)
|
||||||
|
{
|
||||||
|
download(songs, false, false, false, false, newPlaylist);
|
||||||
|
|
||||||
void clear();
|
if (currentPlayingIndex != -1)
|
||||||
|
{
|
||||||
|
MediaPlayerService.executeOnStartedMediaPlayerService(context, (mediaPlayerService) ->
|
||||||
|
{
|
||||||
|
mediaPlayerService.play(currentPlayingIndex, autoPlayStart);
|
||||||
|
|
||||||
void clearIncomplete();
|
if (localMediaPlayer.currentPlaying != null)
|
||||||
|
{
|
||||||
|
if (autoPlay && jukeboxMediaPlayer.getValue().isEnabled())
|
||||||
|
{
|
||||||
|
jukeboxMediaPlayer.getValue().skip(downloader.getCurrentPlayingIndex(), currentPlayingPosition / 1000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (localMediaPlayer.currentPlaying.isCompleteFileAvailable())
|
||||||
|
{
|
||||||
|
localMediaPlayer.play(localMediaPlayer.currentPlaying, currentPlayingPosition, autoPlay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
autoPlayStart = false;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void remove(DownloadFile downloadFile);
|
public synchronized void preload()
|
||||||
|
{
|
||||||
|
MediaPlayerService.getInstance(context);
|
||||||
|
}
|
||||||
|
|
||||||
void play(int index);
|
public synchronized void play(final int index)
|
||||||
|
{
|
||||||
|
MediaPlayerService.executeOnStartedMediaPlayerService(context, (mediaPlayerService) -> {
|
||||||
|
mediaPlayerService.play(index, true);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void seekTo(int position);
|
public synchronized void play()
|
||||||
|
{
|
||||||
|
MediaPlayerService.executeOnStartedMediaPlayerService(context, (mediaPlayerService) -> {
|
||||||
|
|
||||||
void previous();
|
mediaPlayerService.play();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void next();
|
public synchronized void resumeOrPlay()
|
||||||
|
{
|
||||||
|
MediaPlayerService.executeOnStartedMediaPlayerService(context, (mediaPlayerService) -> {
|
||||||
|
mediaPlayerService.resumeOrPlay();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void pause();
|
public synchronized void togglePlayPause()
|
||||||
|
{
|
||||||
|
if (localMediaPlayer.playerState == PlayerState.IDLE) autoPlayStart = true;
|
||||||
|
MediaPlayerService.executeOnStartedMediaPlayerService(context, (mediaPlayerService) -> {
|
||||||
|
mediaPlayerService.togglePlayPause();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void stop();
|
public synchronized void start()
|
||||||
|
{
|
||||||
|
MediaPlayerService.executeOnStartedMediaPlayerService(context, (mediaPlayerService) -> {
|
||||||
|
mediaPlayerService.start();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void start();
|
public synchronized void seekTo(final int position)
|
||||||
|
{
|
||||||
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
|
if (mediaPlayerService != null) mediaPlayerService.seekTo(position);
|
||||||
|
}
|
||||||
|
|
||||||
void reset();
|
public synchronized void pause()
|
||||||
|
{
|
||||||
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
|
if (mediaPlayerService != null) mediaPlayerService.pause();
|
||||||
|
}
|
||||||
|
|
||||||
PlayerState getPlayerState();
|
public synchronized void stop()
|
||||||
|
{
|
||||||
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
|
if (mediaPlayerService != null) mediaPlayerService.stop();
|
||||||
|
}
|
||||||
|
|
||||||
int getPlayerPosition();
|
public synchronized void download(List<MusicDirectory.Entry> songs, boolean save, boolean autoPlay, boolean playNext, boolean shuffle, boolean newPlaylist)
|
||||||
|
{
|
||||||
|
downloader.download(songs, save, autoPlay, playNext, newPlaylist);
|
||||||
|
jukeboxMediaPlayer.getValue().updatePlaylist();
|
||||||
|
|
||||||
int getPlayerDuration();
|
if (shuffle) shuffle();
|
||||||
|
|
||||||
void delete(List<Entry> songs);
|
if (!playNext && !autoPlay && (downloader.downloadList.size() - 1) == downloader.getCurrentPlayingIndex())
|
||||||
|
{
|
||||||
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
|
if (mediaPlayerService != null) mediaPlayerService.setNextPlaying();
|
||||||
|
}
|
||||||
|
|
||||||
void unpin(List<Entry> songs);
|
if (autoPlay)
|
||||||
|
{
|
||||||
|
play(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (localMediaPlayer.currentPlaying == null && downloader.downloadList.size() > 0)
|
||||||
|
{
|
||||||
|
localMediaPlayer.currentPlaying = downloader.downloadList.get(0);
|
||||||
|
localMediaPlayer.currentPlaying.setPlaying(true);
|
||||||
|
}
|
||||||
|
|
||||||
void setSuggestedPlaylistName(String name);
|
downloader.checkDownloads();
|
||||||
|
}
|
||||||
|
|
||||||
String getSuggestedPlaylistName();
|
downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition());
|
||||||
|
}
|
||||||
|
|
||||||
boolean isJukeboxEnabled();
|
public synchronized void downloadBackground(List<MusicDirectory.Entry> songs, boolean save)
|
||||||
|
{
|
||||||
|
downloader.downloadBackground(songs, save);
|
||||||
|
downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition());
|
||||||
|
}
|
||||||
|
|
||||||
boolean isJukeboxAvailable();
|
public synchronized void setCurrentPlaying(DownloadFile currentPlaying)
|
||||||
|
{
|
||||||
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
|
if (mediaPlayerService != null) localMediaPlayer.setCurrentPlaying(currentPlaying);
|
||||||
|
}
|
||||||
|
|
||||||
void setJukeboxEnabled(boolean b);
|
public synchronized void setCurrentPlaying(int index)
|
||||||
|
{
|
||||||
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
|
if (mediaPlayerService != null) mediaPlayerService.setCurrentPlaying(index);
|
||||||
|
}
|
||||||
|
|
||||||
void adjustJukeboxVolume(boolean up);
|
public synchronized void setPlayerState(PlayerState state)
|
||||||
|
{
|
||||||
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
|
if (mediaPlayerService != null) localMediaPlayer.setPlayerState(state);
|
||||||
|
}
|
||||||
|
|
||||||
void togglePlayPause();
|
public void stopJukeboxService()
|
||||||
|
{
|
||||||
|
jukeboxMediaPlayer.getValue().stopJukeboxService();
|
||||||
|
}
|
||||||
|
|
||||||
void setVolume(float volume);
|
public synchronized void setShufflePlayEnabled(boolean enabled)
|
||||||
|
{
|
||||||
|
shufflePlayBuffer.isEnabled = enabled;
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
downloader.checkDownloads();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void restore(List<Entry> songs, int currentPlayingIndex, int currentPlayingPosition, boolean autoPlay, boolean newPlaylist);
|
public boolean isShufflePlayEnabled()
|
||||||
|
{
|
||||||
|
return shufflePlayBuffer.isEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
void stopJukeboxService();
|
public synchronized void shuffle()
|
||||||
|
{
|
||||||
|
downloader.shuffle();
|
||||||
|
|
||||||
void updateNotification();
|
downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition());
|
||||||
|
jukeboxMediaPlayer.getValue().updatePlaylist();
|
||||||
|
|
||||||
void setSongRating(final int rating);
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
|
if (mediaPlayerService != null) mediaPlayerService.setNextPlaying();
|
||||||
|
}
|
||||||
|
|
||||||
DownloadFile getCurrentPlaying();
|
public RepeatMode getRepeatMode()
|
||||||
|
{
|
||||||
|
return Util.getRepeatMode();
|
||||||
|
}
|
||||||
|
|
||||||
int getPlaylistSize();
|
public synchronized void setRepeatMode(RepeatMode repeatMode)
|
||||||
|
{
|
||||||
|
Util.setRepeatMode(repeatMode);
|
||||||
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
|
if (mediaPlayerService != null) mediaPlayerService.setNextPlaying();
|
||||||
|
}
|
||||||
|
|
||||||
int getCurrentPlayingNumberOnPlaylist();
|
public boolean getKeepScreenOn()
|
||||||
|
{
|
||||||
|
return keepScreenOn;
|
||||||
|
}
|
||||||
|
|
||||||
DownloadFile getCurrentDownloading();
|
public void setKeepScreenOn(boolean keepScreenOn)
|
||||||
|
{
|
||||||
|
this.keepScreenOn = keepScreenOn;
|
||||||
|
}
|
||||||
|
|
||||||
List<DownloadFile> getPlayList();
|
public boolean getShowVisualization()
|
||||||
|
{
|
||||||
|
return showVisualization;
|
||||||
|
}
|
||||||
|
|
||||||
long getPlayListUpdateRevision();
|
public void setShowVisualization(boolean showVisualization)
|
||||||
|
{
|
||||||
|
this.showVisualization = showVisualization;
|
||||||
|
}
|
||||||
|
|
||||||
long getPlayListDuration();
|
public synchronized void clear()
|
||||||
|
{
|
||||||
|
clear(true);
|
||||||
|
}
|
||||||
|
|
||||||
DownloadFile getDownloadFileForSong(Entry song);
|
public synchronized void clear(boolean serialize)
|
||||||
}
|
{
|
||||||
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
|
if (mediaPlayerService != null) {
|
||||||
|
mediaPlayerService.clear(serialize);
|
||||||
|
} else {
|
||||||
|
// If no MediaPlayerService is available, just empty the playlist
|
||||||
|
downloader.clear();
|
||||||
|
if (serialize) {
|
||||||
|
downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList,
|
||||||
|
downloader.getCurrentPlayingIndex(), getPlayerPosition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jukeboxMediaPlayer.getValue().updatePlaylist();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void clearIncomplete()
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
Iterator<DownloadFile> iterator = downloader.downloadList.iterator();
|
||||||
|
|
||||||
|
while (iterator.hasNext())
|
||||||
|
{
|
||||||
|
DownloadFile downloadFile = iterator.next();
|
||||||
|
if (!downloadFile.isCompleteFileAvailable())
|
||||||
|
{
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition());
|
||||||
|
jukeboxMediaPlayer.getValue().updatePlaylist();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void remove(DownloadFile downloadFile)
|
||||||
|
{
|
||||||
|
if (downloadFile == localMediaPlayer.currentPlaying)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
setCurrentPlaying(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
downloader.removeDownloadFile(downloadFile);
|
||||||
|
|
||||||
|
downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition());
|
||||||
|
jukeboxMediaPlayer.getValue().updatePlaylist();
|
||||||
|
|
||||||
|
if (downloadFile == localMediaPlayer.nextPlaying)
|
||||||
|
{
|
||||||
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
|
if (mediaPlayerService != null) mediaPlayerService.setNextPlaying();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void delete(List<MusicDirectory.Entry> songs)
|
||||||
|
{
|
||||||
|
for (MusicDirectory.Entry song : songs)
|
||||||
|
{
|
||||||
|
downloader.getDownloadFileForSong(song).delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void unpin(List<MusicDirectory.Entry> songs)
|
||||||
|
{
|
||||||
|
for (MusicDirectory.Entry song : songs)
|
||||||
|
{
|
||||||
|
downloader.getDownloadFileForSong(song).unpin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void previous()
|
||||||
|
{
|
||||||
|
int index = downloader.getCurrentPlayingIndex();
|
||||||
|
if (index == -1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restart song if played more than five seconds.
|
||||||
|
if (getPlayerPosition() > 5000 || index == 0)
|
||||||
|
{
|
||||||
|
play(index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
play(index - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void next()
|
||||||
|
{
|
||||||
|
int index = downloader.getCurrentPlayingIndex();
|
||||||
|
if (index != -1)
|
||||||
|
{
|
||||||
|
switch (getRepeatMode())
|
||||||
|
{
|
||||||
|
case SINGLE:
|
||||||
|
case OFF:
|
||||||
|
if (index + 1 >= 0 && index + 1 < downloader.downloadList.size()) {
|
||||||
|
play(index + 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ALL:
|
||||||
|
play((index + 1) % downloader.downloadList.size());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void reset()
|
||||||
|
{
|
||||||
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
|
if (mediaPlayerService != null) localMediaPlayer.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized int getPlayerPosition()
|
||||||
|
{
|
||||||
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
|
if (mediaPlayerService == null) return 0;
|
||||||
|
return mediaPlayerService.getPlayerPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized int getPlayerDuration()
|
||||||
|
{
|
||||||
|
if (localMediaPlayer.currentPlaying != null)
|
||||||
|
{
|
||||||
|
Integer duration = localMediaPlayer.currentPlaying.getSong().getDuration();
|
||||||
|
if (duration != null)
|
||||||
|
{
|
||||||
|
return duration * 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
|
if (mediaPlayerService == null) return 0;
|
||||||
|
return mediaPlayerService.getPlayerDuration();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayerState getPlayerState() { return localMediaPlayer.playerState; }
|
||||||
|
|
||||||
|
public void setSuggestedPlaylistName(String name)
|
||||||
|
{
|
||||||
|
this.suggestedPlaylistName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSuggestedPlaylistName()
|
||||||
|
{
|
||||||
|
return suggestedPlaylistName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isJukeboxEnabled()
|
||||||
|
{
|
||||||
|
return jukeboxMediaPlayer.getValue().isEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isJukeboxAvailable()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String username = activeServerProvider.getValue().getActiveServer().getUserName();
|
||||||
|
UserInfo user = MusicServiceFactory.getMusicService().getUser(username);
|
||||||
|
return user.getJukeboxRole();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Timber.w(e, "Error getting user information");
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJukeboxEnabled(boolean jukeboxEnabled)
|
||||||
|
{
|
||||||
|
jukeboxMediaPlayer.getValue().setEnabled(jukeboxEnabled);
|
||||||
|
setPlayerState(PlayerState.IDLE);
|
||||||
|
|
||||||
|
if (jukeboxEnabled)
|
||||||
|
{
|
||||||
|
jukeboxMediaPlayer.getValue().startJukeboxService();
|
||||||
|
|
||||||
|
reset();
|
||||||
|
|
||||||
|
// Cancel current download, if necessary.
|
||||||
|
if (downloader.currentDownloading != null)
|
||||||
|
{
|
||||||
|
downloader.currentDownloading.cancelDownload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jukeboxMediaPlayer.getValue().stopJukeboxService();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void adjustJukeboxVolume(boolean up)
|
||||||
|
{
|
||||||
|
jukeboxMediaPlayer.getValue().adjustVolume(up);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVolume(float volume)
|
||||||
|
{
|
||||||
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
|
if (mediaPlayerService != null) localMediaPlayer.setVolume(volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateNotification()
|
||||||
|
{
|
||||||
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
|
if (mediaPlayerService != null) mediaPlayerService.updateNotification(localMediaPlayer.playerState, localMediaPlayer.currentPlaying);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggleSongStarred() {
|
||||||
|
if (localMediaPlayer.currentPlaying == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
final Entry song = localMediaPlayer.currentPlaying.getSong();
|
||||||
|
|
||||||
|
// Trigger an update
|
||||||
|
localMediaPlayer.setCurrentPlaying(localMediaPlayer.currentPlaying);
|
||||||
|
|
||||||
|
song.setStarred(!song.getStarred());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSongRating(final int rating)
|
||||||
|
{
|
||||||
|
if (!KoinJavaComponent.get(FeatureStorage.class).isFeatureEnabled(Feature.FIVE_STAR_RATING))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (localMediaPlayer.currentPlaying == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
final Entry song = localMediaPlayer.currentPlaying.getSong();
|
||||||
|
song.setUserRating(rating);
|
||||||
|
|
||||||
|
new Thread(() -> {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MusicServiceFactory.getMusicService().setRating(song.getId(), rating);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Timber.e(e);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
updateNotification();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DownloadFile getCurrentPlaying() {
|
||||||
|
return localMediaPlayer.currentPlaying;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPlaylistSize() {
|
||||||
|
return downloader.downloadList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCurrentPlayingNumberOnPlaylist() {
|
||||||
|
return downloader.getCurrentPlayingIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DownloadFile getCurrentDownloading() {
|
||||||
|
return downloader.currentDownloading;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DownloadFile> getPlayList() {
|
||||||
|
return downloader.downloadList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getPlayListUpdateRevision() {
|
||||||
|
return downloader.getDownloadListUpdateRevision();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getPlayListDuration() {
|
||||||
|
return downloader.getDownloadListDuration();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DownloadFile getDownloadFileForSong(Entry song) {
|
||||||
|
return downloader.getDownloadFileForSong(song);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,661 +0,0 @@
|
||||||
/*
|
|
||||||
This file is part of Subsonic.
|
|
||||||
|
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Copyright 2009 (C) Sindre Mehus
|
|
||||||
*/
|
|
||||||
package org.moire.ultrasonic.service;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import timber.log.Timber;
|
|
||||||
|
|
||||||
import org.koin.java.KoinJavaComponent;
|
|
||||||
import org.moire.ultrasonic.data.ActiveServerProvider;
|
|
||||||
import org.moire.ultrasonic.domain.MusicDirectory;
|
|
||||||
import org.moire.ultrasonic.domain.MusicDirectory.Entry;
|
|
||||||
import org.moire.ultrasonic.domain.PlayerState;
|
|
||||||
import org.moire.ultrasonic.domain.RepeatMode;
|
|
||||||
import org.moire.ultrasonic.domain.UserInfo;
|
|
||||||
import org.moire.ultrasonic.featureflags.Feature;
|
|
||||||
import org.moire.ultrasonic.featureflags.FeatureStorage;
|
|
||||||
import org.moire.ultrasonic.util.ShufflePlayBuffer;
|
|
||||||
import org.moire.ultrasonic.util.Util;
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import kotlin.Lazy;
|
|
||||||
|
|
||||||
import static org.koin.java.KoinJavaComponent.inject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The implementation of the Media Player Controller.
|
|
||||||
* This class contains everything that is necessary for the Application UI
|
|
||||||
* to control the Media Player implementation.
|
|
||||||
*
|
|
||||||
* @author Sindre Mehus, Joshua Bahnsen
|
|
||||||
* @version $Id$
|
|
||||||
*/
|
|
||||||
public class MediaPlayerControllerImpl implements MediaPlayerController
|
|
||||||
{
|
|
||||||
private boolean created = false;
|
|
||||||
private String suggestedPlaylistName;
|
|
||||||
private boolean keepScreenOn;
|
|
||||||
|
|
||||||
private boolean showVisualization;
|
|
||||||
private boolean autoPlayStart;
|
|
||||||
|
|
||||||
private final Context context;
|
|
||||||
private final Lazy<JukeboxMediaPlayer> jukeboxMediaPlayer = inject(JukeboxMediaPlayer.class);
|
|
||||||
private final Lazy<ActiveServerProvider> activeServerProvider = inject(ActiveServerProvider.class);
|
|
||||||
|
|
||||||
private final DownloadQueueSerializer downloadQueueSerializer;
|
|
||||||
private final ExternalStorageMonitor externalStorageMonitor;
|
|
||||||
private final Downloader downloader;
|
|
||||||
private final ShufflePlayBuffer shufflePlayBuffer;
|
|
||||||
private final LocalMediaPlayer localMediaPlayer;
|
|
||||||
|
|
||||||
public MediaPlayerControllerImpl(Context context, DownloadQueueSerializer downloadQueueSerializer,
|
|
||||||
ExternalStorageMonitor externalStorageMonitor, Downloader downloader,
|
|
||||||
ShufflePlayBuffer shufflePlayBuffer, LocalMediaPlayer localMediaPlayer)
|
|
||||||
{
|
|
||||||
this.context = context;
|
|
||||||
this.downloadQueueSerializer = downloadQueueSerializer;
|
|
||||||
this.externalStorageMonitor = externalStorageMonitor;
|
|
||||||
this.downloader = downloader;
|
|
||||||
this.shufflePlayBuffer = shufflePlayBuffer;
|
|
||||||
this.localMediaPlayer = localMediaPlayer;
|
|
||||||
|
|
||||||
Timber.i("MediaPlayerControllerImpl constructed");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onCreate()
|
|
||||||
{
|
|
||||||
if (created) return;
|
|
||||||
this.externalStorageMonitor.onCreate(this::reset);
|
|
||||||
|
|
||||||
setJukeboxEnabled(activeServerProvider.getValue().getActiveServer().getJukeboxByDefault());
|
|
||||||
created = true;
|
|
||||||
|
|
||||||
Timber.i("MediaPlayerControllerImpl created");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onDestroy()
|
|
||||||
{
|
|
||||||
if (!created) return;
|
|
||||||
externalStorageMonitor.onDestroy();
|
|
||||||
context.stopService(new Intent(context, MediaPlayerService.class));
|
|
||||||
downloader.onDestroy();
|
|
||||||
created = false;
|
|
||||||
|
|
||||||
Timber.i("MediaPlayerControllerImpl destroyed");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void restore(List<MusicDirectory.Entry> songs, final int currentPlayingIndex, final int currentPlayingPosition, final boolean autoPlay, boolean newPlaylist)
|
|
||||||
{
|
|
||||||
download(songs, false, false, false, false, newPlaylist);
|
|
||||||
|
|
||||||
if (currentPlayingIndex != -1)
|
|
||||||
{
|
|
||||||
MediaPlayerService.executeOnStartedMediaPlayerService(context, (mediaPlayerService) ->
|
|
||||||
{
|
|
||||||
mediaPlayerService.play(currentPlayingIndex, autoPlayStart);
|
|
||||||
|
|
||||||
if (localMediaPlayer.currentPlaying != null)
|
|
||||||
{
|
|
||||||
if (autoPlay && jukeboxMediaPlayer.getValue().isEnabled())
|
|
||||||
{
|
|
||||||
jukeboxMediaPlayer.getValue().skip(downloader.getCurrentPlayingIndex(), currentPlayingPosition / 1000);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (localMediaPlayer.currentPlaying.isCompleteFileAvailable())
|
|
||||||
{
|
|
||||||
localMediaPlayer.play(localMediaPlayer.currentPlaying, currentPlayingPosition, autoPlay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
autoPlayStart = false;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void preload()
|
|
||||||
{
|
|
||||||
MediaPlayerService.getInstance(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void play(final int index)
|
|
||||||
{
|
|
||||||
MediaPlayerService.executeOnStartedMediaPlayerService(context, (mediaPlayerService) -> {
|
|
||||||
mediaPlayerService.play(index, true);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void play()
|
|
||||||
{
|
|
||||||
MediaPlayerService.executeOnStartedMediaPlayerService(context, (mediaPlayerService) -> {
|
|
||||||
|
|
||||||
mediaPlayerService.play();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void resumeOrPlay()
|
|
||||||
{
|
|
||||||
MediaPlayerService.executeOnStartedMediaPlayerService(context, (mediaPlayerService) -> {
|
|
||||||
mediaPlayerService.resumeOrPlay();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void togglePlayPause()
|
|
||||||
{
|
|
||||||
if (localMediaPlayer.playerState == PlayerState.IDLE) autoPlayStart = true;
|
|
||||||
MediaPlayerService.executeOnStartedMediaPlayerService(context, (mediaPlayerService) -> {
|
|
||||||
mediaPlayerService.togglePlayPause();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void start()
|
|
||||||
{
|
|
||||||
MediaPlayerService.executeOnStartedMediaPlayerService(context, (mediaPlayerService) -> {
|
|
||||||
mediaPlayerService.start();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void seekTo(final int position)
|
|
||||||
{
|
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
|
||||||
if (mediaPlayerService != null) mediaPlayerService.seekTo(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void pause()
|
|
||||||
{
|
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
|
||||||
if (mediaPlayerService != null) mediaPlayerService.pause();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void stop()
|
|
||||||
{
|
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
|
||||||
if (mediaPlayerService != null) mediaPlayerService.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void download(List<MusicDirectory.Entry> songs, boolean save, boolean autoPlay, boolean playNext, boolean shuffle, boolean newPlaylist)
|
|
||||||
{
|
|
||||||
downloader.download(songs, save, autoPlay, playNext, newPlaylist);
|
|
||||||
jukeboxMediaPlayer.getValue().updatePlaylist();
|
|
||||||
|
|
||||||
if (shuffle) shuffle();
|
|
||||||
|
|
||||||
if (!playNext && !autoPlay && (downloader.downloadList.size() - 1) == downloader.getCurrentPlayingIndex())
|
|
||||||
{
|
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
|
||||||
if (mediaPlayerService != null) mediaPlayerService.setNextPlaying();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (autoPlay)
|
|
||||||
{
|
|
||||||
play(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (localMediaPlayer.currentPlaying == null && downloader.downloadList.size() > 0)
|
|
||||||
{
|
|
||||||
localMediaPlayer.currentPlaying = downloader.downloadList.get(0);
|
|
||||||
localMediaPlayer.currentPlaying.setPlaying(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
downloader.checkDownloads();
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void downloadBackground(List<MusicDirectory.Entry> songs, boolean save)
|
|
||||||
{
|
|
||||||
downloader.downloadBackground(songs, save);
|
|
||||||
downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void setCurrentPlaying(DownloadFile currentPlaying)
|
|
||||||
{
|
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
|
||||||
if (mediaPlayerService != null) localMediaPlayer.setCurrentPlaying(currentPlaying);
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void setCurrentPlaying(int index)
|
|
||||||
{
|
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
|
||||||
if (mediaPlayerService != null) mediaPlayerService.setCurrentPlaying(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void setPlayerState(PlayerState state)
|
|
||||||
{
|
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
|
||||||
if (mediaPlayerService != null) localMediaPlayer.setPlayerState(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopJukeboxService()
|
|
||||||
{
|
|
||||||
jukeboxMediaPlayer.getValue().stopJukeboxService();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void setShufflePlayEnabled(boolean enabled)
|
|
||||||
{
|
|
||||||
shufflePlayBuffer.isEnabled = enabled;
|
|
||||||
if (enabled)
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
downloader.checkDownloads();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isShufflePlayEnabled()
|
|
||||||
{
|
|
||||||
return shufflePlayBuffer.isEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void shuffle()
|
|
||||||
{
|
|
||||||
downloader.shuffle();
|
|
||||||
|
|
||||||
downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition());
|
|
||||||
jukeboxMediaPlayer.getValue().updatePlaylist();
|
|
||||||
|
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
|
||||||
if (mediaPlayerService != null) mediaPlayerService.setNextPlaying();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RepeatMode getRepeatMode()
|
|
||||||
{
|
|
||||||
return Util.getRepeatMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void setRepeatMode(RepeatMode repeatMode)
|
|
||||||
{
|
|
||||||
Util.setRepeatMode(repeatMode);
|
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
|
||||||
if (mediaPlayerService != null) mediaPlayerService.setNextPlaying();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean getKeepScreenOn()
|
|
||||||
{
|
|
||||||
return keepScreenOn;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setKeepScreenOn(boolean keepScreenOn)
|
|
||||||
{
|
|
||||||
this.keepScreenOn = keepScreenOn;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean getShowVisualization()
|
|
||||||
{
|
|
||||||
return showVisualization;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setShowVisualization(boolean showVisualization)
|
|
||||||
{
|
|
||||||
this.showVisualization = showVisualization;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void clear()
|
|
||||||
{
|
|
||||||
clear(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void clear(boolean serialize)
|
|
||||||
{
|
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
|
||||||
if (mediaPlayerService != null) {
|
|
||||||
mediaPlayerService.clear(serialize);
|
|
||||||
} else {
|
|
||||||
// If no MediaPlayerService is available, just empty the playlist
|
|
||||||
downloader.clear();
|
|
||||||
if (serialize) {
|
|
||||||
downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList,
|
|
||||||
downloader.getCurrentPlayingIndex(), getPlayerPosition());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jukeboxMediaPlayer.getValue().updatePlaylist();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void clearIncomplete()
|
|
||||||
{
|
|
||||||
reset();
|
|
||||||
Iterator<DownloadFile> iterator = downloader.downloadList.iterator();
|
|
||||||
|
|
||||||
while (iterator.hasNext())
|
|
||||||
{
|
|
||||||
DownloadFile downloadFile = iterator.next();
|
|
||||||
if (!downloadFile.isCompleteFileAvailable())
|
|
||||||
{
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition());
|
|
||||||
jukeboxMediaPlayer.getValue().updatePlaylist();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void remove(DownloadFile downloadFile)
|
|
||||||
{
|
|
||||||
if (downloadFile == localMediaPlayer.currentPlaying)
|
|
||||||
{
|
|
||||||
reset();
|
|
||||||
setCurrentPlaying(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
downloader.removeDownloadFile(downloadFile);
|
|
||||||
|
|
||||||
downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition());
|
|
||||||
jukeboxMediaPlayer.getValue().updatePlaylist();
|
|
||||||
|
|
||||||
if (downloadFile == localMediaPlayer.nextPlaying)
|
|
||||||
{
|
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
|
||||||
if (mediaPlayerService != null) mediaPlayerService.setNextPlaying();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void delete(List<MusicDirectory.Entry> songs)
|
|
||||||
{
|
|
||||||
for (MusicDirectory.Entry song : songs)
|
|
||||||
{
|
|
||||||
downloader.getDownloadFileForSong(song).delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void unpin(List<MusicDirectory.Entry> songs)
|
|
||||||
{
|
|
||||||
for (MusicDirectory.Entry song : songs)
|
|
||||||
{
|
|
||||||
downloader.getDownloadFileForSong(song).unpin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void previous()
|
|
||||||
{
|
|
||||||
int index = downloader.getCurrentPlayingIndex();
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restart song if played more than five seconds.
|
|
||||||
if (getPlayerPosition() > 5000 || index == 0)
|
|
||||||
{
|
|
||||||
play(index);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
play(index - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void next()
|
|
||||||
{
|
|
||||||
int index = downloader.getCurrentPlayingIndex();
|
|
||||||
if (index != -1)
|
|
||||||
{
|
|
||||||
switch (getRepeatMode())
|
|
||||||
{
|
|
||||||
case SINGLE:
|
|
||||||
case OFF:
|
|
||||||
if (index + 1 >= 0 && index + 1 < downloader.downloadList.size()) {
|
|
||||||
play(index + 1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ALL:
|
|
||||||
play((index + 1) % downloader.downloadList.size());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void reset()
|
|
||||||
{
|
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
|
||||||
if (mediaPlayerService != null) localMediaPlayer.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized int getPlayerPosition()
|
|
||||||
{
|
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
|
||||||
if (mediaPlayerService == null) return 0;
|
|
||||||
return mediaPlayerService.getPlayerPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized int getPlayerDuration()
|
|
||||||
{
|
|
||||||
if (localMediaPlayer.currentPlaying != null)
|
|
||||||
{
|
|
||||||
Integer duration = localMediaPlayer.currentPlaying.getSong().getDuration();
|
|
||||||
if (duration != null)
|
|
||||||
{
|
|
||||||
return duration * 1000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
|
||||||
if (mediaPlayerService == null) return 0;
|
|
||||||
return mediaPlayerService.getPlayerDuration();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PlayerState getPlayerState() { return localMediaPlayer.playerState; }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSuggestedPlaylistName(String name)
|
|
||||||
{
|
|
||||||
this.suggestedPlaylistName = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getSuggestedPlaylistName()
|
|
||||||
{
|
|
||||||
return suggestedPlaylistName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isJukeboxEnabled()
|
|
||||||
{
|
|
||||||
return jukeboxMediaPlayer.getValue().isEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isJukeboxAvailable()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
String username = activeServerProvider.getValue().getActiveServer().getUserName();
|
|
||||||
UserInfo user = MusicServiceFactory.getMusicService().getUser(username);
|
|
||||||
return user.getJukeboxRole();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Timber.w(e, "Error getting user information");
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setJukeboxEnabled(boolean jukeboxEnabled)
|
|
||||||
{
|
|
||||||
jukeboxMediaPlayer.getValue().setEnabled(jukeboxEnabled);
|
|
||||||
setPlayerState(PlayerState.IDLE);
|
|
||||||
|
|
||||||
if (jukeboxEnabled)
|
|
||||||
{
|
|
||||||
jukeboxMediaPlayer.getValue().startJukeboxService();
|
|
||||||
|
|
||||||
reset();
|
|
||||||
|
|
||||||
// Cancel current download, if necessary.
|
|
||||||
if (downloader.currentDownloading != null)
|
|
||||||
{
|
|
||||||
downloader.currentDownloading.cancelDownload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
jukeboxMediaPlayer.getValue().stopJukeboxService();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void adjustJukeboxVolume(boolean up)
|
|
||||||
{
|
|
||||||
jukeboxMediaPlayer.getValue().adjustVolume(up);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setVolume(float volume)
|
|
||||||
{
|
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
|
||||||
if (mediaPlayerService != null) localMediaPlayer.setVolume(volume);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateNotification()
|
|
||||||
{
|
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
|
||||||
if (mediaPlayerService != null) mediaPlayerService.updateNotification(localMediaPlayer.playerState, localMediaPlayer.currentPlaying);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void toggleSongStarred() {
|
|
||||||
if (localMediaPlayer.currentPlaying == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
final Entry song = localMediaPlayer.currentPlaying.getSong();
|
|
||||||
|
|
||||||
// Trigger an update
|
|
||||||
localMediaPlayer.setCurrentPlaying(localMediaPlayer.currentPlaying);
|
|
||||||
|
|
||||||
song.setStarred(!song.getStarred());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSongRating(final int rating)
|
|
||||||
{
|
|
||||||
if (!KoinJavaComponent.get(FeatureStorage.class).isFeatureEnabled(Feature.FIVE_STAR_RATING))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (localMediaPlayer.currentPlaying == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
final Entry song = localMediaPlayer.currentPlaying.getSong();
|
|
||||||
song.setUserRating(rating);
|
|
||||||
|
|
||||||
new Thread(() -> {
|
|
||||||
try
|
|
||||||
{
|
|
||||||
MusicServiceFactory.getMusicService().setRating(song.getId(), rating);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Timber.e(e);
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
|
|
||||||
updateNotification();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DownloadFile getCurrentPlaying() {
|
|
||||||
return localMediaPlayer.currentPlaying;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getPlaylistSize() {
|
|
||||||
return downloader.downloadList.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCurrentPlayingNumberOnPlaylist() {
|
|
||||||
return downloader.getCurrentPlayingIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DownloadFile getCurrentDownloading() {
|
|
||||||
return downloader.currentDownloading;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<DownloadFile> getPlayList() {
|
|
||||||
return downloader.downloadList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getPlayListUpdateRevision() {
|
|
||||||
return downloader.getDownloadListUpdateRevision();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getPlayListDuration() {
|
|
||||||
return downloader.getDownloadListDuration();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DownloadFile getDownloadFileForSong(Entry song) {
|
|
||||||
return downloader.getDownloadFileForSong(song);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -44,14 +44,14 @@ public class MediaPlayerLifecycleSupport
|
||||||
{
|
{
|
||||||
private boolean created = false;
|
private boolean created = false;
|
||||||
private DownloadQueueSerializer downloadQueueSerializer; // From DI
|
private DownloadQueueSerializer downloadQueueSerializer; // From DI
|
||||||
private final MediaPlayerControllerImpl mediaPlayerController; // From DI
|
private final MediaPlayerController mediaPlayerController; // From DI
|
||||||
private final Downloader downloader; // From DI
|
private final Downloader downloader; // From DI
|
||||||
private Context context;
|
private Context context;
|
||||||
|
|
||||||
private BroadcastReceiver headsetEventReceiver;
|
private BroadcastReceiver headsetEventReceiver;
|
||||||
|
|
||||||
public MediaPlayerLifecycleSupport(Context context, DownloadQueueSerializer downloadQueueSerializer,
|
public MediaPlayerLifecycleSupport(Context context, DownloadQueueSerializer downloadQueueSerializer,
|
||||||
final MediaPlayerControllerImpl mediaPlayerController, final Downloader downloader)
|
final MediaPlayerController mediaPlayerController, final Downloader downloader)
|
||||||
{
|
{
|
||||||
this.downloadQueueSerializer = downloadQueueSerializer;
|
this.downloadQueueSerializer = downloadQueueSerializer;
|
||||||
this.mediaPlayerController = mediaPlayerController;
|
this.mediaPlayerController = mediaPlayerController;
|
||||||
|
|
|
@ -9,7 +9,6 @@ import org.moire.ultrasonic.service.ExternalStorageMonitor
|
||||||
import org.moire.ultrasonic.service.JukeboxMediaPlayer
|
import org.moire.ultrasonic.service.JukeboxMediaPlayer
|
||||||
import org.moire.ultrasonic.service.LocalMediaPlayer
|
import org.moire.ultrasonic.service.LocalMediaPlayer
|
||||||
import org.moire.ultrasonic.service.MediaPlayerController
|
import org.moire.ultrasonic.service.MediaPlayerController
|
||||||
import org.moire.ultrasonic.service.MediaPlayerControllerImpl
|
|
||||||
import org.moire.ultrasonic.service.MediaPlayerLifecycleSupport
|
import org.moire.ultrasonic.service.MediaPlayerLifecycleSupport
|
||||||
import org.moire.ultrasonic.util.ShufflePlayBuffer
|
import org.moire.ultrasonic.util.ShufflePlayBuffer
|
||||||
|
|
||||||
|
@ -17,9 +16,7 @@ import org.moire.ultrasonic.util.ShufflePlayBuffer
|
||||||
* This Koin module contains the registration of classes related to the media player
|
* This Koin module contains the registration of classes related to the media player
|
||||||
*/
|
*/
|
||||||
val mediaPlayerModule = module {
|
val mediaPlayerModule = module {
|
||||||
single<MediaPlayerController> {
|
single { MediaPlayerController(androidContext(), get(), get(), get(), get(), get()) }
|
||||||
MediaPlayerControllerImpl(androidContext(), get(), get(), get(), get(), get())
|
|
||||||
}
|
|
||||||
|
|
||||||
single { JukeboxMediaPlayer(androidContext(), get()) }
|
single { JukeboxMediaPlayer(androidContext(), get()) }
|
||||||
single { MediaPlayerLifecycleSupport(androidContext(), get(), get(), get()) }
|
single { MediaPlayerLifecycleSupport(androidContext(), get(), get(), get()) }
|
||||||
|
@ -31,5 +28,5 @@ val mediaPlayerModule = module {
|
||||||
single { AudioFocusHandler(get()) }
|
single { AudioFocusHandler(get()) }
|
||||||
|
|
||||||
// TODO Ideally this can be cleaned up when all circular references are removed.
|
// TODO Ideally this can be cleaned up when all circular references are removed.
|
||||||
single { MediaPlayerControllerImpl(androidContext(), get(), get(), get(), get(), get()) }
|
single { MediaPlayerController(androidContext(), get(), get(), get(), get(), get()) }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue