Refactored playback related things
This commit is contained in:
parent
53628dde54
commit
0820763c7f
|
@ -310,7 +310,7 @@ public class BookmarkActivity extends SubsonicTabActivity
|
||||||
|
|
||||||
for (MusicDirectory.Entry song : selection)
|
for (MusicDirectory.Entry song : selection)
|
||||||
{
|
{
|
||||||
DownloadFile downloadFile = getDownloadService().forSong(song);
|
DownloadFile downloadFile = downloader.getValue().getDownloadFileForSong(song);
|
||||||
if (downloadFile.isWorkDone())
|
if (downloadFile.isWorkDone())
|
||||||
{
|
{
|
||||||
deleteEnabled = true;
|
deleteEnabled = true;
|
||||||
|
|
|
@ -293,7 +293,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
|
||||||
@Override
|
@Override
|
||||||
protected Boolean doInBackground() throws Throwable
|
protected Boolean doInBackground() throws Throwable
|
||||||
{
|
{
|
||||||
if (getDownloadService().getCurrentPlayingIndex() < getDownloadService().size() - 1)
|
if (downloader.getValue().getCurrentPlayingIndex() < downloader.getValue().downloadList.size() - 1)
|
||||||
{
|
{
|
||||||
getDownloadService().next();
|
getDownloadService().next();
|
||||||
return true;
|
return true;
|
||||||
|
@ -567,7 +567,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
|
||||||
|
|
||||||
final DownloadService downloadService = getDownloadService();
|
final DownloadService downloadService = getDownloadService();
|
||||||
|
|
||||||
if (downloadService == null || downloadService.getCurrentPlaying() == null)
|
if (downloadService == null || player.getValue().currentPlaying == null)
|
||||||
{
|
{
|
||||||
playlistFlipper.setDisplayedChild(1);
|
playlistFlipper.setDisplayedChild(1);
|
||||||
}
|
}
|
||||||
|
@ -632,7 +632,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final DownloadFile currentDownloading = getDownloadService().getCurrentDownloading();
|
final DownloadFile currentDownloading = downloader.getValue().currentDownloading;
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
if (currentDownloading == playlistView.getItemAtPosition(i))
|
if (currentDownloading == playlistView.getItemAtPosition(i))
|
||||||
|
@ -782,7 +782,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
|
||||||
|
|
||||||
if (downloadService != null)
|
if (downloadService != null)
|
||||||
{
|
{
|
||||||
DownloadFile downloadFile = downloadService.getCurrentPlaying();
|
DownloadFile downloadFile = player.getValue().currentPlaying;
|
||||||
|
|
||||||
if (downloadFile != null)
|
if (downloadFile != null)
|
||||||
{
|
{
|
||||||
|
@ -1019,7 +1019,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
|
||||||
onDownloadListChanged();
|
onDownloadListChanged();
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_item_save_playlist:
|
case R.id.menu_item_save_playlist:
|
||||||
if (!getDownloadService().getSongs().isEmpty())
|
if (!downloader.getValue().downloadList.isEmpty())
|
||||||
{
|
{
|
||||||
showDialog(DIALOG_SAVE_PLAYLIST);
|
showDialog(DIALOG_SAVE_PLAYLIST);
|
||||||
}
|
}
|
||||||
|
@ -1142,7 +1142,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
|
||||||
|
|
||||||
if (downloadService != null)
|
if (downloadService != null)
|
||||||
{
|
{
|
||||||
List<DownloadFile> downloadServiceSongs = downloadService.getSongs();
|
List<DownloadFile> downloadServiceSongs = downloader.getValue().downloadList;
|
||||||
|
|
||||||
if (downloadServiceSongs != null)
|
if (downloadServiceSongs != null)
|
||||||
{
|
{
|
||||||
|
@ -1175,12 +1175,12 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentRevision != getDownloadService().getDownloadListUpdateRevision())
|
if (currentRevision != downloader.getValue().getDownloadListUpdateRevision())
|
||||||
{
|
{
|
||||||
onDownloadListChanged();
|
onDownloadListChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentPlaying != getDownloadService().getCurrentPlaying())
|
if (currentPlaying != player.getValue().currentPlaying)
|
||||||
{
|
{
|
||||||
onCurrentChanged();
|
onCurrentChanged();
|
||||||
}
|
}
|
||||||
|
@ -1199,7 +1199,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
|
||||||
protected Void doInBackground() throws Throwable
|
protected Void doInBackground() throws Throwable
|
||||||
{
|
{
|
||||||
final List<MusicDirectory.Entry> entries = new LinkedList<MusicDirectory.Entry>();
|
final List<MusicDirectory.Entry> entries = new LinkedList<MusicDirectory.Entry>();
|
||||||
for (final DownloadFile downloadFile : getDownloadService().getSongs())
|
for (final DownloadFile downloadFile : downloader.getValue().downloadList)
|
||||||
{
|
{
|
||||||
entries.add(downloadFile.getSong());
|
entries.add(downloadFile.getSong());
|
||||||
}
|
}
|
||||||
|
@ -1254,7 +1254,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
|
||||||
{
|
{
|
||||||
warnIfNetworkOrStorageUnavailable();
|
warnIfNetworkOrStorageUnavailable();
|
||||||
|
|
||||||
final int current = service.getCurrentPlayingIndex();
|
final int current = downloader.getValue().getCurrentPlayingIndex();
|
||||||
|
|
||||||
if (current == -1)
|
if (current == -1)
|
||||||
{
|
{
|
||||||
|
@ -1275,7 +1275,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<DownloadFile> list = downloadService.getSongs();
|
final List<DownloadFile> list = downloader.getValue().downloadList;
|
||||||
|
|
||||||
emptyTextView.setText(R.string.download_empty);
|
emptyTextView.setText(R.string.download_empty);
|
||||||
final SongListAdapter adapter = new SongListAdapter(this, list);
|
final SongListAdapter adapter = new SongListAdapter(this, list);
|
||||||
|
@ -1313,7 +1313,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadFile currentPlaying = downloadService.getCurrentPlaying();
|
DownloadFile currentPlaying = player.getValue().currentPlaying;
|
||||||
|
|
||||||
if (currentPlaying == item)
|
if (currentPlaying == item)
|
||||||
{
|
{
|
||||||
|
@ -1333,7 +1333,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
|
||||||
});
|
});
|
||||||
|
|
||||||
emptyTextView.setVisibility(list.isEmpty() ? View.VISIBLE : View.GONE);
|
emptyTextView.setVisibility(list.isEmpty() ? View.VISIBLE : View.GONE);
|
||||||
currentRevision = downloadService.getDownloadListUpdateRevision();
|
currentRevision = downloader.getValue().getDownloadListUpdateRevision();
|
||||||
|
|
||||||
switch (downloadService.getRepeatMode())
|
switch (downloadService.getRepeatMode())
|
||||||
{
|
{
|
||||||
|
@ -1360,13 +1360,13 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentPlaying = downloadService.getCurrentPlaying();
|
currentPlaying = player.getValue().currentPlaying;
|
||||||
|
|
||||||
scrollToCurrent();
|
scrollToCurrent();
|
||||||
|
|
||||||
long totalDuration = downloadService.getDownloadListDuration();
|
long totalDuration = downloader.getValue().getDownloadListDuration();
|
||||||
long totalSongs = downloadService.getSongs().size();
|
long totalSongs = downloader.getValue().downloadList.size();
|
||||||
int currentSongIndex = downloadService.getCurrentPlayingIndex() + 1;
|
int currentSongIndex = downloader.getValue().getCurrentPlayingIndex() + 1;
|
||||||
|
|
||||||
String duration = Util.formatTotalDuration(totalDuration);
|
String duration = Util.formatTotalDuration(totalDuration);
|
||||||
|
|
||||||
|
@ -1580,7 +1580,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi
|
||||||
if (e1X - e2X > swipeDistance && absX > swipeVelocity)
|
if (e1X - e2X > swipeDistance && absX > swipeVelocity)
|
||||||
{
|
{
|
||||||
warnIfNetworkOrStorageUnavailable();
|
warnIfNetworkOrStorageUnavailable();
|
||||||
if (downloadService.getCurrentPlayingIndex() < downloadService.size() - 1)
|
if (downloader.getValue().getCurrentPlayingIndex() < downloader.getValue().downloadList.size() - 1)
|
||||||
{
|
{
|
||||||
downloadService.next();
|
downloadService.next();
|
||||||
onCurrentChanged();
|
onCurrentChanged();
|
||||||
|
|
|
@ -520,7 +520,7 @@ public class SearchActivity extends SubsonicTabActivity
|
||||||
|
|
||||||
if (autoplay)
|
if (autoplay)
|
||||||
{
|
{
|
||||||
downloadService.play(downloadService.size() - 1);
|
downloadService.play(downloader.getValue().downloadList.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_added, 1, 1));
|
Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_added, 1, 1));
|
||||||
|
|
|
@ -1024,7 +1024,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity
|
||||||
|
|
||||||
for (MusicDirectory.Entry song : selection)
|
for (MusicDirectory.Entry song : selection)
|
||||||
{
|
{
|
||||||
DownloadFile downloadFile = getDownloadService().forSong(song);
|
DownloadFile downloadFile = downloader.getValue().getDownloadFileForSong(song);
|
||||||
if (downloadFile.isWorkDone())
|
if (downloadFile.isWorkDone())
|
||||||
{
|
{
|
||||||
deleteEnabled = true;
|
deleteEnabled = true;
|
||||||
|
|
|
@ -78,6 +78,9 @@ public class SubsonicTabActivity extends ResultActivity implements OnClickListen
|
||||||
|
|
||||||
private Lazy<DownloadServiceImpl> downloadServiceImpl = inject(DownloadServiceImpl.class);
|
private Lazy<DownloadServiceImpl> downloadServiceImpl = inject(DownloadServiceImpl.class);
|
||||||
private Lazy<DownloadServiceLifecycleSupport> lifecycleSupport = inject(DownloadServiceLifecycleSupport.class);
|
private Lazy<DownloadServiceLifecycleSupport> lifecycleSupport = inject(DownloadServiceLifecycleSupport.class);
|
||||||
|
protected Lazy<Downloader> downloader = inject(Downloader.class);
|
||||||
|
protected Lazy<Player> player = inject(Player.class);
|
||||||
|
|
||||||
|
|
||||||
public MenuDrawer menuDrawer;
|
public MenuDrawer menuDrawer;
|
||||||
private int activePosition = 1;
|
private int activePosition = 1;
|
||||||
|
@ -266,7 +269,7 @@ public class SubsonicTabActivity extends ResultActivity implements OnClickListen
|
||||||
|
|
||||||
if (playerState.equals(PlayerState.PAUSED) || playerState.equals(PlayerState.STARTED))
|
if (playerState.equals(PlayerState.PAUSED) || playerState.equals(PlayerState.STARTED))
|
||||||
{
|
{
|
||||||
DownloadFile file = downloadServiceImpl.getValue().getCurrentPlaying();
|
DownloadFile file = player.getValue().currentPlaying;
|
||||||
|
|
||||||
if (file != null)
|
if (file != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,8 +5,9 @@ import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
|
||||||
import org.moire.ultrasonic.domain.MusicDirectory.Entry;
|
import org.moire.ultrasonic.domain.MusicDirectory.Entry;
|
||||||
import org.moire.ultrasonic.service.DownloadService;
|
|
||||||
import org.moire.ultrasonic.service.DownloadServiceImpl;
|
import org.moire.ultrasonic.service.DownloadServiceImpl;
|
||||||
|
import org.moire.ultrasonic.service.Downloader;
|
||||||
|
import org.moire.ultrasonic.service.Player;
|
||||||
|
|
||||||
import kotlin.Lazy;
|
import kotlin.Lazy;
|
||||||
|
|
||||||
|
@ -16,16 +17,18 @@ public class A2dpIntentReceiver extends BroadcastReceiver
|
||||||
{
|
{
|
||||||
private static final String PLAYSTATUS_RESPONSE = "com.android.music.playstatusresponse";
|
private static final String PLAYSTATUS_RESPONSE = "com.android.music.playstatusresponse";
|
||||||
private Lazy<DownloadServiceImpl> downloadServiceImpl = inject(DownloadServiceImpl.class);
|
private Lazy<DownloadServiceImpl> downloadServiceImpl = inject(DownloadServiceImpl.class);
|
||||||
|
private Lazy<Downloader> downloader = inject(Downloader.class);
|
||||||
|
protected Lazy<Player> player = inject(Player.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent)
|
public void onReceive(Context context, Intent intent)
|
||||||
{
|
{
|
||||||
if (downloadServiceImpl.getValue().getCurrentPlaying() == null)
|
if (player.getValue().currentPlaying == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry song = downloadServiceImpl.getValue().getCurrentPlaying().getSong();
|
Entry song = player.getValue().currentPlaying.getSong();
|
||||||
|
|
||||||
if (song == null)
|
if (song == null)
|
||||||
{
|
{
|
||||||
|
@ -35,8 +38,8 @@ public class A2dpIntentReceiver extends BroadcastReceiver
|
||||||
Intent avrcpIntent = new Intent(PLAYSTATUS_RESPONSE);
|
Intent avrcpIntent = new Intent(PLAYSTATUS_RESPONSE);
|
||||||
|
|
||||||
Integer duration = song.getDuration();
|
Integer duration = song.getDuration();
|
||||||
Integer playerPosition = downloadServiceImpl.getValue().getPlayerPosition();
|
int playerPosition = downloadServiceImpl.getValue().getPlayerPosition();
|
||||||
Integer listSize = downloadServiceImpl.getValue().getDownloads().size();
|
int listSize = downloader.getValue().getDownloads().size();
|
||||||
|
|
||||||
if (duration != null)
|
if (duration != null)
|
||||||
{
|
{
|
||||||
|
@ -52,11 +55,7 @@ public class A2dpIntentReceiver extends BroadcastReceiver
|
||||||
avrcpIntent.putExtra("playing", true);
|
avrcpIntent.putExtra("playing", true);
|
||||||
break;
|
break;
|
||||||
case STOPPED:
|
case STOPPED:
|
||||||
avrcpIntent.putExtra("playing", false);
|
|
||||||
break;
|
|
||||||
case PAUSED:
|
case PAUSED:
|
||||||
avrcpIntent.putExtra("playing", false);
|
|
||||||
break;
|
|
||||||
case COMPLETED:
|
case COMPLETED:
|
||||||
avrcpIntent.putExtra("playing", false);
|
avrcpIntent.putExtra("playing", false);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package org.moire.ultrasonic.service;
|
||||||
|
|
||||||
|
public abstract class BiConsumer<T, U>
|
||||||
|
{
|
||||||
|
public abstract void accept(T t, U u);
|
||||||
|
}
|
|
@ -68,6 +68,9 @@ public class DownloadFile
|
||||||
private volatile boolean saveWhenDone;
|
private volatile boolean saveWhenDone;
|
||||||
private volatile boolean completeWhenDone;
|
private volatile boolean completeWhenDone;
|
||||||
|
|
||||||
|
private Lazy<Downloader> downloader = inject(Downloader.class);
|
||||||
|
|
||||||
|
|
||||||
public DownloadFile(Context context, MusicDirectory.Entry song, boolean save)
|
public DownloadFile(Context context, MusicDirectory.Entry song, boolean save)
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
|
@ -443,7 +446,7 @@ public class DownloadFile
|
||||||
|
|
||||||
new CacheCleaner(context).cleanSpace();
|
new CacheCleaner(context).cleanSpace();
|
||||||
|
|
||||||
MediaPlayerService.checkDownloads(context);
|
downloader.getValue().checkDownloads();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,30 +61,10 @@ public interface DownloadService
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
void clearBackground();
|
|
||||||
|
|
||||||
void clearIncomplete();
|
void clearIncomplete();
|
||||||
|
|
||||||
int size();
|
|
||||||
|
|
||||||
void remove(int which);
|
|
||||||
|
|
||||||
void remove(DownloadFile downloadFile);
|
void remove(DownloadFile downloadFile);
|
||||||
|
|
||||||
long getDownloadListDuration();
|
|
||||||
|
|
||||||
List<DownloadFile> getSongs();
|
|
||||||
|
|
||||||
List<DownloadFile> getDownloads();
|
|
||||||
|
|
||||||
List<DownloadFile> getBackgroundDownloads();
|
|
||||||
|
|
||||||
int getCurrentPlayingIndex();
|
|
||||||
|
|
||||||
DownloadFile getCurrentPlaying();
|
|
||||||
|
|
||||||
DownloadFile getCurrentDownloading();
|
|
||||||
|
|
||||||
void play(int index);
|
void play(int index);
|
||||||
|
|
||||||
void seekTo(int position);
|
void seekTo(int position);
|
||||||
|
@ -111,10 +91,6 @@ public interface DownloadService
|
||||||
|
|
||||||
void unpin(List<Entry> songs);
|
void unpin(List<Entry> songs);
|
||||||
|
|
||||||
DownloadFile forSong(Entry song);
|
|
||||||
|
|
||||||
long getDownloadListUpdateRevision();
|
|
||||||
|
|
||||||
void setSuggestedPlaylistName(String name);
|
void setSuggestedPlaylistName(String name);
|
||||||
|
|
||||||
String getSuggestedPlaylistName();
|
String getSuggestedPlaylistName();
|
||||||
|
|
|
@ -32,19 +32,15 @@ import org.moire.ultrasonic.domain.RepeatMode;
|
||||||
import org.moire.ultrasonic.domain.UserInfo;
|
import org.moire.ultrasonic.domain.UserInfo;
|
||||||
import org.moire.ultrasonic.featureflags.Feature;
|
import org.moire.ultrasonic.featureflags.Feature;
|
||||||
import org.moire.ultrasonic.featureflags.FeatureStorage;
|
import org.moire.ultrasonic.featureflags.FeatureStorage;
|
||||||
import org.moire.ultrasonic.util.LRUCache;
|
|
||||||
import org.moire.ultrasonic.util.ShufflePlayBuffer;
|
import org.moire.ultrasonic.util.ShufflePlayBuffer;
|
||||||
import org.moire.ultrasonic.util.Util;
|
import org.moire.ultrasonic.util.Util;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import kotlin.Lazy;
|
import kotlin.Lazy;
|
||||||
|
|
||||||
import static org.koin.java.standalone.KoinJavaComponent.inject;
|
import static org.koin.java.standalone.KoinJavaComponent.inject;
|
||||||
import static org.moire.ultrasonic.service.MediaPlayerService.playerState;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sindre Mehus, Joshua Bahnsen
|
* @author Sindre Mehus, Joshua Bahnsen
|
||||||
|
@ -54,8 +50,6 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
{
|
{
|
||||||
private static final String TAG = DownloadServiceImpl.class.getSimpleName();
|
private static final String TAG = DownloadServiceImpl.class.getSimpleName();
|
||||||
|
|
||||||
private final LRUCache<MusicDirectory.Entry, DownloadFile> downloadFileCache = new LRUCache<>(100);
|
|
||||||
|
|
||||||
private String suggestedPlaylistName;
|
private String suggestedPlaylistName;
|
||||||
private boolean keepScreenOn;
|
private boolean keepScreenOn;
|
||||||
|
|
||||||
|
@ -66,13 +60,18 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
public Lazy<JukeboxService> jukeboxService = inject(JukeboxService.class);
|
public Lazy<JukeboxService> jukeboxService = inject(JukeboxService.class);
|
||||||
private Lazy<DownloadQueueSerializer> downloadQueueSerializer = inject(DownloadQueueSerializer.class);
|
private Lazy<DownloadQueueSerializer> downloadQueueSerializer = inject(DownloadQueueSerializer.class);
|
||||||
private Lazy<ExternalStorageMonitor> externalStorageMonitor = inject(ExternalStorageMonitor.class);
|
private Lazy<ExternalStorageMonitor> externalStorageMonitor = inject(ExternalStorageMonitor.class);
|
||||||
|
private final Downloader downloader;
|
||||||
|
private final ShufflePlayBuffer shufflePlayBuffer;
|
||||||
|
private final Player player;
|
||||||
|
|
||||||
public DownloadServiceImpl(Context context)
|
public DownloadServiceImpl(Context context, Downloader downloader, ShufflePlayBuffer shufflePlayBuffer,
|
||||||
|
Player player)
|
||||||
{
|
{
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
this.downloader = downloader;
|
||||||
|
this.shufflePlayBuffer = shufflePlayBuffer;
|
||||||
|
this.player = player;
|
||||||
|
|
||||||
// TODO: refactor
|
|
||||||
MediaPlayerService.shufflePlayBuffer = new ShufflePlayBuffer(context);
|
|
||||||
externalStorageMonitor.getValue().onCreate(new Runnable() {
|
externalStorageMonitor.getValue().onCreate(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -120,26 +119,25 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (MediaPlayerService.currentPlaying != null)
|
if (player.currentPlaying != null)
|
||||||
{
|
{
|
||||||
if (autoPlay && jukeboxService.getValue().isEnabled())
|
if (autoPlay && jukeboxService.getValue().isEnabled())
|
||||||
{
|
{
|
||||||
jukeboxService.getValue().skip(getCurrentPlayingIndex(), currentPlayingPosition / 1000);
|
jukeboxService.getValue().skip(downloader.getCurrentPlayingIndex(), currentPlayingPosition / 1000);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (MediaPlayerService.currentPlaying.isCompleteFileAvailable())
|
if (player.currentPlaying.isCompleteFileAvailable())
|
||||||
{
|
{
|
||||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(MediaPlayerService mediaPlayerService) {
|
public void accept(MediaPlayerService mediaPlayerService) {
|
||||||
mediaPlayerService.doPlay(MediaPlayerService.currentPlaying, currentPlayingPosition, autoPlay);
|
player.doPlay(player.currentPlaying, currentPlayingPosition, autoPlay);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
autoPlayStart = false;
|
autoPlayStart = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,7 +166,7 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
@Override
|
@Override
|
||||||
public synchronized void togglePlayPause()
|
public synchronized void togglePlayPause()
|
||||||
{
|
{
|
||||||
if (playerState == PlayerState.IDLE) autoPlayStart = true;
|
if (player.playerState == PlayerState.IDLE) autoPlayStart = true;
|
||||||
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
executeOnStartedMediaPlayerService(new Consumer<MediaPlayerService>() {
|
||||||
@Override
|
@Override
|
||||||
public void accept(MediaPlayerService mediaPlayerService) {
|
public void accept(MediaPlayerService mediaPlayerService) {
|
||||||
|
@ -222,96 +220,42 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void download(List<MusicDirectory.Entry> songs, boolean save, boolean autoplay, boolean playNext, boolean shuffle, boolean newPlaylist)
|
public synchronized void download(List<MusicDirectory.Entry> songs, boolean save, boolean autoPlay, boolean playNext, boolean shuffle, boolean newPlaylist)
|
||||||
{
|
{
|
||||||
MediaPlayerService.shufflePlay = false;
|
downloader.download(songs, save, autoPlay, playNext, newPlaylist);
|
||||||
int offset = 1;
|
jukeboxService.getValue().updatePlaylist();
|
||||||
|
|
||||||
if (songs.isEmpty())
|
if (shuffle) shuffle();
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newPlaylist)
|
if (!playNext && !autoPlay && (downloader.downloadList.size() - 1) == downloader.getCurrentPlayingIndex())
|
||||||
{
|
|
||||||
MediaPlayerService.downloadList.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (playNext)
|
|
||||||
{
|
|
||||||
if (autoplay && getCurrentPlayingIndex() >= 0)
|
|
||||||
{
|
|
||||||
offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (MusicDirectory.Entry song : songs)
|
|
||||||
{
|
|
||||||
DownloadFile downloadFile = new DownloadFile(context, song, save);
|
|
||||||
MediaPlayerService.downloadList.add(getCurrentPlayingIndex() + offset, downloadFile);
|
|
||||||
offset++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int size = size();
|
|
||||||
int index = getCurrentPlayingIndex();
|
|
||||||
|
|
||||||
for (MusicDirectory.Entry song : songs)
|
|
||||||
{
|
|
||||||
DownloadFile downloadFile = new DownloadFile(context, song, save);
|
|
||||||
MediaPlayerService.downloadList.add(downloadFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!autoplay && (size - 1) == index)
|
|
||||||
{
|
{
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
if (mediaPlayerService != null) mediaPlayerService.setNextPlaying();
|
if (mediaPlayerService != null) mediaPlayerService.setNextPlaying();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
if (autoPlay)
|
||||||
MediaPlayerService.revision++;
|
|
||||||
|
|
||||||
jukeboxService.getValue().updatePlaylist();
|
|
||||||
|
|
||||||
if (shuffle) shuffle();
|
|
||||||
|
|
||||||
if (autoplay)
|
|
||||||
{
|
{
|
||||||
play(0);
|
play(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (MediaPlayerService.currentPlaying == null)
|
downloader.setFirstPlaying();
|
||||||
{
|
|
||||||
MediaPlayerService.currentPlaying = MediaPlayerService.downloadList.get(0);
|
|
||||||
MediaPlayerService.currentPlaying.setPlaying(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaPlayerService.checkDownloads(context);
|
downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition());
|
||||||
}
|
|
||||||
|
|
||||||
downloadQueueSerializer.getValue().serializeDownloadQueue(getSongs(), getCurrentPlayingIndex(), getPlayerPosition());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void downloadBackground(List<MusicDirectory.Entry> songs, boolean save)
|
public synchronized void downloadBackground(List<MusicDirectory.Entry> songs, boolean save)
|
||||||
{
|
{
|
||||||
for (MusicDirectory.Entry song : songs)
|
downloader.downloadBackground(songs, save);
|
||||||
{
|
downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition());
|
||||||
DownloadFile downloadFile = new DownloadFile(context, song, save);
|
|
||||||
MediaPlayerService.backgroundDownloadList.add(downloadFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
MediaPlayerService.revision++;
|
|
||||||
|
|
||||||
MediaPlayerService.checkDownloads(context);
|
|
||||||
downloadQueueSerializer.getValue().serializeDownloadQueue(getSongs(), getCurrentPlayingIndex(), getPlayerPosition());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setCurrentPlaying(DownloadFile currentPlaying)
|
public synchronized void setCurrentPlaying(DownloadFile currentPlaying)
|
||||||
{
|
{
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
if (mediaPlayerService != null) mediaPlayerService.setCurrentPlaying(currentPlaying);
|
if (mediaPlayerService != null) player.setCurrentPlaying(currentPlaying);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setCurrentPlaying(int index)
|
public synchronized void setCurrentPlaying(int index)
|
||||||
|
@ -323,7 +267,7 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
public synchronized void setPlayerState(PlayerState state)
|
public synchronized void setPlayerState(PlayerState state)
|
||||||
{
|
{
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
if (mediaPlayerService != null) mediaPlayerService.setPlayerState(state);
|
if (mediaPlayerService != null) player.setPlayerState(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -341,31 +285,26 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
@Override
|
@Override
|
||||||
public synchronized void setShufflePlayEnabled(boolean enabled)
|
public synchronized void setShufflePlayEnabled(boolean enabled)
|
||||||
{
|
{
|
||||||
MediaPlayerService.shufflePlay = enabled;
|
shufflePlayBuffer.isEnabled = enabled;
|
||||||
if (MediaPlayerService.shufflePlay)
|
if (enabled)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
MediaPlayerService.checkDownloads(context);
|
downloader.checkDownloads();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isShufflePlayEnabled()
|
public boolean isShufflePlayEnabled()
|
||||||
{
|
{
|
||||||
return MediaPlayerService.shufflePlay;
|
return shufflePlayBuffer.isEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void shuffle()
|
public synchronized void shuffle()
|
||||||
{
|
{
|
||||||
Collections.shuffle(MediaPlayerService.downloadList);
|
downloader.shuffle();
|
||||||
if (MediaPlayerService.currentPlaying != null)
|
|
||||||
{
|
downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition());
|
||||||
MediaPlayerService.downloadList.remove(getCurrentPlayingIndex());
|
|
||||||
MediaPlayerService.downloadList.add(0, MediaPlayerService.currentPlaying);
|
|
||||||
}
|
|
||||||
MediaPlayerService.revision++;
|
|
||||||
downloadQueueSerializer.getValue().serializeDownloadQueue(getSongs(), getCurrentPlayingIndex(), getPlayerPosition());
|
|
||||||
jukeboxService.getValue().updatePlaylist();
|
jukeboxService.getValue().updatePlaylist();
|
||||||
|
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
|
@ -410,33 +349,6 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
this.showVisualization = showVisualization;
|
this.showVisualization = showVisualization;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized DownloadFile forSong(MusicDirectory.Entry song)
|
|
||||||
{
|
|
||||||
for (DownloadFile downloadFile : MediaPlayerService.downloadList)
|
|
||||||
{
|
|
||||||
if (downloadFile.getSong().equals(song) && ((downloadFile.isDownloading() && !downloadFile.isDownloadCancelled() && downloadFile.getPartialFile().exists()) || downloadFile.isWorkDone()))
|
|
||||||
{
|
|
||||||
return downloadFile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (DownloadFile downloadFile : MediaPlayerService.backgroundDownloadList)
|
|
||||||
{
|
|
||||||
if (downloadFile.getSong().equals(song))
|
|
||||||
{
|
|
||||||
return downloadFile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DownloadFile downloadFile = downloadFileCache.get(song);
|
|
||||||
if (downloadFile == null)
|
|
||||||
{
|
|
||||||
downloadFile = new DownloadFile(context, song, false);
|
|
||||||
downloadFileCache.put(song, downloadFile);
|
|
||||||
}
|
|
||||||
return downloadFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void clear()
|
public synchronized void clear()
|
||||||
{
|
{
|
||||||
|
@ -445,30 +357,17 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
|
|
||||||
public synchronized void clear(boolean serialize)
|
public synchronized void clear(boolean serialize)
|
||||||
{
|
{
|
||||||
MediaPlayerService.clear(serialize);
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
jukeboxService.getValue().updatePlaylist();
|
if (mediaPlayerService != null) mediaPlayerService.clear(serialize);
|
||||||
if (serialize)
|
|
||||||
{
|
|
||||||
downloadQueueSerializer.getValue().serializeDownloadQueue(getSongs(), getCurrentPlayingIndex(), getPlayerPosition());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
jukeboxService.getValue().updatePlaylist();
|
||||||
public synchronized void clearBackground()
|
|
||||||
{
|
|
||||||
if (MediaPlayerService.currentDownloading != null && MediaPlayerService.backgroundDownloadList.contains(MediaPlayerService.currentDownloading))
|
|
||||||
{
|
|
||||||
MediaPlayerService.currentDownloading.cancelDownload();
|
|
||||||
MediaPlayerService.currentDownloading = null;
|
|
||||||
}
|
|
||||||
MediaPlayerService.backgroundDownloadList.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void clearIncomplete()
|
public synchronized void clearIncomplete()
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
Iterator<DownloadFile> iterator = MediaPlayerService.downloadList.iterator();
|
Iterator<DownloadFile> iterator = downloader.downloadList.iterator();
|
||||||
|
|
||||||
while (iterator.hasNext())
|
while (iterator.hasNext())
|
||||||
{
|
{
|
||||||
|
@ -479,41 +378,25 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadQueueSerializer.getValue().serializeDownloadQueue(getSongs(), getCurrentPlayingIndex(), getPlayerPosition());
|
downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition());
|
||||||
jukeboxService.getValue().updatePlaylist();
|
jukeboxService.getValue().updatePlaylist();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized int size()
|
|
||||||
{
|
|
||||||
return MediaPlayerService.downloadList.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void remove(int which)
|
|
||||||
{
|
|
||||||
MediaPlayerService.downloadList.remove(which);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void remove(DownloadFile downloadFile)
|
public synchronized void remove(DownloadFile downloadFile)
|
||||||
{
|
{
|
||||||
if (downloadFile == MediaPlayerService.currentDownloading)
|
if (downloadFile == player.currentPlaying)
|
||||||
{
|
|
||||||
MediaPlayerService.currentDownloading.cancelDownload();
|
|
||||||
MediaPlayerService.currentDownloading = null;
|
|
||||||
}
|
|
||||||
if (downloadFile == MediaPlayerService.currentPlaying)
|
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
setCurrentPlaying(null);
|
setCurrentPlaying(null);
|
||||||
}
|
}
|
||||||
MediaPlayerService.downloadList.remove(downloadFile);
|
|
||||||
MediaPlayerService.backgroundDownloadList.remove(downloadFile);
|
downloader.removeDownloadFile(downloadFile);
|
||||||
MediaPlayerService.revision++;
|
|
||||||
downloadQueueSerializer.getValue().serializeDownloadQueue(getSongs(), getCurrentPlayingIndex(), getPlayerPosition());
|
downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition());
|
||||||
jukeboxService.getValue().updatePlaylist();
|
jukeboxService.getValue().updatePlaylist();
|
||||||
if (downloadFile == MediaPlayerService.nextPlaying)
|
|
||||||
|
if (downloadFile == player.nextPlaying)
|
||||||
{
|
{
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
if (mediaPlayerService != null) mediaPlayerService.setNextPlaying();
|
if (mediaPlayerService != null) mediaPlayerService.setNextPlaying();
|
||||||
|
@ -525,7 +408,7 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
{
|
{
|
||||||
for (MusicDirectory.Entry song : songs)
|
for (MusicDirectory.Entry song : songs)
|
||||||
{
|
{
|
||||||
forSong(song).delete();
|
downloader.getDownloadFileForSong(song).delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,76 +417,14 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
{
|
{
|
||||||
for (MusicDirectory.Entry song : songs)
|
for (MusicDirectory.Entry song : songs)
|
||||||
{
|
{
|
||||||
forSong(song).unpin();
|
downloader.getDownloadFileForSong(song).unpin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized int getCurrentPlayingIndex()
|
|
||||||
{
|
|
||||||
return MediaPlayerService.downloadList.indexOf(MediaPlayerService.currentPlaying);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DownloadFile getCurrentPlaying()
|
|
||||||
{
|
|
||||||
return MediaPlayerService.currentPlaying;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DownloadFile getCurrentDownloading()
|
|
||||||
{
|
|
||||||
return MediaPlayerService.currentDownloading;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<DownloadFile> getSongs() { return MediaPlayerService.downloadList; }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getDownloadListDuration()
|
|
||||||
{
|
|
||||||
long totalDuration = 0;
|
|
||||||
|
|
||||||
for (DownloadFile downloadFile : MediaPlayerService.downloadList)
|
|
||||||
{
|
|
||||||
Entry entry = downloadFile.getSong();
|
|
||||||
|
|
||||||
if (!entry.isDirectory())
|
|
||||||
{
|
|
||||||
if (entry.getArtist() != null)
|
|
||||||
{
|
|
||||||
Integer duration = entry.getDuration();
|
|
||||||
|
|
||||||
if (duration != null)
|
|
||||||
{
|
|
||||||
totalDuration += duration;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return totalDuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized List<DownloadFile> getDownloads()
|
|
||||||
{
|
|
||||||
List<DownloadFile> temp = new ArrayList<>();
|
|
||||||
temp.addAll(MediaPlayerService.downloadList);
|
|
||||||
temp.addAll(MediaPlayerService.backgroundDownloadList);
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<DownloadFile> getBackgroundDownloads()
|
|
||||||
{
|
|
||||||
return MediaPlayerService.backgroundDownloadList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void previous()
|
public synchronized void previous()
|
||||||
{
|
{
|
||||||
int index = getCurrentPlayingIndex();
|
int index = downloader.getCurrentPlayingIndex();
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -623,7 +444,7 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
@Override
|
@Override
|
||||||
public synchronized void next()
|
public synchronized void next()
|
||||||
{
|
{
|
||||||
int index = getCurrentPlayingIndex();
|
int index = downloader.getCurrentPlayingIndex();
|
||||||
if (index != -1)
|
if (index != -1)
|
||||||
{
|
{
|
||||||
play(index + 1);
|
play(index + 1);
|
||||||
|
@ -634,7 +455,7 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
public synchronized void reset()
|
public synchronized void reset()
|
||||||
{
|
{
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
if (mediaPlayerService != null) mediaPlayerService.reset();
|
if (mediaPlayerService != null) player.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -648,24 +469,22 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
@Override
|
@Override
|
||||||
public synchronized int getPlayerDuration()
|
public synchronized int getPlayerDuration()
|
||||||
{
|
{
|
||||||
if (MediaPlayerService.currentPlaying != null)
|
if (player.currentPlaying != null)
|
||||||
{
|
{
|
||||||
Integer duration = MediaPlayerService.currentPlaying.getSong().getDuration();
|
Integer duration = player.currentPlaying.getSong().getDuration();
|
||||||
if (duration != null)
|
if (duration != null)
|
||||||
{
|
{
|
||||||
return duration * 1000;
|
return duration * 1000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
if (mediaPlayerService == null) return 0;
|
if (mediaPlayerService == null) return 0;
|
||||||
return mediaPlayerService.getPlayerDuration();
|
return mediaPlayerService.getPlayerDuration();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PlayerState getPlayerState()
|
public PlayerState getPlayerState() { return player.playerState; }
|
||||||
{
|
|
||||||
return playerState;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSuggestedPlaylistName(String name)
|
public void setSuggestedPlaylistName(String name)
|
||||||
|
@ -680,12 +499,12 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getEqualizerAvailable() { return MediaPlayerService.equalizerAvailable; }
|
public boolean getEqualizerAvailable() { return player.equalizerAvailable; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getVisualizerAvailable()
|
public boolean getVisualizerAvailable()
|
||||||
{
|
{
|
||||||
return MediaPlayerService.visualizerAvailable;
|
return player.visualizerAvailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -693,7 +512,7 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
{
|
{
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
if (mediaPlayerService == null) return null;
|
if (mediaPlayerService == null) return null;
|
||||||
return mediaPlayerService.getEqualizerController();
|
return player.getEqualizerController();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -701,7 +520,7 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
{
|
{
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
if (mediaPlayerService == null) return null;
|
if (mediaPlayerService == null) return null;
|
||||||
return mediaPlayerService.getVisualizerController();
|
return player.getVisualizerController();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -757,9 +576,9 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
// Cancel current download, if necessary.
|
// Cancel current download, if necessary.
|
||||||
if (MediaPlayerService.currentDownloading != null)
|
if (downloader.currentDownloading != null)
|
||||||
{
|
{
|
||||||
MediaPlayerService.currentDownloading.cancelDownload();
|
downloader.currentDownloading.cancelDownload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -778,13 +597,13 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
public void setVolume(float volume)
|
public void setVolume(float volume)
|
||||||
{
|
{
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
if (mediaPlayerService != null) mediaPlayerService.setVolume(volume);
|
if (mediaPlayerService != null) player.setVolume(volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void swap(boolean mainList, int from, int to)
|
public synchronized void swap(boolean mainList, int from, int to)
|
||||||
{
|
{
|
||||||
List<DownloadFile> list = mainList ? MediaPlayerService.downloadList : MediaPlayerService.backgroundDownloadList;
|
List<DownloadFile> list = mainList ? downloader.downloadList : downloader.backgroundDownloadList;
|
||||||
int max = list.size();
|
int max = list.size();
|
||||||
|
|
||||||
if (to >= max)
|
if (to >= max)
|
||||||
|
@ -796,7 +615,7 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
to = 0;
|
to = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int currentPlayingIndex = getCurrentPlayingIndex();
|
int currentPlayingIndex = downloader.getCurrentPlayingIndex();
|
||||||
DownloadFile movedSong = list.remove(from);
|
DownloadFile movedSong = list.remove(from);
|
||||||
list.add(to, movedSong);
|
list.add(to, movedSong);
|
||||||
|
|
||||||
|
@ -804,7 +623,7 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
{
|
{
|
||||||
jukeboxService.getValue().updatePlaylist();
|
jukeboxService.getValue().updatePlaylist();
|
||||||
}
|
}
|
||||||
else if (mainList && (movedSong == MediaPlayerService.nextPlaying || (currentPlayingIndex + 1) == to))
|
else if (mainList && (movedSong == player.nextPlaying || (currentPlayingIndex + 1) == to))
|
||||||
{
|
{
|
||||||
// Moving next playing or moving a song to be next playing
|
// Moving next playing or moving a song to be next playing
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
|
@ -812,17 +631,11 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getDownloadListUpdateRevision()
|
|
||||||
{
|
|
||||||
return MediaPlayerService.revision;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateNotification()
|
public void updateNotification()
|
||||||
{
|
{
|
||||||
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();
|
||||||
if (mediaPlayerService != null) mediaPlayerService.updateNotification();
|
if (mediaPlayerService != null) mediaPlayerService.updateNotification(player.playerState, player.currentPlaying);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSongRating(final int rating)
|
public void setSongRating(final int rating)
|
||||||
|
@ -830,10 +643,10 @@ public class DownloadServiceImpl implements DownloadService
|
||||||
if (!KoinJavaComponent.get(FeatureStorage.class).isFeatureEnabled(Feature.FIVE_STAR_RATING))
|
if (!KoinJavaComponent.get(FeatureStorage.class).isFeatureEnabled(Feature.FIVE_STAR_RATING))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (MediaPlayerService.currentPlaying == null)
|
if (player.currentPlaying == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
final Entry song = MediaPlayerService.currentPlaying.getSong();
|
final Entry song = player.currentPlaying.getSong();
|
||||||
song.setUserRating(rating);
|
song.setUserRating(rating);
|
||||||
|
|
||||||
new Thread(new Runnable()
|
new Thread(new Runnable()
|
||||||
|
|
|
@ -49,14 +49,16 @@ public class DownloadServiceLifecycleSupport
|
||||||
|
|
||||||
private Lazy<DownloadQueueSerializer> downloadQueueSerializer = inject(DownloadQueueSerializer.class);
|
private Lazy<DownloadQueueSerializer> downloadQueueSerializer = inject(DownloadQueueSerializer.class);
|
||||||
private final DownloadServiceImpl downloadService; // From DI
|
private final DownloadServiceImpl downloadService; // From DI
|
||||||
|
private final Downloader downloader; // From DI
|
||||||
|
|
||||||
private BroadcastReceiver headsetEventReceiver;
|
private BroadcastReceiver headsetEventReceiver;
|
||||||
private Context context;
|
private Context context;
|
||||||
|
|
||||||
public DownloadServiceLifecycleSupport(Context context, final DownloadServiceImpl downloadService)
|
public DownloadServiceLifecycleSupport(Context context, final DownloadServiceImpl downloadService, final Downloader downloader)
|
||||||
{
|
{
|
||||||
this.downloadService = downloadService;
|
this.downloadService = downloadService;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
this.downloader = downloader;
|
||||||
|
|
||||||
registerHeadsetReceiver();
|
registerHeadsetReceiver();
|
||||||
|
|
||||||
|
@ -80,8 +82,8 @@ public class DownloadServiceLifecycleSupport
|
||||||
downloadService.restore(state.songs, state.currentPlayingIndex, state.currentPlayingPosition, false, false);
|
downloadService.restore(state.songs, state.currentPlayingIndex, state.currentPlayingPosition, false, false);
|
||||||
|
|
||||||
// Work-around: Serialize again, as the restore() method creates a serialization without current playing info.
|
// Work-around: Serialize again, as the restore() method creates a serialization without current playing info.
|
||||||
downloadQueueSerializer.getValue().serializeDownloadQueue(downloadService.getSongs(),
|
downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList,
|
||||||
downloadService.getCurrentPlayingIndex(), downloadService.getPlayerPosition());
|
downloader.getCurrentPlayingIndex(), downloadService.getPlayerPosition());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -165,7 +167,7 @@ public class DownloadServiceLifecycleSupport
|
||||||
downloadService.previous();
|
downloadService.previous();
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||||||
if (downloadService.getCurrentPlayingIndex() < downloadService.size() - 1)
|
if (downloader.getCurrentPlayingIndex() < downloader.downloadList.size() - 1)
|
||||||
{
|
{
|
||||||
downloadService.next();
|
downloadService.next();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,454 @@
|
||||||
|
package org.moire.ultrasonic.service;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.moire.ultrasonic.domain.MusicDirectory;
|
||||||
|
import org.moire.ultrasonic.util.LRUCache;
|
||||||
|
import org.moire.ultrasonic.util.ShufflePlayBuffer;
|
||||||
|
import org.moire.ultrasonic.util.Util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import kotlin.Lazy;
|
||||||
|
|
||||||
|
import static org.koin.java.standalone.KoinJavaComponent.inject;
|
||||||
|
import static org.moire.ultrasonic.domain.PlayerState.DOWNLOADING;
|
||||||
|
import static org.moire.ultrasonic.domain.PlayerState.STARTED;
|
||||||
|
|
||||||
|
public class Downloader
|
||||||
|
{
|
||||||
|
private static final String TAG = Downloader.class.getSimpleName();
|
||||||
|
|
||||||
|
private final ShufflePlayBuffer shufflePlayBuffer;
|
||||||
|
private final ExternalStorageMonitor externalStorageMonitor;
|
||||||
|
private final Player player;
|
||||||
|
public Lazy<JukeboxService> jukeboxService = inject(JukeboxService.class);
|
||||||
|
|
||||||
|
public final List<DownloadFile> downloadList = new ArrayList<>();
|
||||||
|
public final List<DownloadFile> backgroundDownloadList = new ArrayList<>();
|
||||||
|
private final List<DownloadFile> cleanupCandidates = new ArrayList<>();
|
||||||
|
private final LRUCache<MusicDirectory.Entry, DownloadFile> downloadFileCache = new LRUCache<>(100);
|
||||||
|
|
||||||
|
public DownloadFile currentDownloading;
|
||||||
|
public static long revision;
|
||||||
|
|
||||||
|
private ScheduledExecutorService executorService;
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
public Downloader(Context context, ShufflePlayBuffer shufflePlayBuffer, ExternalStorageMonitor externalStorageMonitor,
|
||||||
|
Player player)
|
||||||
|
{
|
||||||
|
this.context = context;
|
||||||
|
this.shufflePlayBuffer = shufflePlayBuffer;
|
||||||
|
this.externalStorageMonitor = externalStorageMonitor;
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onCreate()
|
||||||
|
{
|
||||||
|
Runnable downloadChecker = new Runnable()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
checkDownloads();
|
||||||
|
}
|
||||||
|
catch (Throwable x)
|
||||||
|
{
|
||||||
|
Log.e(TAG, "checkDownloads() failed.", x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
executorService = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
executorService.scheduleWithFixedDelay(downloadChecker, 5, 5, TimeUnit.SECONDS);
|
||||||
|
Log.i(TAG, "Downloader created");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDestroy()
|
||||||
|
{
|
||||||
|
executorService.shutdown();
|
||||||
|
Log.i(TAG, "Downloader destroyed");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected synchronized void checkDownloads()
|
||||||
|
{
|
||||||
|
if (!Util.isExternalStoragePresent() || !externalStorageMonitor.isExternalStorageAvailable())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shufflePlayBuffer.isEnabled)
|
||||||
|
{
|
||||||
|
checkShufflePlay(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jukeboxService.getValue().isEnabled() || !Util.isNetworkConnected(context))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (downloadList.isEmpty() && backgroundDownloadList.isEmpty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to download current playing?
|
||||||
|
if (player.currentPlaying != null && player.currentPlaying != currentDownloading && !player.currentPlaying.isWorkDone())
|
||||||
|
{
|
||||||
|
// Cancel current download, if necessary.
|
||||||
|
if (currentDownloading != null)
|
||||||
|
{
|
||||||
|
currentDownloading.cancelDownload();
|
||||||
|
}
|
||||||
|
|
||||||
|
currentDownloading = player.currentPlaying;
|
||||||
|
currentDownloading.download();
|
||||||
|
cleanupCandidates.add(currentDownloading);
|
||||||
|
|
||||||
|
// Delete obsolete .partial and .complete files.
|
||||||
|
cleanup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find a suitable target for download.
|
||||||
|
if (currentDownloading != null &&
|
||||||
|
!currentDownloading.isWorkDone() &&
|
||||||
|
(!currentDownloading.isFailed() || (downloadList.isEmpty() && backgroundDownloadList.isEmpty())))
|
||||||
|
{
|
||||||
|
cleanup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is a target to download
|
||||||
|
currentDownloading = null;
|
||||||
|
int n = downloadList.size();
|
||||||
|
|
||||||
|
int preloaded = 0;
|
||||||
|
|
||||||
|
if (n != 0)
|
||||||
|
{
|
||||||
|
int start = player.currentPlaying == null ? 0 : getCurrentPlayingIndex();
|
||||||
|
if (start == -1) start = 0;
|
||||||
|
|
||||||
|
int i = start;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
DownloadFile downloadFile = downloadList.get(i);
|
||||||
|
if (!downloadFile.isWorkDone())
|
||||||
|
{
|
||||||
|
if (downloadFile.shouldSave() || preloaded < Util.getPreloadCount(context))
|
||||||
|
{
|
||||||
|
currentDownloading = downloadFile;
|
||||||
|
currentDownloading.download();
|
||||||
|
cleanupCandidates.add(currentDownloading);
|
||||||
|
if (i == (start + 1))
|
||||||
|
{
|
||||||
|
player.setNextPlayerState(DOWNLOADING);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (player.currentPlaying != downloadFile)
|
||||||
|
{
|
||||||
|
preloaded++;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = (i + 1) % n;
|
||||||
|
} while (i != start);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((preloaded + 1 == n || preloaded >= Util.getPreloadCount(context) || downloadList.isEmpty()) && !backgroundDownloadList.isEmpty())
|
||||||
|
{
|
||||||
|
for (int i = 0; i < backgroundDownloadList.size(); i++)
|
||||||
|
{
|
||||||
|
DownloadFile downloadFile = backgroundDownloadList.get(i);
|
||||||
|
if (downloadFile.isWorkDone() && (!downloadFile.shouldSave() || downloadFile.isSaved()))
|
||||||
|
{
|
||||||
|
if (Util.getShouldScanMedia(context))
|
||||||
|
{
|
||||||
|
Util.scanMedia(context, downloadFile.getCompleteFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't need to keep list like active song list
|
||||||
|
backgroundDownloadList.remove(i);
|
||||||
|
revision++;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentDownloading = downloadFile;
|
||||||
|
currentDownloading.download();
|
||||||
|
cleanupCandidates.add(currentDownloading);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete obsolete .partial and .complete files.
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized int getCurrentPlayingIndex()
|
||||||
|
{
|
||||||
|
return downloadList.indexOf(player.currentPlaying);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getDownloadListDuration()
|
||||||
|
{
|
||||||
|
long totalDuration = 0;
|
||||||
|
|
||||||
|
for (DownloadFile downloadFile : downloadList)
|
||||||
|
{
|
||||||
|
MusicDirectory.Entry entry = downloadFile.getSong();
|
||||||
|
|
||||||
|
if (!entry.isDirectory())
|
||||||
|
{
|
||||||
|
if (entry.getArtist() != null)
|
||||||
|
{
|
||||||
|
Integer duration = entry.getDuration();
|
||||||
|
|
||||||
|
if (duration != null)
|
||||||
|
{
|
||||||
|
totalDuration += duration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized List<DownloadFile> getDownloads()
|
||||||
|
{
|
||||||
|
List<DownloadFile> temp = new ArrayList<>();
|
||||||
|
temp.addAll(downloadList);
|
||||||
|
temp.addAll(backgroundDownloadList);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DownloadFile> getBackgroundDownloads()
|
||||||
|
{
|
||||||
|
return backgroundDownloadList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getDownloadListUpdateRevision()
|
||||||
|
{
|
||||||
|
return revision;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void clear()
|
||||||
|
{
|
||||||
|
downloadList.clear();
|
||||||
|
revision++;
|
||||||
|
if (currentDownloading != null)
|
||||||
|
{
|
||||||
|
currentDownloading.cancelDownload();
|
||||||
|
currentDownloading = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void clearBackground()
|
||||||
|
{
|
||||||
|
if (currentDownloading != null && backgroundDownloadList.contains(currentDownloading))
|
||||||
|
{
|
||||||
|
currentDownloading.cancelDownload();
|
||||||
|
currentDownloading = null;
|
||||||
|
}
|
||||||
|
backgroundDownloadList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void removeDownloadFile(DownloadFile downloadFile)
|
||||||
|
{
|
||||||
|
if (downloadFile == currentDownloading)
|
||||||
|
{
|
||||||
|
currentDownloading.cancelDownload();
|
||||||
|
currentDownloading = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadList.remove(downloadFile);
|
||||||
|
backgroundDownloadList.remove(downloadFile);
|
||||||
|
revision++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void download(List<MusicDirectory.Entry> songs, boolean save, boolean autoPlay, boolean playNext, boolean newPlaylist)
|
||||||
|
{
|
||||||
|
shufflePlayBuffer.isEnabled = false;
|
||||||
|
int offset = 1;
|
||||||
|
|
||||||
|
if (songs.isEmpty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newPlaylist)
|
||||||
|
{
|
||||||
|
downloadList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playNext)
|
||||||
|
{
|
||||||
|
if (autoPlay && getCurrentPlayingIndex() >= 0)
|
||||||
|
{
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MusicDirectory.Entry song : songs)
|
||||||
|
{
|
||||||
|
DownloadFile downloadFile = new DownloadFile(context, song, save);
|
||||||
|
downloadList.add(getCurrentPlayingIndex() + offset, downloadFile);
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (MusicDirectory.Entry song : songs)
|
||||||
|
{
|
||||||
|
DownloadFile downloadFile = new DownloadFile(context, song, save);
|
||||||
|
downloadList.add(downloadFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
revision++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void downloadBackground(List<MusicDirectory.Entry> songs, boolean save)
|
||||||
|
{
|
||||||
|
for (MusicDirectory.Entry song : songs)
|
||||||
|
{
|
||||||
|
DownloadFile downloadFile = new DownloadFile(context, song, save);
|
||||||
|
backgroundDownloadList.add(downloadFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
revision++;
|
||||||
|
|
||||||
|
checkDownloads();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void shuffle()
|
||||||
|
{
|
||||||
|
Collections.shuffle(downloadList);
|
||||||
|
if (player.currentPlaying != null)
|
||||||
|
{
|
||||||
|
downloadList.remove(getCurrentPlayingIndex());
|
||||||
|
downloadList.add(0, player.currentPlaying);
|
||||||
|
}
|
||||||
|
revision++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void setFirstPlaying()
|
||||||
|
{
|
||||||
|
if (player.currentPlaying == null)
|
||||||
|
{
|
||||||
|
player.currentPlaying = downloadList.get(0);
|
||||||
|
player.currentPlaying.setPlaying(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkDownloads();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized DownloadFile getDownloadFileForSong(MusicDirectory.Entry song)
|
||||||
|
{
|
||||||
|
for (DownloadFile downloadFile : downloadList)
|
||||||
|
{
|
||||||
|
if (downloadFile.getSong().equals(song) && ((downloadFile.isDownloading() && !downloadFile.isDownloadCancelled() && downloadFile.getPartialFile().exists()) || downloadFile.isWorkDone()))
|
||||||
|
{
|
||||||
|
return downloadFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (DownloadFile downloadFile : backgroundDownloadList)
|
||||||
|
{
|
||||||
|
if (downloadFile.getSong().equals(song))
|
||||||
|
{
|
||||||
|
return downloadFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DownloadFile downloadFile = downloadFileCache.get(song);
|
||||||
|
if (downloadFile == null)
|
||||||
|
{
|
||||||
|
downloadFile = new DownloadFile(context, song, false);
|
||||||
|
downloadFileCache.put(song, downloadFile);
|
||||||
|
}
|
||||||
|
return downloadFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void cleanup()
|
||||||
|
{
|
||||||
|
Iterator<DownloadFile> iterator = cleanupCandidates.iterator();
|
||||||
|
while (iterator.hasNext())
|
||||||
|
{
|
||||||
|
DownloadFile downloadFile = iterator.next();
|
||||||
|
if (downloadFile != player.currentPlaying && downloadFile != currentDownloading)
|
||||||
|
{
|
||||||
|
if (downloadFile.cleanup())
|
||||||
|
{
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void checkShufflePlay(Context context)
|
||||||
|
{
|
||||||
|
// Get users desired random playlist size
|
||||||
|
int listSize = Util.getMaxSongs(context);
|
||||||
|
boolean wasEmpty = downloadList.isEmpty();
|
||||||
|
|
||||||
|
long revisionBefore = revision;
|
||||||
|
|
||||||
|
// First, ensure that list is at least 20 songs long.
|
||||||
|
int size = downloadList.size();
|
||||||
|
if (size < listSize)
|
||||||
|
{
|
||||||
|
for (MusicDirectory.Entry song : shufflePlayBuffer.get(listSize - size))
|
||||||
|
{
|
||||||
|
DownloadFile downloadFile = new DownloadFile(context, song, false);
|
||||||
|
downloadList.add(downloadFile);
|
||||||
|
revision++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int currIndex = player.currentPlaying == null ? 0 : getCurrentPlayingIndex();
|
||||||
|
|
||||||
|
// Only shift playlist if playing song #5 or later.
|
||||||
|
if (currIndex > 4)
|
||||||
|
{
|
||||||
|
int songsToShift = currIndex - 2;
|
||||||
|
for (MusicDirectory.Entry song : shufflePlayBuffer.get(songsToShift))
|
||||||
|
{
|
||||||
|
downloadList.add(new DownloadFile(context, song, false));
|
||||||
|
downloadList.get(0).cancelDownload();
|
||||||
|
downloadList.remove(0);
|
||||||
|
revision++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (revisionBefore != revision)
|
||||||
|
{
|
||||||
|
jukeboxService.getValue().updatePlaylist();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wasEmpty && !downloadList.isEmpty())
|
||||||
|
{
|
||||||
|
if (jukeboxService.getValue().isEnabled())
|
||||||
|
{
|
||||||
|
jukeboxService.getValue().skip(0, 0);
|
||||||
|
player.setPlayerState(STARTED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
player.play(downloadList.get(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -71,7 +71,9 @@ public class JukeboxService
|
||||||
private boolean enabled = false;
|
private boolean enabled = false;
|
||||||
private Context context;
|
private Context context;
|
||||||
|
|
||||||
|
// TODO: These create circular references, try to refactor
|
||||||
private Lazy<DownloadServiceImpl> downloadServiceImpl = inject(DownloadServiceImpl.class);
|
private Lazy<DownloadServiceImpl> downloadServiceImpl = inject(DownloadServiceImpl.class);
|
||||||
|
private final Downloader downloader;
|
||||||
|
|
||||||
// TODO: Report warning if queue fills up.
|
// TODO: Report warning if queue fills up.
|
||||||
// TODO: Create shutdown method?
|
// TODO: Create shutdown method?
|
||||||
|
@ -79,9 +81,10 @@ public class JukeboxService
|
||||||
// TODO: Persist RC state?
|
// TODO: Persist RC state?
|
||||||
// TODO: Minimize status updates.
|
// TODO: Minimize status updates.
|
||||||
|
|
||||||
public JukeboxService(Context context)
|
public JukeboxService(Context context, Downloader downloader)
|
||||||
{
|
{
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
this.downloader = downloader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startJukeboxService()
|
public void startJukeboxService()
|
||||||
|
@ -182,7 +185,7 @@ public class JukeboxService
|
||||||
// Track change?
|
// Track change?
|
||||||
Integer index = jukeboxStatus.getCurrentPlayingIndex();
|
Integer index = jukeboxStatus.getCurrentPlayingIndex();
|
||||||
|
|
||||||
if (index != null && index != -1 && index != downloadServiceImpl.getValue().getCurrentPlayingIndex())
|
if (index != null && index != -1 && index != downloader.getCurrentPlayingIndex())
|
||||||
{
|
{
|
||||||
downloadServiceImpl.getValue().setCurrentPlaying(index);
|
downloadServiceImpl.getValue().setCurrentPlaying(index);
|
||||||
}
|
}
|
||||||
|
@ -232,8 +235,8 @@ public class JukeboxService
|
||||||
tasks.remove(Stop.class);
|
tasks.remove(Stop.class);
|
||||||
tasks.remove(Start.class);
|
tasks.remove(Start.class);
|
||||||
|
|
||||||
List<String> ids = new ArrayList<String>();
|
List<String> ids = new ArrayList<>();
|
||||||
for (DownloadFile file : downloadServiceImpl.getValue().getDownloads())
|
for (DownloadFile file : downloader.getDownloads())
|
||||||
{
|
{
|
||||||
ids.add(file.getSong().getId());
|
ids.add(file.getSong().getId());
|
||||||
}
|
}
|
||||||
|
@ -334,7 +337,7 @@ public class JukeboxService
|
||||||
|
|
||||||
private static class TaskQueue
|
private static class TaskQueue
|
||||||
{
|
{
|
||||||
private final LinkedBlockingQueue<JukeboxTask> queue = new LinkedBlockingQueue<JukeboxTask>();
|
private final LinkedBlockingQueue<JukeboxTask> queue = new LinkedBlockingQueue<>();
|
||||||
|
|
||||||
void add(JukeboxTask jukeboxTask)
|
void add(JukeboxTask jukeboxTask)
|
||||||
{
|
{
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -7,8 +7,7 @@ import android.util.Log;
|
||||||
|
|
||||||
import org.moire.ultrasonic.domain.Playlist;
|
import org.moire.ultrasonic.domain.Playlist;
|
||||||
import org.moire.ultrasonic.service.DownloadFile;
|
import org.moire.ultrasonic.service.DownloadFile;
|
||||||
import org.moire.ultrasonic.service.DownloadService;
|
import org.moire.ultrasonic.service.Downloader;
|
||||||
import org.moire.ultrasonic.service.DownloadServiceImpl;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -35,7 +34,7 @@ public class CacheCleaner
|
||||||
private static final long MIN_FREE_SPACE = 500 * 1024L * 1024L;
|
private static final long MIN_FREE_SPACE = 500 * 1024L * 1024L;
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private Lazy<DownloadServiceImpl> downloadServiceImpl = inject(DownloadServiceImpl.class);
|
private Lazy<Downloader> downloader = inject(Downloader.class);
|
||||||
|
|
||||||
public CacheCleaner(Context context)
|
public CacheCleaner(Context context)
|
||||||
{
|
{
|
||||||
|
@ -223,7 +222,7 @@ public class CacheCleaner
|
||||||
{
|
{
|
||||||
Set<File> filesToNotDelete = new HashSet<File>(5);
|
Set<File> filesToNotDelete = new HashSet<File>(5);
|
||||||
|
|
||||||
for (DownloadFile downloadFile : downloadServiceImpl.getValue().getDownloads())
|
for (DownloadFile downloadFile : downloader.getValue().getDownloads())
|
||||||
{
|
{
|
||||||
filesToNotDelete.add(downloadFile.getPartialFile());
|
filesToNotDelete.add(downloadFile.getPartialFile());
|
||||||
filesToNotDelete.add(downloadFile.getCompleteFile());
|
filesToNotDelete.add(downloadFile.getCompleteFile());
|
||||||
|
|
|
@ -37,19 +37,24 @@ import java.util.concurrent.TimeUnit;
|
||||||
*/
|
*/
|
||||||
public class ShufflePlayBuffer
|
public class ShufflePlayBuffer
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final String TAG = ShufflePlayBuffer.class.getSimpleName();
|
private static final String TAG = ShufflePlayBuffer.class.getSimpleName();
|
||||||
private static final int CAPACITY = 50;
|
private static final int CAPACITY = 50;
|
||||||
private static final int REFILL_THRESHOLD = 40;
|
private static final int REFILL_THRESHOLD = 40;
|
||||||
|
|
||||||
private final ScheduledExecutorService executorService;
|
|
||||||
private final List<MusicDirectory.Entry> buffer = new ArrayList<MusicDirectory.Entry>();
|
private final List<MusicDirectory.Entry> buffer = new ArrayList<MusicDirectory.Entry>();
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
private ScheduledExecutorService executorService;
|
||||||
private int currentServer;
|
private int currentServer;
|
||||||
|
|
||||||
|
public boolean isEnabled = false;
|
||||||
|
|
||||||
public ShufflePlayBuffer(Context context)
|
public ShufflePlayBuffer(Context context)
|
||||||
{
|
{
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onCreate()
|
||||||
|
{
|
||||||
executorService = Executors.newSingleThreadScheduledExecutor();
|
executorService = Executors.newSingleThreadScheduledExecutor();
|
||||||
Runnable runnable = new Runnable()
|
Runnable runnable = new Runnable()
|
||||||
{
|
{
|
||||||
|
@ -62,6 +67,11 @@ public class ShufflePlayBuffer
|
||||||
executorService.scheduleWithFixedDelay(runnable, 1, 10, TimeUnit.SECONDS);
|
executorService.scheduleWithFixedDelay(runnable, 1, 10, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onDestroy()
|
||||||
|
{
|
||||||
|
executorService.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
public List<MusicDirectory.Entry> get(int size)
|
public List<MusicDirectory.Entry> get(int size)
|
||||||
{
|
{
|
||||||
clearBufferIfNecessary();
|
clearBufferIfNecessary();
|
||||||
|
@ -78,13 +88,9 @@ public class ShufflePlayBuffer
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown()
|
|
||||||
{
|
|
||||||
executorService.shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refill()
|
private void refill()
|
||||||
{
|
{
|
||||||
|
if (!isEnabled) return;
|
||||||
|
|
||||||
// Check if active server has changed.
|
// Check if active server has changed.
|
||||||
clearBufferIfNecessary();
|
clearBufferIfNecessary();
|
||||||
|
|
|
@ -57,6 +57,7 @@ import org.moire.ultrasonic.service.DownloadFile;
|
||||||
import org.moire.ultrasonic.service.DownloadService;
|
import org.moire.ultrasonic.service.DownloadService;
|
||||||
import org.moire.ultrasonic.service.DownloadServiceImpl;
|
import org.moire.ultrasonic.service.DownloadServiceImpl;
|
||||||
import org.moire.ultrasonic.service.DownloadServiceLifecycleSupport;
|
import org.moire.ultrasonic.service.DownloadServiceLifecycleSupport;
|
||||||
|
import org.moire.ultrasonic.service.Downloader;
|
||||||
import org.moire.ultrasonic.service.MediaPlayerService;
|
import org.moire.ultrasonic.service.MediaPlayerService;
|
||||||
import org.moire.ultrasonic.service.MusicServiceFactory;
|
import org.moire.ultrasonic.service.MusicServiceFactory;
|
||||||
|
|
||||||
|
@ -960,7 +961,7 @@ public class Util extends DownloadActivity
|
||||||
context.sendBroadcast(intent);
|
context.sendBroadcast(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void broadcastA2dpMetaDataChange(Context context, DownloadService downloadService)
|
public static void broadcastA2dpMetaDataChange(Context context, int playerPosition, DownloadFile currentPlaying, int listSize, int id)
|
||||||
{
|
{
|
||||||
if (!Util.getShouldSendBluetoothNotifications(context))
|
if (!Util.getShouldSendBluetoothNotifications(context))
|
||||||
{
|
{
|
||||||
|
@ -970,17 +971,9 @@ public class Util extends DownloadActivity
|
||||||
Entry song = null;
|
Entry song = null;
|
||||||
Intent avrcpIntent = new Intent(CM_AVRCP_METADATA_CHANGED);
|
Intent avrcpIntent = new Intent(CM_AVRCP_METADATA_CHANGED);
|
||||||
|
|
||||||
if (downloadService != null)
|
if (currentPlaying != null) song = currentPlaying.getSong();
|
||||||
{
|
|
||||||
DownloadFile entry = downloadService.getCurrentPlaying();
|
|
||||||
|
|
||||||
if (entry != null)
|
if (song == null)
|
||||||
{
|
|
||||||
song = entry.getSong();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (downloadService == null || song == null)
|
|
||||||
{
|
{
|
||||||
avrcpIntent.putExtra("track", "");
|
avrcpIntent.putExtra("track", "");
|
||||||
avrcpIntent.putExtra("track_name", "");
|
avrcpIntent.putExtra("track_name", "");
|
||||||
|
@ -1013,9 +1006,6 @@ public class Util extends DownloadActivity
|
||||||
String artist = song.getArtist();
|
String artist = song.getArtist();
|
||||||
String album = song.getAlbum();
|
String album = song.getAlbum();
|
||||||
Integer duration = song.getDuration();
|
Integer duration = song.getDuration();
|
||||||
Integer listSize = downloadService.getDownloads().size();
|
|
||||||
Integer id = downloadService.getCurrentPlayingIndex() + 1;
|
|
||||||
Integer playerPosition = downloadService.getPlayerPosition();
|
|
||||||
|
|
||||||
avrcpIntent.putExtra("track", title);
|
avrcpIntent.putExtra("track", title);
|
||||||
avrcpIntent.putExtra("track_name", title);
|
avrcpIntent.putExtra("track_name", title);
|
||||||
|
|
|
@ -39,8 +39,10 @@ import org.moire.ultrasonic.featureflags.FeatureStorage;
|
||||||
import org.moire.ultrasonic.service.DownloadFile;
|
import org.moire.ultrasonic.service.DownloadFile;
|
||||||
import org.moire.ultrasonic.service.DownloadService;
|
import org.moire.ultrasonic.service.DownloadService;
|
||||||
import org.moire.ultrasonic.service.DownloadServiceImpl;
|
import org.moire.ultrasonic.service.DownloadServiceImpl;
|
||||||
|
import org.moire.ultrasonic.service.Downloader;
|
||||||
import org.moire.ultrasonic.service.MusicService;
|
import org.moire.ultrasonic.service.MusicService;
|
||||||
import org.moire.ultrasonic.service.MusicServiceFactory;
|
import org.moire.ultrasonic.service.MusicServiceFactory;
|
||||||
|
import org.moire.ultrasonic.service.Player;
|
||||||
import org.moire.ultrasonic.util.Util;
|
import org.moire.ultrasonic.util.Util;
|
||||||
import org.moire.ultrasonic.util.VideoPlayerType;
|
import org.moire.ultrasonic.util.VideoPlayerType;
|
||||||
|
|
||||||
|
@ -82,7 +84,8 @@ public class SongView extends UpdateView implements Checkable
|
||||||
private boolean maximized = false;
|
private boolean maximized = false;
|
||||||
private boolean useFiveStarRating;
|
private boolean useFiveStarRating;
|
||||||
|
|
||||||
private Lazy<DownloadServiceImpl> downloadServiceImpl = inject(DownloadServiceImpl.class);
|
private Lazy<Downloader> downloader = inject(Downloader.class);
|
||||||
|
protected Lazy<Player> player = inject(Player.class);
|
||||||
|
|
||||||
public SongView(Context context)
|
public SongView(Context context)
|
||||||
{
|
{
|
||||||
|
@ -169,7 +172,7 @@ public class SongView extends UpdateView implements Checkable
|
||||||
|
|
||||||
this.song = song;
|
this.song = song;
|
||||||
|
|
||||||
this.downloadFile = downloadServiceImpl.getValue().forSong(song);
|
this.downloadFile = downloader.getValue().getDownloadFileForSong(song);
|
||||||
|
|
||||||
StringBuilder artist = new StringBuilder(60);
|
StringBuilder artist = new StringBuilder(60);
|
||||||
|
|
||||||
|
@ -320,7 +323,7 @@ public class SongView extends UpdateView implements Checkable
|
||||||
{
|
{
|
||||||
updateBackground();
|
updateBackground();
|
||||||
|
|
||||||
downloadFile = downloadServiceImpl.getValue().forSong(this.song);
|
downloadFile = downloader.getValue().getDownloadFileForSong(this.song);
|
||||||
File partialFile = downloadFile.getPartialFile();
|
File partialFile = downloadFile.getPartialFile();
|
||||||
|
|
||||||
if (downloadFile.isWorkDone())
|
if (downloadFile.isWorkDone())
|
||||||
|
@ -410,7 +413,7 @@ public class SongView extends UpdateView implements Checkable
|
||||||
viewHolder.fiveStar4.setImageDrawable(rating > 3 ? starDrawable : starHollowDrawable);
|
viewHolder.fiveStar4.setImageDrawable(rating > 3 ? starDrawable : starHollowDrawable);
|
||||||
viewHolder.fiveStar5.setImageDrawable(rating > 4 ? starDrawable : starHollowDrawable);
|
viewHolder.fiveStar5.setImageDrawable(rating > 4 ? starDrawable : starHollowDrawable);
|
||||||
|
|
||||||
boolean playing = downloadServiceImpl.getValue().getCurrentPlaying() == downloadFile;
|
boolean playing = player.getValue().currentPlaying == downloadFile;
|
||||||
|
|
||||||
if (playing)
|
if (playing)
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.moire.ultrasonic.cache.PermanentFileStorage
|
||||||
import org.moire.ultrasonic.service.*
|
import org.moire.ultrasonic.service.*
|
||||||
import org.moire.ultrasonic.subsonic.loader.image.SubsonicImageLoader
|
import org.moire.ultrasonic.subsonic.loader.image.SubsonicImageLoader
|
||||||
import org.moire.ultrasonic.util.Constants
|
import org.moire.ultrasonic.util.Constants
|
||||||
|
import org.moire.ultrasonic.util.ShufflePlayBuffer
|
||||||
|
|
||||||
internal const val MUSIC_SERVICE_CONTEXT = "CurrentMusicService"
|
internal const val MUSIC_SERVICE_CONTEXT = "CurrentMusicService"
|
||||||
internal const val ONLINE_MUSIC_SERVICE = "OnlineMusicService"
|
internal const val ONLINE_MUSIC_SERVICE = "OnlineMusicService"
|
||||||
|
@ -112,9 +113,12 @@ val musicServiceModule = module(MUSIC_SERVICE_CONTEXT) {
|
||||||
|
|
||||||
single { SubsonicImageLoader(getProperty(DiProperties.APP_CONTEXT), get()) }
|
single { SubsonicImageLoader(getProperty(DiProperties.APP_CONTEXT), get()) }
|
||||||
|
|
||||||
single { DownloadServiceImpl(androidContext()) }
|
single { DownloadServiceImpl(androidContext(), get(), get(), get()) }
|
||||||
single { JukeboxService(androidContext()) }
|
single { JukeboxService(androidContext(), get()) }
|
||||||
single { DownloadServiceLifecycleSupport(androidContext(), get())}
|
single { DownloadServiceLifecycleSupport(androidContext(), get(), get()) }
|
||||||
single { DownloadQueueSerializer(androidContext())}
|
single { DownloadQueueSerializer(androidContext()) }
|
||||||
single { ExternalStorageMonitor(androidContext())}
|
single { ExternalStorageMonitor(androidContext()) }
|
||||||
|
single { ShufflePlayBuffer(androidContext()) }
|
||||||
|
single { Downloader(androidContext(), get(), get(), get()) }
|
||||||
|
single { Player(androidContext()) }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue