/*
This file is part of Subsonic.
Subsonic is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Subsonic is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
Copyright 2009 (C) Sindre Mehus
*/
package github.daneren2005.dsub.service;
import android.content.SharedPreferences;
import android.util.Log;
import java.util.Iterator;
import java.util.concurrent.LinkedBlockingQueue;
import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.domain.RemoteStatus;
import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.Util;
import github.daneren2005.serverproxy.FileProxy;
import github.daneren2005.serverproxy.ServerProxy;
import github.daneren2005.serverproxy.WebProxy;
public abstract class RemoteController {
private static final String TAG = RemoteController.class.getSimpleName();
protected DownloadService downloadService;
protected boolean nextSupported = false;
protected ServerProxy proxy;
protected String rootLocation = "";
public RemoteController(DownloadService downloadService) {
this.downloadService = downloadService;
SharedPreferences prefs = Util.getPreferences(downloadService);
rootLocation = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
}
public abstract void create(boolean playing, int seconds);
public abstract void start();
public abstract void stop();
public abstract void shutdown();
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() {
if(Util.getPreferences(downloadService).getBoolean(Constants.PREFERENCES_KEY_CAST_GAPLESS_PLAYBACK, true)) {
return this.nextSupported;
} else {
return false;
}
}
public abstract void setVolume(int volume);
public abstract void updateVolume(boolean up);
public abstract double getVolume();
public boolean isSeekable() {
return true;
}
public abstract int getRemotePosition();
public int getRemoteDuration() {
return 0;
}
protected abstract class RemoteTask {
abstract RemoteStatus execute() throws Exception;
@Override
public String toString() {
return getClass().getSimpleName();
}
}
protected static class TaskQueue {
private final LinkedBlockingQueue<RemoteTask> queue = new LinkedBlockingQueue<RemoteTask>();
void add(RemoteTask jukeboxTask) {
queue.add(jukeboxTask);
}
RemoteTask take() throws InterruptedException {
return queue.take();
}
void remove(Class<? extends RemoteTask> clazz) {
try {
Iterator<RemoteTask> iterator = queue.iterator();
while (iterator.hasNext()) {
RemoteTask task = iterator.next();
if (clazz.equals(task.getClass())) {
iterator.remove();
}
}
} catch (Throwable x) {
Log.w(TAG, "Failed to clean-up task queue.", x);
}
}
void clear() {
queue.clear();
}
}
protected WebProxy createWebProxy() {
MusicService musicService = MusicServiceFactory.getMusicService(downloadService);
if(musicService instanceof CachedMusicService) {
RESTMusicService restMusicService = ((CachedMusicService)musicService).getMusicService();
return new WebProxy(downloadService, restMusicService.getSSLSocketFactory(), restMusicService.getHostNameVerifier());
} else {
return new WebProxy(downloadService);
}
}
protected String getStreamUrl(MusicService musicService, DownloadFile downloadFile) throws Exception {
MusicDirectory.Entry song = downloadFile.getSong();
String url;
// In offline mode or playing offline song
if(downloadFile.isStream()) {
url = downloadFile.getStream();
} else if(Util.isOffline(downloadService) || song.getId().indexOf(rootLocation) != -1) {
if(proxy == null) {
proxy = new FileProxy(downloadService);
proxy.start();
}
// 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;
}
if(proxy == null) {
proxy = createWebProxy();
proxy.start();
}
} else if(proxy != null) {
proxy.stop();
proxy = null;
}
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 WebProxy
if(proxy != null) {
url = proxy.getPublicAddress(url);
}
}
return url;
}
}