diff options
-rw-r--r-- | README | 19 | ||||
-rw-r--r-- | res/anim/fade_in.xml | 5 | ||||
-rw-r--r-- | res/anim/fade_out.xml | 5 | ||||
-rw-r--r-- | res/xml/changelog.xml | 2 | ||||
-rw-r--r-- | src/github/daneren2005/dsub/activity/SubsonicActivity.java | 1 | ||||
-rw-r--r-- | src/github/daneren2005/dsub/provider/DLNARouteProvider.java | 25 | ||||
-rw-r--r-- | src/github/daneren2005/dsub/service/DLNAController.java | 317 | ||||
-rw-r--r-- | src/github/daneren2005/dsub/service/DownloadService.java | 53 | ||||
-rw-r--r-- | src/github/daneren2005/dsub/service/RemoteController.java | 8 |
9 files changed, 281 insertions, 154 deletions
@@ -5,22 +5,3 @@ git submodule update Go to DragSortListView/library, and ServerProxy and build project files with: android update project --path ./ - - -Roadmap of major planned features in rough order that I plan to work on them in (little features get sprinkled in wherever): - -Madsonic support - -Pandora Mode - -Top tracks for artist -DLNA - -Casting - -Library Provider -Album Art Grid View - -Display artists if supported (yes for tags, no for folders currently) - -Display playlists, pull info from cached listings -New Tabs - -Internet Radio tab -HLS Video - -Display video where album art is currently (double tap to fullscreen) - -Videos can play inline with songs - diff --git a/res/anim/fade_in.xml b/res/anim/fade_in.xml new file mode 100644 index 00000000..c41db065 --- /dev/null +++ b/res/anim/fade_in.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<alpha xmlns:android="http://schemas.android.com/apk/res/android" + android:duration="500" + android:fromAlpha="0.0" + android:toAlpha="1.0" />
\ No newline at end of file diff --git a/res/anim/fade_out.xml b/res/anim/fade_out.xml new file mode 100644 index 00000000..d615f2a1 --- /dev/null +++ b/res/anim/fade_out.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<alpha xmlns:android="http://schemas.android.com/apk/res/android" + android:duration="500" + android:fromAlpha="1.0" + android:toAlpha="0.0" />
\ No newline at end of file diff --git a/res/xml/changelog.xml b/res/xml/changelog.xml index 7fc45072..9b7fe781 100644 --- a/res/xml/changelog.xml +++ b/res/xml/changelog.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <changelog> - <release version="4.9.4" versioncode="144" releasedate="3/9/2015"> + <release version="4.9.4" versioncode="147" releasedate="3/9/2015"> <change>Cast proxy setting for fixing casting with self-signed certificates</change> <change>View all albums in alphabetical order from Home tab</change> <change>View all videso from Home tab</change> diff --git a/src/github/daneren2005/dsub/activity/SubsonicActivity.java b/src/github/daneren2005/dsub/activity/SubsonicActivity.java index dab46779..e3094546 100644 --- a/src/github/daneren2005/dsub/activity/SubsonicActivity.java +++ b/src/github/daneren2005/dsub/activity/SubsonicActivity.java @@ -137,6 +137,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte // Make sure to update theme
if (theme != null && !theme.equals(Util.getTheme(this)) || fullScreen != Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_FULL_SCREEN, false)) {
restart();
+ overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
}
populateDrawer();
diff --git a/src/github/daneren2005/dsub/provider/DLNARouteProvider.java b/src/github/daneren2005/dsub/provider/DLNARouteProvider.java index 8d9c5f45..54c9ffb5 100644 --- a/src/github/daneren2005/dsub/provider/DLNARouteProvider.java +++ b/src/github/daneren2005/dsub/provider/DLNARouteProvider.java @@ -68,6 +68,7 @@ public class DLNARouteProvider extends MediaRouteProvider { private HashMap<String, DLNADevice> devices = new HashMap<String, DLNADevice>(); private List<String> adding = new ArrayList<String>(); + private List<String> removing = new ArrayList<String>(); private AndroidUpnpService dlnaService; private ServiceConnection dlnaServiceConnection; private boolean searchOnConnect = false; @@ -215,6 +216,11 @@ public class DLNARouteProvider extends MediaRouteProvider { if(adding.contains(id)) { return; } + // Just a temp disconnect, already have it's info + if(removing.contains(id)) { + removing.remove(id); + return; + } adding.add(id); if(device.getType().getType().equals("MediaRenderer") && device instanceof RemoteDevice) { @@ -261,16 +267,21 @@ public class DLNARouteProvider extends MediaRouteProvider { } private void deviceRemoved(Device device) { if(device.getType().getType().equals("MediaRenderer") && device instanceof RemoteDevice) { - String id = device.getIdentity().getUdn().toString(); - devices.remove(id); - - // Make sure we do this on the main thread - downloadService.post(new Runnable() { + final String id = device.getIdentity().getUdn().toString(); + removing.add(id); + + // Delay removal for a few seconds to make sure that it isn't just a temp disconnect + dlnaService.getControlPoint().search(); + downloadService.postDelayed(new Runnable() { @Override public void run() { - broadcastDescriptors(); + if(removing.contains(id)) { + devices.remove(id); + removing.remove(id); + broadcastDescriptors(); + } } - }); + }, 5000L); } } diff --git a/src/github/daneren2005/dsub/service/DLNAController.java b/src/github/daneren2005/dsub/service/DLNAController.java index 5daf0910..036b111e 100644 --- a/src/github/daneren2005/dsub/service/DLNAController.java +++ b/src/github/daneren2005/dsub/service/DLNAController.java @@ -19,6 +19,7 @@ import android.content.SharedPreferences; import android.os.Looper;
import android.util.Log;
+import org.fourthline.cling.controlpoint.ActionCallback;
import org.fourthline.cling.controlpoint.ControlPoint;
import org.fourthline.cling.controlpoint.SubscriptionCallback;
import org.fourthline.cling.model.action.ActionInvocation;
@@ -30,6 +31,7 @@ import org.fourthline.cling.model.meta.Service; import org.fourthline.cling.model.meta.StateVariable;
import org.fourthline.cling.model.state.StateVariableValue;
import org.fourthline.cling.model.types.ServiceType;
+import org.fourthline.cling.model.types.UnsignedIntegerFourBytes;
import org.fourthline.cling.support.avtransport.callback.GetPositionInfo;
import org.fourthline.cling.support.avtransport.callback.Pause;
import org.fourthline.cling.support.avtransport.callback.Play;
@@ -65,6 +67,7 @@ import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.domain.PlayerState;
import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.FileUtil;
+import github.daneren2005.dsub.util.Pair;
import github.daneren2005.dsub.util.Util;
import github.daneren2005.serverproxy.FileProxy;
import github.daneren2005.serverproxy.ServerProxy;
@@ -79,6 +82,7 @@ public class DLNAController extends RemoteController { ControlPoint controlPoint;
SubscriptionCallback callback;
boolean supportsSeek = false;
+ boolean supportsSetupNext = false;
private ServerProxy proxy;
String rootLocation = "";
@@ -87,6 +91,8 @@ public class DLNAController extends RemoteController { final AtomicLong lastUpdate = new AtomicLong();
int currentPosition = 0;
String currentPlayingURI;
+ String nextPlayingURI;
+ DownloadFile nextPlaying;
boolean running = true;
boolean hasDuration = false;
Runnable searchDLNA = new Runnable() {
@@ -108,6 +114,7 @@ public class DLNAController extends RemoteController { SharedPreferences prefs = Util.getPreferences(downloadService);
rootLocation = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
+ nextSupported = true;
}
@Override
@@ -131,6 +138,10 @@ public class DLNAController extends RemoteController { }
}
}
+ Action setupNextAction = genaSubscription.getService().getAction("SetNextAVTransportURI");
+ if(setupNextAction != null) {
+ supportsSetupNext = true;
+ }
startSong(downloadService.getCurrentPlaying(), playing, seconds);
downloadService.postDelayed(searchDLNA, SEARCH_UPDATE_INTERVAL_SECONDS);
@@ -160,6 +171,11 @@ public class DLNAController extends RemoteController { switch (lastChange.getEventedValue(0, AVTransportVariable.TransportState.class).getValue()) {
case PLAYING:
downloadService.setPlayerState(PlayerState.STARTED);
+
+ // Try to setup next playing after playback start has been registered
+ if(supportsSetupNext && downloadService.getNextPlayerState() == PlayerState.IDLE) {
+ downloadService.setNextPlaying();
+ }
break;
case PAUSED_PLAYBACK:
downloadService.setPlayerState(PlayerState.PAUSED);
@@ -308,6 +324,11 @@ public class DLNAController extends RemoteController { }
@Override
+ public void changeNextTrack(DownloadFile song) {
+ setupNextSong(song);
+ }
+
+ @Override
public void setVolume(int volume) {
if(volume < 0) {
volume = 0;
@@ -382,152 +403,195 @@ public class DLNAController extends RemoteController { error = false;
downloadService.setPlayerState(PlayerState.PREPARING);
- MusicDirectory.Entry song = currentPlaying.getSong();
try {
- // Get url for entry
- MusicService musicService = MusicServiceFactory.getMusicService(downloadService);
- String url;
- // In offline mode or playing offline song
- if(Util.isOffline(downloadService) || song.getId().indexOf(rootLocation) != -1) {
- if(proxy == null) {
- proxy = new FileProxy(downloadService);
- proxy.start();
- }
+ Pair<String, String> songInfo = getSongInfo(currentPlaying);
- // Offline song
- if(song.getId().indexOf(rootLocation) != -1) {
- url = proxy.getPublicAddress(song.getId());
- } else {
- // Playing online song in offline mode
- url = proxy.getPublicAddress(currentPlaying.getCompleteFile().getPath());
- }
- } else {
- // Check if we want a proxy going still
- if(Util.isCastProxy(downloadService)) {
- if(proxy instanceof FileProxy) {
- proxy.stop();
- proxy = null;
+ currentPlayingURI = songInfo.getFirst();
+ downloadService.setNextPlayerState(PlayerState.IDLE);
+ controlPoint.execute(new SetAVTransportURI(getTransportService(), songInfo.getFirst(), songInfo.getSecond()) {
+ @Override
+ public void success(ActionInvocation invocation) {
+ if(position != 0) {
+ changePosition(position);
}
- if(proxy == null) {
- proxy = createWebProxy();
- proxy.start();
+ if (autoStart) {
+ start();
+ } else {
+ downloadService.setPlayerState(PlayerState.PAUSED);
}
- } else if(proxy != null) {
- proxy.stop();
- proxy = null;
- }
- if(song.isVideo()) {
- url = musicService.getHlsUrl(song.getId(), currentPlaying.getBitRate(), downloadService);
- } else {
- url = musicService.getMusicUrl(downloadService, song, currentPlaying.getBitRate());
+ currentPosition = position;
+ lastUpdate.set(System.currentTimeMillis());
+ getUpdatedStatus();
}
- // If proxy is going, it is a WebProxy
- if(proxy != null) {
- url = proxy.getPublicAddress(url);
+ @Override
+ public void failure(ActionInvocation actionInvocation, UpnpResponse upnpResponse, String msg) {
+ Log.w(TAG, "Set URI failed: " + msg);
+ failedLoad();
}
- }
+ });
+ } catch (Exception e) {
+ Log.w(TAG, "Failed startSong", e);
+ failedLoad();
+ }
+ }
+ private void setupNextSong(final DownloadFile nextPlaying) {
+ this.nextPlaying = nextPlaying;
+ nextPlayingURI = null;
+ if(nextPlaying == null) {
+ downloadService.setNextPlayerState(PlayerState.IDLE);
+ Log.i(TAG, "Nothing to play next");
+ return;
+ }
- // Create metadata for entry
- Item track;
- if(song.isVideo()) {
- track = new VideoItem(song.getId(), song.getParent(), song.getTitle(), song.getArtist());
- } else {
- String contentType = null;
- if(song.getTranscodedContentType() != null) {
- contentType = song.getTranscodedContentType();
- } else if(song.getContentType() != null) {
- contentType = song.getContentType();
+ downloadService.setNextPlayerState(PlayerState.PREPARING);
+ try {
+ Pair<String, String> songInfo = getSongInfo(nextPlaying);
+
+ nextPlayingURI = songInfo.getFirst();
+ controlPoint.execute(new SetNextAVTransportURI(getTransportService(), songInfo.getFirst(), songInfo.getSecond()) {
+ @Override
+ public void success(ActionInvocation invocation) {
+ downloadService.setNextPlayerState(PlayerState.PREPARED);
}
- MimeType mimeType;
- // If we can parse the content type, use it instead of hard coding
- if(contentType != null && contentType.indexOf("/") != -1 && contentType.indexOf("/") != (contentType.length() - 1)) {
- String[] typeParts = contentType.split("/");
- mimeType = new MimeType(typeParts[0], typeParts[1]);
- } else {
- mimeType = new MimeType("audio", "mpeg");
+ @Override
+ public void failure(ActionInvocation actionInvocation, UpnpResponse upnpResponse, String msg) {
+ Log.w(TAG, "Set next URI failed: " + msg);
+ nextPlayingURI = null;
+ DLNAController.this.nextPlaying = null;
+ downloadService.setNextPlayerState(PlayerState.IDLE);
}
+ });
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to setup next song", e);
+ nextPlayingURI = null;
+ this.nextPlaying = null;
+ downloadService.setNextPlayerState(PlayerState.IDLE);
+ }
+ }
- Res res = new Res(mimeType, song.getSize(), url);
+ Pair<String, String> getSongInfo(final DownloadFile downloadFile) throws Exception {
+ MusicDirectory.Entry song = downloadFile.getSong();
+
+ // Get url for entry
+ MusicService musicService = MusicServiceFactory.getMusicService(downloadService);
+ String url;
+ // In offline mode or playing offline song
+ if(Util.isOffline(downloadService) || song.getId().indexOf(rootLocation) != -1) {
+ if(proxy == null) {
+ proxy = new FileProxy(downloadService);
+ proxy.start();
+ }
- if(song.getDuration() != null) {
- SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
- df.setTimeZone(TimeZone.getTimeZone("UTC"));
- res.setDuration(df.format(new Date(song.getDuration() * 1000)));
+ // Offline song
+ if(song.getId().indexOf(rootLocation) != -1) {
+ url = proxy.getPublicAddress(song.getId());
+ } else {
+ // Playing online song in offline mode
+ url = proxy.getPublicAddress(downloadFile.getCompleteFile().getPath());
+ }
+ } else {
+ // Check if we want a proxy going still
+ if(Util.isCastProxy(downloadService)) {
+ if(proxy instanceof FileProxy) {
+ proxy.stop();
+ proxy = null;
}
- MusicTrack musicTrack = new MusicTrack(song.getId(), song.getParent(), song.getTitle(), song.getArtist(), song.getAlbum(), song.getArtist(), res);
- musicTrack.setOriginalTrackNumber(song.getTrack());
+ if(proxy == null) {
+ proxy = createWebProxy();
+ proxy.start();
+ }
+ } else if(proxy != null) {
+ proxy.stop();
+ proxy = null;
+ }
- if(song.getCoverArt() != null) {
- String coverArt = null;
- if(proxy == null || proxy instanceof WebProxy) {
- coverArt = musicService.getCoverArtUrl(downloadService, song);
+ if(song.isVideo()) {
+ url = musicService.getHlsUrl(song.getId(), downloadFile.getBitRate(), downloadService);
+ } else {
+ url = musicService.getMusicUrl(downloadService, song, downloadFile.getBitRate());
+ }
- // If proxy is going, it is a web proxy
- if(proxy != null) {
- coverArt = proxy.getPublicAddress(coverArt);
- }
- } else {
- File coverArtFile = FileUtil.getAlbumArtFile(downloadService, song);
- if(coverArtFile != null && coverArtFile.exists()) {
- coverArt = proxy.getPublicAddress(coverArtFile.getPath());
- }
- }
+ // If proxy is going, it is a WebProxy
+ if(proxy != null) {
+ url = proxy.getPublicAddress(url);
+ }
+ }
- if(coverArt != null) {
- DIDLObject.Property.UPNP.ALBUM_ART_URI albumArtUri = new DIDLObject.Property.UPNP.ALBUM_ART_URI(URI.create(coverArt));
- musicTrack.addProperty(albumArtUri);
- }
- }
+ // Create metadata for entry
+ Item track;
+ if(song.isVideo()) {
+ track = new VideoItem(song.getId(), song.getParent(), song.getTitle(), song.getArtist());
+ } else {
+ String contentType = null;
+ if(song.getTranscodedContentType() != null) {
+ contentType = song.getTranscodedContentType();
+ } else if(song.getContentType() != null) {
+ contentType = song.getContentType();
+ }
- track = musicTrack;
+ MimeType mimeType;
+ // If we can parse the content type, use it instead of hard coding
+ if(contentType != null && contentType.indexOf("/") != -1 && contentType.indexOf("/") != (contentType.length() - 1)) {
+ String[] typeParts = contentType.split("/");
+ mimeType = new MimeType(typeParts[0], typeParts[1]);
+ } else {
+ mimeType = new MimeType("audio", "mpeg");
}
- DIDLParser parser = new DIDLParser();
- DIDLContent didl = new DIDLContent();
- didl.addItem(track);
+ Res res = new Res(mimeType, song.getSize(), url);
- String metadata = "";
- try {
- metadata = parser.generate(didl);
- } catch(Exception e) {
- Log.w(TAG, "Metadata generation failed", e);
+ if(song.getDuration() != null) {
+ SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
+ df.setTimeZone(TimeZone.getTimeZone("UTC"));
+ res.setDuration(df.format(new Date(song.getDuration() * 1000)));
}
- currentPlayingURI = url;
- controlPoint.execute(new SetAVTransportURI(getTransportService(), url, metadata) {
- @Override
- public void success(ActionInvocation invocation) {
- if(position != 0) {
- changePosition(position);
- }
+ MusicTrack musicTrack = new MusicTrack(song.getId(), song.getParent(), song.getTitle(), song.getArtist(), song.getAlbum(), song.getArtist(), res);
+ musicTrack.setOriginalTrackNumber(song.getTrack());
- if (autoStart) {
- start();
- } else {
- downloadService.setPlayerState(PlayerState.PAUSED);
- }
+ if(song.getCoverArt() != null) {
+ String coverArt = null;
+ if(proxy == null || proxy instanceof WebProxy) {
+ coverArt = musicService.getCoverArtUrl(downloadService, song);
- currentPosition = position;
- lastUpdate.set(System.currentTimeMillis());
- getUpdatedStatus();
+ // If proxy is going, it is a web proxy
+ if(proxy != null) {
+ coverArt = proxy.getPublicAddress(coverArt);
+ }
+ } else {
+ File coverArtFile = FileUtil.getAlbumArtFile(downloadService, song);
+ if(coverArtFile != null && coverArtFile.exists()) {
+ coverArt = proxy.getPublicAddress(coverArtFile.getPath());
+ }
}
- @Override
- public void failure(ActionInvocation actionInvocation, UpnpResponse upnpResponse, String msg) {
- Log.w(TAG, "Set URI failed: " + msg);
- failedLoad();
+ if(coverArt != null) {
+ DIDLObject.Property.UPNP.ALBUM_ART_URI albumArtUri = new DIDLObject.Property.UPNP.ALBUM_ART_URI(URI.create(coverArt));
+ musicTrack.addProperty(albumArtUri);
}
- });
- } catch (Exception e) {
- Log.w(TAG, "Failed startSong", e);
- failedLoad();
+ }
+
+ track = musicTrack;
+ }
+
+ DIDLParser parser = new DIDLParser();
+ DIDLContent didl = new DIDLContent();
+ didl.addItem(track);
+
+ String metadata = "";
+ try {
+ metadata = parser.generate(didl);
+ } catch(Exception e) {
+ Log.w(TAG, "Metadata generation failed", e);
}
+
+ return new Pair<String, String>(url, metadata);
}
private void failedLoad() {
@@ -572,6 +636,12 @@ public class DLNAController extends RemoteController { // Let's get the updated position
currentPosition = (int) positionInfo.getTrackElapsedSeconds();
+ if(positionInfo.getTrackURI() != null && positionInfo.getTrackURI().equals(nextPlayingURI) && downloadService.getNextPlayerState() == PlayerState.PREPARED) {
+ downloadService.setCurrentPlaying(nextPlaying, true);
+ downloadService.setPlayerState(PlayerState.STARTED);
+ downloadService.setNextPlaying();
+ }
+
downloadService.postDelayed(new Runnable() {
@Override
public void run() {
@@ -593,4 +663,25 @@ public class DLNAController extends RemoteController { }
});
}
+
+ private abstract class SetNextAVTransportURI extends ActionCallback {
+ public SetNextAVTransportURI(Service service, String uri) {
+ this(new UnsignedIntegerFourBytes(0), service, uri, null);
+ }
+
+ public SetNextAVTransportURI(Service service, String uri, String metadata) {
+ this(new UnsignedIntegerFourBytes(0), service, uri, metadata);
+ }
+
+ public SetNextAVTransportURI(UnsignedIntegerFourBytes instanceId, Service service, String uri) {
+ this(instanceId, service, uri, null);
+ }
+
+ public SetNextAVTransportURI(UnsignedIntegerFourBytes instanceId, Service service, String uri, String metadata) {
+ super(new ActionInvocation(service.getAction("SetNextAVTransportURI")));
+ getActionInvocation().setInput("InstanceID", instanceId);
+ getActionInvocation().setInput("NextURI", uri);
+ getActionInvocation().setInput("NextURIMetaData", metadata);
+ }
+ }
}
diff --git a/src/github/daneren2005/dsub/service/DownloadService.java b/src/github/daneren2005/dsub/service/DownloadService.java index 562d621c..a6b66d5a 100644 --- a/src/github/daneren2005/dsub/service/DownloadService.java +++ b/src/github/daneren2005/dsub/service/DownloadService.java @@ -757,11 +757,15 @@ public class DownloadService extends Service { synchronized void setNextPlaying() { SharedPreferences prefs = Util.getPreferences(DownloadService.this); - boolean gaplessPlayback = prefs.getBoolean(Constants.PREFERENCES_KEY_GAPLESS_PLAYBACK, true); - if(!gaplessPlayback) { - nextPlaying = null; - nextPlayerState = IDLE; - return; + + // Only obey gapless playback for local + if(remoteState == LOCAL) { + boolean gaplessPlayback = prefs.getBoolean(Constants.PREFERENCES_KEY_GAPLESS_PLAYBACK, true); + if (!gaplessPlayback) { + nextPlaying = null; + nextPlayerState = IDLE; + return; + } } setNextPlayerState(IDLE); @@ -774,10 +778,19 @@ public class DownloadService extends Service { } if(index < size() && index != -1 && index != currentPlayingIndex) { nextPlaying = downloadList.get(index); - nextPlayingTask = new CheckCompletionTask(nextPlaying); - nextPlayingTask.execute(); + + if(remoteState == LOCAL) { + nextPlayingTask = new CheckCompletionTask(nextPlaying); + nextPlayingTask.execute(); + } else if(remoteController != null) { + remoteController.changeNextTrack(nextPlaying); + } } else { - resetNext(); + if(remoteState == LOCAL) { + resetNext(); + } else if(remoteController != null) { + remoteController.changeNextTrack(nextPlaying); + } nextPlaying = null; } } @@ -812,6 +825,10 @@ public class DownloadService extends Service { return currentDownloading; } + public DownloadFile getNextPlaying() { + return nextPlaying; + } + public List<DownloadFile> getSongs() { return downloadList; } @@ -1174,6 +1191,10 @@ public class DownloadService extends Service { return playerState; } + public PlayerState getNextPlayerState() { + return nextPlayerState; + } + public synchronized void setPlayerState(final PlayerState playerState) { Log.i(TAG, this.playerState.name() + " -> " + playerState.name() + " (" + currentPlaying + ")"); @@ -1277,7 +1298,7 @@ public class DownloadService extends Service { scrobbler.scrobble(this, currentPlaying, true); } - private synchronized void setNextPlayerState(PlayerState playerState) { + public synchronized void setNextPlayerState(PlayerState playerState) { Log.i(TAG, "Next: " + this.nextPlayerState.name() + " -> " + playerState.name() + " (" + nextPlaying + ")"); this.nextPlayerState = playerState; } @@ -1777,11 +1798,15 @@ public class DownloadService extends Service { DownloadFile movedSong = list.remove(from); list.add(to, movedSong); currentPlayingIndex = downloadList.indexOf(currentPlaying); - if(remoteState != LOCAL && mainList) { - updateRemotePlaylist(); - } else if(mainList && (movedSong == nextPlaying || movedSong == currentPlaying || (currentPlayingIndex + 1) == to)) { - // Moving next playing, current playing, or moving a song to be next playing - setNextPlaying(); + if(mainList) { + if(remoteState == LOCAL || (remoteController != null && remoteController.isNextSupported())) { + // Moving next playing, current playing, or moving a song to be next playing + if(movedSong == nextPlaying || movedSong == currentPlaying || (currentPlayingIndex + 1) == to) { + setNextPlaying(); + } + } else { + updateRemotePlaylist(); + } } } diff --git a/src/github/daneren2005/dsub/service/RemoteController.java b/src/github/daneren2005/dsub/service/RemoteController.java index 4483598c..cac28c09 100644 --- a/src/github/daneren2005/dsub/service/RemoteController.java +++ b/src/github/daneren2005/dsub/service/RemoteController.java @@ -37,6 +37,7 @@ import github.daneren2005.serverproxy.WebProxy; public abstract class RemoteController { private static final String TAG = RemoteController.class.getSimpleName(); protected DownloadService downloadService; + protected boolean nextSupported = false; public abstract void create(boolean playing, int seconds); public abstract void start(); @@ -46,6 +47,13 @@ public abstract class RemoteController { public abstract void updatePlaylist(); public abstract void changePosition(int seconds); public abstract void changeTrack(int index, DownloadFile song); + // Really is abstract, just don't want to require RemoteController's support it + public void changeNextTrack(DownloadFile song) { + + }; + public boolean isNextSupported() { + return this.nextSupported; + } public abstract void setVolume(int volume); public abstract void updateVolume(boolean up); public abstract double getVolume(); |