aboutsummaryrefslogtreecommitdiff
path: root/subsonic-android/src/net/sourceforge/subsonic/androidapp/service
diff options
context:
space:
mode:
Diffstat (limited to 'subsonic-android/src/net/sourceforge/subsonic/androidapp/service')
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/CachedMusicService.java237
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/DownloadFile.java323
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/DownloadService.java112
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/DownloadServiceImpl.java930
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/DownloadServiceLifecycleSupport.java271
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/JukeboxService.java356
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/MediaStoreService.java109
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/MusicService.java91
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/MusicServiceFactory.java36
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/OfflineException.java32
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/OfflineMusicService.java273
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/RESTMusicService.java785
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/Scrobbler.java52
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ServerTooOldException.java51
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/AbstractParser.java138
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/AlbumListParser.java62
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/ErrorParser.java49
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/IndexesParser.java104
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/JukeboxStatusParser.java62
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/LicenseParser.java62
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/LyricsParser.java65
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/MusicDirectoryEntryParser.java59
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/MusicDirectoryParser.java71
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/MusicFoldersParser.java69
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/PlaylistParser.java62
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/PlaylistsParser.java67
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/RandomSongsParser.java62
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/SearchResult2Parser.java75
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/SearchResultParser.java67
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/SubsonicRESTException.java19
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/VersionParser.java47
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ssl/SSLSocketFactory.java497
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ssl/TrustManagerDecorator.java65
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ssl/TrustSelfSignedStrategy.java44
-rw-r--r--subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ssl/TrustStrategy.java57
35 files changed, 0 insertions, 5461 deletions
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/CachedMusicService.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/CachedMusicService.java
deleted file mode 100644
index 14aed954..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/CachedMusicService.java
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service;
-
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.http.HttpResponse;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import net.sourceforge.subsonic.androidapp.domain.Indexes;
-import net.sourceforge.subsonic.androidapp.domain.JukeboxStatus;
-import net.sourceforge.subsonic.androidapp.domain.Lyrics;
-import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
-import net.sourceforge.subsonic.androidapp.domain.MusicFolder;
-import net.sourceforge.subsonic.androidapp.domain.Playlist;
-import net.sourceforge.subsonic.androidapp.domain.SearchCritera;
-import net.sourceforge.subsonic.androidapp.domain.SearchResult;
-import net.sourceforge.subsonic.androidapp.domain.Version;
-import net.sourceforge.subsonic.androidapp.util.CancellableTask;
-import net.sourceforge.subsonic.androidapp.util.LRUCache;
-import net.sourceforge.subsonic.androidapp.util.ProgressListener;
-import net.sourceforge.subsonic.androidapp.util.TimeLimitedCache;
-import net.sourceforge.subsonic.androidapp.util.Util;
-
-/**
- * @author Sindre Mehus
- */
-public class CachedMusicService implements MusicService {
-
- private static final int MUSIC_DIR_CACHE_SIZE = 20;
- private static final int TTL_MUSIC_DIR = 5 * 60; // Five minutes
-
- private final MusicService musicService;
- private final LRUCache<String, TimeLimitedCache<MusicDirectory>> cachedMusicDirectories;
- private final TimeLimitedCache<Boolean> cachedLicenseValid = new TimeLimitedCache<Boolean>(120, TimeUnit.SECONDS);
- private final TimeLimitedCache<Indexes> cachedIndexes = new TimeLimitedCache<Indexes>(60 * 60, TimeUnit.SECONDS);
- private final TimeLimitedCache<List<Playlist>> cachedPlaylists = new TimeLimitedCache<List<Playlist>>(60, TimeUnit.SECONDS);
- private final TimeLimitedCache<List<MusicFolder>> cachedMusicFolders = new TimeLimitedCache<List<MusicFolder>>(10 * 3600, TimeUnit.SECONDS);
- private String restUrl;
-
- public CachedMusicService(MusicService musicService) {
- this.musicService = musicService;
- cachedMusicDirectories = new LRUCache<String, TimeLimitedCache<MusicDirectory>>(MUSIC_DIR_CACHE_SIZE);
- }
-
- @Override
- public void ping(Context context, ProgressListener progressListener) throws Exception {
- checkSettingsChanged(context);
- musicService.ping(context, progressListener);
- }
-
- @Override
- public boolean isLicenseValid(Context context, ProgressListener progressListener) throws Exception {
- checkSettingsChanged(context);
- Boolean result = cachedLicenseValid.get();
- if (result == null) {
- result = musicService.isLicenseValid(context, progressListener);
- cachedLicenseValid.set(result, result ? 30L * 60L : 2L * 60L, TimeUnit.SECONDS);
- }
- return result;
- }
-
- @Override
- public List<MusicFolder> getMusicFolders(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
- checkSettingsChanged(context);
- if (refresh) {
- cachedMusicFolders.clear();
- }
- List<MusicFolder> result = cachedMusicFolders.get();
- if (result == null) {
- result = musicService.getMusicFolders(refresh, context, progressListener);
- cachedMusicFolders.set(result);
- }
- return result;
- }
-
- @Override
- public Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
- checkSettingsChanged(context);
- if (refresh) {
- cachedIndexes.clear();
- cachedMusicFolders.clear();
- cachedMusicDirectories.clear();
- }
- Indexes result = cachedIndexes.get();
- if (result == null) {
- result = musicService.getIndexes(musicFolderId, refresh, context, progressListener);
- cachedIndexes.set(result);
- }
- return result;
- }
-
- @Override
- public MusicDirectory getMusicDirectory(String id, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
- checkSettingsChanged(context);
- TimeLimitedCache<MusicDirectory> cache = refresh ? null : cachedMusicDirectories.get(id);
- MusicDirectory dir = cache == null ? null : cache.get();
- if (dir == null) {
- dir = musicService.getMusicDirectory(id, refresh, context, progressListener);
- cache = new TimeLimitedCache<MusicDirectory>(TTL_MUSIC_DIR, TimeUnit.SECONDS);
- cache.set(dir);
- cachedMusicDirectories.put(id, cache);
- }
- return dir;
- }
-
- @Override
- public SearchResult search(SearchCritera criteria, Context context, ProgressListener progressListener) throws Exception {
- return musicService.search(criteria, context, progressListener);
- }
-
- @Override
- public MusicDirectory getPlaylist(String id, String name, Context context, ProgressListener progressListener) throws Exception {
- return musicService.getPlaylist(id, name, context, progressListener);
- }
-
- @Override
- public List<Playlist> getPlaylists(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
- checkSettingsChanged(context);
- List<Playlist> result = refresh ? null : cachedPlaylists.get();
- if (result == null) {
- result = musicService.getPlaylists(refresh, context, progressListener);
- cachedPlaylists.set(result);
- }
- return result;
- }
-
- @Override
- public void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries, Context context, ProgressListener progressListener) throws Exception {
- musicService.createPlaylist(id, name, entries, context, progressListener);
- }
-
- @Override
- public Lyrics getLyrics(String artist, String title, Context context, ProgressListener progressListener) throws Exception {
- return musicService.getLyrics(artist, title, context, progressListener);
- }
-
- @Override
- public void scrobble(String id, boolean submission, Context context, ProgressListener progressListener) throws Exception {
- musicService.scrobble(id, submission, context, progressListener);
- }
-
- @Override
- public MusicDirectory getAlbumList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception {
- return musicService.getAlbumList(type, size, offset, context, progressListener);
- }
-
- @Override
- public MusicDirectory getRandomSongs(int size, Context context, ProgressListener progressListener) throws Exception {
- return musicService.getRandomSongs(size, context, progressListener);
- }
-
- @Override
- public Bitmap getCoverArt(Context context, MusicDirectory.Entry entry, int size, boolean saveToFile, ProgressListener progressListener) throws Exception {
- return musicService.getCoverArt(context, entry, size, saveToFile, progressListener);
- }
-
- @Override
- public HttpResponse getDownloadInputStream(Context context, MusicDirectory.Entry song, long offset, int maxBitrate, CancellableTask task) throws Exception {
- return musicService.getDownloadInputStream(context, song, offset, maxBitrate, task);
- }
-
- @Override
- public Version getLocalVersion(Context context) throws Exception {
- return musicService.getLocalVersion(context);
- }
-
- @Override
- public Version getLatestVersion(Context context, ProgressListener progressListener) throws Exception {
- return musicService.getLatestVersion(context, progressListener);
- }
-
- @Override
- public String getVideoUrl(Context context, String id) {
- return musicService.getVideoUrl(context, id);
- }
-
- @Override
- public JukeboxStatus updateJukeboxPlaylist(List<String> ids, Context context, ProgressListener progressListener) throws Exception {
- return musicService.updateJukeboxPlaylist(ids, context, progressListener);
- }
-
- @Override
- public JukeboxStatus skipJukebox(int index, int offsetSeconds, Context context, ProgressListener progressListener) throws Exception {
- return musicService.skipJukebox(index, offsetSeconds, context, progressListener);
- }
-
- @Override
- public JukeboxStatus stopJukebox(Context context, ProgressListener progressListener) throws Exception {
- return musicService.stopJukebox(context, progressListener);
- }
-
- @Override
- public JukeboxStatus startJukebox(Context context, ProgressListener progressListener) throws Exception {
- return musicService.startJukebox(context, progressListener);
- }
-
- @Override
- public JukeboxStatus getJukeboxStatus(Context context, ProgressListener progressListener) throws Exception {
- return musicService.getJukeboxStatus(context, progressListener);
- }
-
- @Override
- public JukeboxStatus setJukeboxGain(float gain, Context context, ProgressListener progressListener) throws Exception {
- return musicService.setJukeboxGain(gain, context, progressListener);
- }
-
- private void checkSettingsChanged(Context context) {
- String newUrl = Util.getRestUrl(context, null);
- if (!Util.equals(newUrl, restUrl)) {
- cachedMusicFolders.clear();
- cachedMusicDirectories.clear();
- cachedLicenseValid.clear();
- cachedIndexes.clear();
- cachedPlaylists.clear();
- restUrl = newUrl;
- }
- }
-}
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/DownloadFile.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/DownloadFile.java
deleted file mode 100644
index 46373afe..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/DownloadFile.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import android.content.Context;
-import android.os.PowerManager;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
-import net.sourceforge.subsonic.androidapp.util.CancellableTask;
-import net.sourceforge.subsonic.androidapp.util.FileUtil;
-import net.sourceforge.subsonic.androidapp.util.Util;
-import net.sourceforge.subsonic.androidapp.util.CacheCleaner;
-
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-
-/**
- * @author Sindre Mehus
- * @version $Id$
- */
-public class DownloadFile {
-
- private static final String TAG = DownloadFile.class.getSimpleName();
- private final Context context;
- private final MusicDirectory.Entry song;
- private final File partialFile;
- private final File completeFile;
- private final File saveFile;
-
- private final MediaStoreService mediaStoreService;
- private CancellableTask downloadTask;
- private boolean save;
- private boolean failed;
- private int bitRate;
-
- public DownloadFile(Context context, MusicDirectory.Entry song, boolean save) {
- this.context = context;
- this.song = song;
- this.save = save;
- saveFile = FileUtil.getSongFile(context, song);
- bitRate = Util.getMaxBitrate(context);
- partialFile = new File(saveFile.getParent(), FileUtil.getBaseName(saveFile.getName()) +
- "." + bitRate + ".partial." + FileUtil.getExtension(saveFile.getName()));
- completeFile = new File(saveFile.getParent(), FileUtil.getBaseName(saveFile.getName()) +
- ".complete." + FileUtil.getExtension(saveFile.getName()));
- mediaStoreService = new MediaStoreService(context);
- }
-
- public MusicDirectory.Entry getSong() {
- return song;
- }
-
- /**
- * Returns the effective bit rate.
- */
- public int getBitRate() {
- if (bitRate > 0) {
- return bitRate;
- }
- return song.getBitRate() == null ? 160 : song.getBitRate();
- }
-
- public synchronized void download() {
- FileUtil.createDirectoryForParent(saveFile);
- failed = false;
- downloadTask = new DownloadTask();
- downloadTask.start();
- }
-
- public synchronized void cancelDownload() {
- if (downloadTask != null) {
- downloadTask.cancel();
- }
- }
-
- public File getCompleteFile() {
- if (saveFile.exists()) {
- return saveFile;
- }
-
- if (completeFile.exists()) {
- return completeFile;
- }
-
- return saveFile;
- }
-
- public File getPartialFile() {
- return partialFile;
- }
-
- public boolean isSaved() {
- return saveFile.exists();
- }
-
- public synchronized boolean isCompleteFileAvailable() {
- return saveFile.exists() || completeFile.exists();
- }
-
- public synchronized boolean isWorkDone() {
- return saveFile.exists() || (completeFile.exists() && !save);
- }
-
- public synchronized boolean isDownloading() {
- return downloadTask != null && downloadTask.isRunning();
- }
-
- public synchronized boolean isDownloadCancelled() {
- return downloadTask != null && downloadTask.isCancelled();
- }
-
- public boolean shouldSave() {
- return save;
- }
-
- public boolean isFailed() {
- return failed;
- }
-
- public void delete() {
- cancelDownload();
- Util.delete(partialFile);
- Util.delete(completeFile);
- Util.delete(saveFile);
- mediaStoreService.deleteFromMediaStore(this);
- }
-
- public void unpin() {
- if (saveFile.exists()) {
- saveFile.renameTo(completeFile);
- }
- }
-
- public boolean cleanup() {
- boolean ok = true;
- if (completeFile.exists() || saveFile.exists()) {
- ok = Util.delete(partialFile);
- }
- if (saveFile.exists()) {
- ok &= Util.delete(completeFile);
- }
- return ok;
- }
-
- // In support of LRU caching.
- public void updateModificationDate() {
- updateModificationDate(saveFile);
- updateModificationDate(partialFile);
- updateModificationDate(completeFile);
- }
-
- private void updateModificationDate(File file) {
- if (file.exists()) {
- boolean ok = file.setLastModified(System.currentTimeMillis());
- if (!ok) {
- Log.w(TAG, "Failed to set last-modified date on " + file);
- }
- }
- }
-
- @Override
- public String toString() {
- return "DownloadFile (" + song + ")";
- }
-
- private class DownloadTask extends CancellableTask {
-
- @Override
- public void execute() {
-
- InputStream in = null;
- FileOutputStream out = null;
- PowerManager.WakeLock wakeLock = null;
- try {
-
- if (Util.isScreenLitOnDownload(context)) {
- PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- wakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, toString());
- wakeLock.acquire();
- Log.i(TAG, "Acquired wake lock " + wakeLock);
- }
-
- if (saveFile.exists()) {
- Log.i(TAG, saveFile + " already exists. Skipping.");
- return;
- }
- if (completeFile.exists()) {
- if (save) {
- Util.atomicCopy(completeFile, saveFile);
- } else {
- Log.i(TAG, completeFile + " already exists. Skipping.");
- }
- return;
- }
-
- MusicService musicService = MusicServiceFactory.getMusicService(context);
-
- // Attempt partial HTTP GET, appending to the file if it exists.
- HttpResponse response = musicService.getDownloadInputStream(context, song, partialFile.length(), bitRate, DownloadTask.this);
- in = response.getEntity().getContent();
- boolean partial = response.getStatusLine().getStatusCode() == HttpStatus.SC_PARTIAL_CONTENT;
- if (partial) {
- Log.i(TAG, "Executed partial HTTP GET, skipping " + partialFile.length() + " bytes");
- }
-
- out = new FileOutputStream(partialFile, partial);
- long n = copy(in, out);
- Log.i(TAG, "Downloaded " + n + " bytes to " + partialFile);
- out.flush();
- out.close();
-
- if (isCancelled()) {
- throw new Exception("Download of '" + song + "' was cancelled");
- }
-
- downloadAndSaveCoverArt(musicService);
-
- if (save) {
- Util.atomicCopy(partialFile, saveFile);
- mediaStoreService.saveInMediaStore(DownloadFile.this);
- } else {
- Util.atomicCopy(partialFile, completeFile);
- }
-
- } catch (Exception x) {
- Util.close(out);
- Util.delete(completeFile);
- Util.delete(saveFile);
- if (!isCancelled()) {
- failed = true;
- Log.w(TAG, "Failed to download '" + song + "'.", x);
- }
-
- } finally {
- Util.close(in);
- Util.close(out);
- if (wakeLock != null) {
- wakeLock.release();
- Log.i(TAG, "Released wake lock " + wakeLock);
- }
- new CacheCleaner(context, DownloadServiceImpl.getInstance()).clean();
- }
- }
-
- @Override
- public String toString() {
- return "DownloadTask (" + song + ")";
- }
-
- private void downloadAndSaveCoverArt(MusicService musicService) throws Exception {
- try {
- if (song.getCoverArt() != null) {
- DisplayMetrics metrics = context.getResources().getDisplayMetrics();
- int size = Math.min(metrics.widthPixels, metrics.heightPixels);
- musicService.getCoverArt(context, song, size, true, null);
- }
- } catch (Exception x) {
- Log.e(TAG, "Failed to get cover art.", x);
- }
- }
-
- private long copy(final InputStream in, OutputStream out) throws IOException, InterruptedException {
-
- // Start a thread that will close the input stream if the task is
- // cancelled, thus causing the copy() method to return.
- new Thread() {
- @Override
- public void run() {
- while (true) {
- Util.sleepQuietly(3000L);
- if (isCancelled()) {
- Util.close(in);
- return;
- }
- if (!isRunning()) {
- return;
- }
- }
- }
- }.start();
-
- byte[] buffer = new byte[1024 * 16];
- long count = 0;
- int n;
- long lastLog = System.currentTimeMillis();
-
- while (!isCancelled() && (n = in.read(buffer)) != -1) {
- out.write(buffer, 0, n);
- count += n;
-
- long now = System.currentTimeMillis();
- if (now - lastLog > 3000L) { // Only every so often.
- Log.i(TAG, "Downloaded " + Util.formatBytes(count) + " of " + song);
- lastLog = now;
- }
- }
- return count;
- }
- }
-}
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/DownloadService.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/DownloadService.java
deleted file mode 100644
index b136bdbc..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/DownloadService.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service;
-
-import java.util.List;
-
-import net.sourceforge.subsonic.androidapp.audiofx.EqualizerController;
-import net.sourceforge.subsonic.androidapp.audiofx.VisualizerController;
-import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
-import net.sourceforge.subsonic.androidapp.domain.PlayerState;
-import net.sourceforge.subsonic.androidapp.domain.RepeatMode;
-
-/**
- * @author Sindre Mehus
- * @version $Id$
- */
-public interface DownloadService {
-
- void download(List<MusicDirectory.Entry> songs, boolean save, boolean autoplay, boolean playNext);
-
- void setShufflePlayEnabled(boolean enabled);
-
- boolean isShufflePlayEnabled();
-
- void shuffle();
-
- RepeatMode getRepeatMode();
-
- void setRepeatMode(RepeatMode repeatMode);
-
- boolean getKeepScreenOn();
-
- void setKeepScreenOn(boolean screenOn);
-
- boolean getShowVisualization();
-
- void setShowVisualization(boolean showVisualization);
-
- void clear();
-
- void clearIncomplete();
-
- int size();
-
- void remove(DownloadFile downloadFile);
-
- List<DownloadFile> getDownloads();
-
- int getCurrentPlayingIndex();
-
- DownloadFile getCurrentPlaying();
-
- DownloadFile getCurrentDownloading();
-
- void play(int index);
-
- void seekTo(int position);
-
- void previous();
-
- void next();
-
- void pause();
-
- void start();
-
- void reset();
-
- PlayerState getPlayerState();
-
- int getPlayerPosition();
-
- int getPlayerDuration();
-
- void delete(List<MusicDirectory.Entry> songs);
-
- void unpin(List<MusicDirectory.Entry> songs);
-
- DownloadFile forSong(MusicDirectory.Entry song);
-
- long getDownloadListUpdateRevision();
-
- void setSuggestedPlaylistName(String name);
-
- String getSuggestedPlaylistName();
-
- EqualizerController getEqualizerController();
-
- VisualizerController getVisualizerController();
-
- boolean isJukeboxEnabled();
-
- void setJukeboxEnabled(boolean b);
-
- void adjustJukeboxVolume(boolean up);
-}
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/DownloadServiceImpl.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/DownloadServiceImpl.java
deleted file mode 100644
index 2e668fea..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/DownloadServiceImpl.java
+++ /dev/null
@@ -1,930 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service;
-
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.media.AudioManager;
-import android.media.MediaPlayer;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.PowerManager;
-import android.util.Log;
-import net.sourceforge.subsonic.androidapp.audiofx.EqualizerController;
-import net.sourceforge.subsonic.androidapp.audiofx.VisualizerController;
-import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
-import net.sourceforge.subsonic.androidapp.domain.PlayerState;
-import net.sourceforge.subsonic.androidapp.domain.RepeatMode;
-import net.sourceforge.subsonic.androidapp.util.CancellableTask;
-import net.sourceforge.subsonic.androidapp.util.LRUCache;
-import net.sourceforge.subsonic.androidapp.util.ShufflePlayBuffer;
-import net.sourceforge.subsonic.androidapp.util.SimpleServiceBinder;
-import net.sourceforge.subsonic.androidapp.util.Util;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-import static net.sourceforge.subsonic.androidapp.domain.PlayerState.*;
-
-/**
- * @author Sindre Mehus
- * @version $Id$
- */
-public class DownloadServiceImpl extends Service implements DownloadService {
-
- private static final String TAG = DownloadServiceImpl.class.getSimpleName();
-
- public static final String CMD_PLAY = "net.sourceforge.subsonic.androidapp.CMD_PLAY";
- public static final String CMD_TOGGLEPAUSE = "net.sourceforge.subsonic.androidapp.CMD_TOGGLEPAUSE";
- public static final String CMD_PAUSE = "net.sourceforge.subsonic.androidapp.CMD_PAUSE";
- public static final String CMD_STOP = "net.sourceforge.subsonic.androidapp.CMD_STOP";
- public static final String CMD_PREVIOUS = "net.sourceforge.subsonic.androidapp.CMD_PREVIOUS";
- public static final String CMD_NEXT = "net.sourceforge.subsonic.androidapp.CMD_NEXT";
-
- private final IBinder binder = new SimpleServiceBinder<DownloadService>(this);
- private MediaPlayer mediaPlayer;
- private final List<DownloadFile> downloadList = new ArrayList<DownloadFile>();
- private final Handler handler = new Handler();
- private final DownloadServiceLifecycleSupport lifecycleSupport = new DownloadServiceLifecycleSupport(this);
- private final ShufflePlayBuffer shufflePlayBuffer = new ShufflePlayBuffer(this);
-
- private final LRUCache<MusicDirectory.Entry, DownloadFile> downloadFileCache = new LRUCache<MusicDirectory.Entry, DownloadFile>(100);
- private final List<DownloadFile> cleanupCandidates = new ArrayList<DownloadFile>();
- private final Scrobbler scrobbler = new Scrobbler();
- private final JukeboxService jukeboxService = new JukeboxService(this);
- private DownloadFile currentPlaying;
- private DownloadFile currentDownloading;
- private CancellableTask bufferTask;
- private PlayerState playerState = IDLE;
- private boolean shufflePlay;
- private long revision;
- private static DownloadService instance;
- private String suggestedPlaylistName;
- private PowerManager.WakeLock wakeLock;
- private boolean keepScreenOn = false;
-
- private static boolean equalizerAvailable;
- private static boolean visualizerAvailable;
- private EqualizerController equalizerController;
- private VisualizerController visualizerController;
- private boolean showVisualization;
- private boolean jukeboxEnabled;
-
- static {
- try {
- EqualizerController.checkAvailable();
- equalizerAvailable = true;
- } catch (Throwable t) {
- equalizerAvailable = false;
- }
- }
- static {
- try {
- VisualizerController.checkAvailable();
- visualizerAvailable = true;
- } catch (Throwable t) {
- visualizerAvailable = false;
- }
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
-
- mediaPlayer = new MediaPlayer();
- mediaPlayer.setWakeMode(this, PowerManager.PARTIAL_WAKE_LOCK);
-
- mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
- @Override
- public boolean onError(MediaPlayer mediaPlayer, int what, int more) {
- handleError(new Exception("MediaPlayer error: " + what + " (" + more + ")"));
- return false;
- }
- });
-
- if (equalizerAvailable) {
- equalizerController = new EqualizerController(this, mediaPlayer);
- if (!equalizerController.isAvailable()) {
- equalizerController = null;
- } else {
- equalizerController.loadSettings();
- }
- }
- if (visualizerAvailable) {
- visualizerController = new VisualizerController(this, mediaPlayer);
- if (!visualizerController.isAvailable()) {
- visualizerController = null;
- }
- }
-
- PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
- wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this.getClass().getName());
- wakeLock.setReferenceCounted(false);
-
- instance = this;
- lifecycleSupport.onCreate();
- }
-
- @Override
- public void onStart(Intent intent, int startId) {
- super.onStart(intent, startId);
- lifecycleSupport.onStart(intent);
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- lifecycleSupport.onDestroy();
- mediaPlayer.release();
- shufflePlayBuffer.shutdown();
- if (equalizerController != null) {
- equalizerController.release();
- }
- if (visualizerController != null) {
- visualizerController.release();
- }
-
- instance = null;
- }
-
- public static DownloadService getInstance() {
- return instance;
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return binder;
- }
-
- @Override
- public synchronized void download(List<MusicDirectory.Entry> songs, boolean save, boolean autoplay, boolean playNext) {
- shufflePlay = false;
- int offset = 1;
-
- if (songs.isEmpty()) {
- return;
- }
- if (playNext) {
- if (autoplay && getCurrentPlayingIndex() >= 0) {
- offset = 0;
- }
- for (MusicDirectory.Entry song : songs) {
- DownloadFile downloadFile = new DownloadFile(this, song, save);
- downloadList.add(getCurrentPlayingIndex() + offset, downloadFile);
- offset++;
- }
- revision++;
- } else {
- for (MusicDirectory.Entry song : songs) {
- DownloadFile downloadFile = new DownloadFile(this, song, save);
- downloadList.add(downloadFile);
- }
- revision++;
- }
- updateJukeboxPlaylist();
-
- if (autoplay) {
- play(0);
- } else {
- if (currentPlaying == null) {
- currentPlaying = downloadList.get(0);
- }
- checkDownloads();
- }
- lifecycleSupport.serializeDownloadQueue();
- }
-
- private void updateJukeboxPlaylist() {
- if (jukeboxEnabled) {
- jukeboxService.updatePlaylist();
- }
- }
-
- public void restore(List<MusicDirectory.Entry> songs, int currentPlayingIndex, int currentPlayingPosition) {
- download(songs, false, false, false);
- if (currentPlayingIndex != -1) {
- play(currentPlayingIndex, false);
- if (currentPlaying.isCompleteFileAvailable()) {
- doPlay(currentPlaying, currentPlayingPosition, false);
- }
- }
- }
-
- @Override
- public synchronized void setShufflePlayEnabled(boolean enabled) {
- if (shufflePlay == enabled) {
- return;
- }
-
- shufflePlay = enabled;
- if (shufflePlay) {
- clear();
- checkDownloads();
- }
- }
-
- @Override
- public synchronized boolean isShufflePlayEnabled() {
- return shufflePlay;
- }
-
- @Override
- public synchronized void shuffle() {
- Collections.shuffle(downloadList);
- if (currentPlaying != null) {
- downloadList.remove(getCurrentPlayingIndex());
- downloadList.add(0, currentPlaying);
- }
- revision++;
- lifecycleSupport.serializeDownloadQueue();
- updateJukeboxPlaylist();
- }
-
- @Override
- public RepeatMode getRepeatMode() {
- return Util.getRepeatMode(this);
- }
-
- @Override
- public void setRepeatMode(RepeatMode repeatMode) {
- Util.setRepeatMode(this, repeatMode);
- }
-
- @Override
- public boolean getKeepScreenOn() {
- return keepScreenOn;
- }
-
- @Override
- public void setKeepScreenOn(boolean keepScreenOn) {
- this.keepScreenOn = keepScreenOn;
- }
-
- @Override
- public boolean getShowVisualization() {
- return showVisualization;
- }
-
- @Override
- public void setShowVisualization(boolean showVisualization) {
- this.showVisualization = showVisualization;
- }
-
- @Override
- public synchronized DownloadFile forSong(MusicDirectory.Entry song) {
- for (DownloadFile downloadFile : downloadList) {
- if (downloadFile.getSong().equals(song)) {
- return downloadFile;
- }
- }
-
- DownloadFile downloadFile = downloadFileCache.get(song);
- if (downloadFile == null) {
- downloadFile = new DownloadFile(this, song, false);
- downloadFileCache.put(song, downloadFile);
- }
- return downloadFile;
- }
-
- @Override
- public synchronized void clear() {
- clear(true);
- }
-
- @Override
- public synchronized void clearIncomplete() {
- reset();
- Iterator<DownloadFile> iterator = downloadList.iterator();
- while (iterator.hasNext()) {
- DownloadFile downloadFile = iterator.next();
- if (!downloadFile.isCompleteFileAvailable()) {
- iterator.remove();
- }
- }
- lifecycleSupport.serializeDownloadQueue();
- updateJukeboxPlaylist();
- }
-
- @Override
- public synchronized int size() {
- return downloadList.size();
- }
-
- public synchronized void clear(boolean serialize) {
- reset();
- downloadList.clear();
- revision++;
- if (currentDownloading != null) {
- currentDownloading.cancelDownload();
- currentDownloading = null;
- }
- setCurrentPlaying(null, false);
-
- if (serialize) {
- lifecycleSupport.serializeDownloadQueue();
- }
- updateJukeboxPlaylist();
- }
-
- @Override
- public synchronized void remove(DownloadFile downloadFile) {
- if (downloadFile == currentDownloading) {
- currentDownloading.cancelDownload();
- currentDownloading = null;
- }
- if (downloadFile == currentPlaying) {
- reset();
- setCurrentPlaying(null, false);
- }
- downloadList.remove(downloadFile);
- revision++;
- lifecycleSupport.serializeDownloadQueue();
- updateJukeboxPlaylist();
- }
-
- @Override
- public synchronized void delete(List<MusicDirectory.Entry> songs) {
- for (MusicDirectory.Entry song : songs) {
- forSong(song).delete();
- }
- }
-
- @Override
- public synchronized void unpin(List<MusicDirectory.Entry> songs) {
- for (MusicDirectory.Entry song : songs) {
- forSong(song).unpin();
- }
- }
-
- synchronized void setCurrentPlaying(int currentPlayingIndex, boolean showNotification) {
- try {
- setCurrentPlaying(downloadList.get(currentPlayingIndex), showNotification);
- } catch (IndexOutOfBoundsException x) {
- // Ignored
- }
- }
-
- synchronized void setCurrentPlaying(DownloadFile currentPlaying, boolean showNotification) {
- this.currentPlaying = currentPlaying;
-
- if (currentPlaying != null) {
- Util.broadcastNewTrackInfo(this, currentPlaying.getSong());
- } else {
- Util.broadcastNewTrackInfo(this, null);
- }
-
- if (currentPlaying != null && showNotification) {
- Util.showPlayingNotification(this, this, handler, currentPlaying.getSong());
- } else {
- Util.hidePlayingNotification(this, this, handler);
- }
- }
-
- @Override
- public synchronized int getCurrentPlayingIndex() {
- return downloadList.indexOf(currentPlaying);
- }
-
- @Override
- public DownloadFile getCurrentPlaying() {
- return currentPlaying;
- }
-
- @Override
- public DownloadFile getCurrentDownloading() {
- return currentDownloading;
- }
-
- @Override
- public synchronized List<DownloadFile> getDownloads() {
- return new ArrayList<DownloadFile>(downloadList);
- }
-
- /** Plays either the current song (resume) or the first/next one in queue. */
- public synchronized void play()
- {
- int current = getCurrentPlayingIndex();
- if (current == -1) {
- play(0);
- } else {
- play(current);
- }
- }
-
- @Override
- public synchronized void play(int index) {
- play(index, true);
- }
-
- private synchronized void play(int index, boolean start) {
- if (index < 0 || index >= size()) {
- reset();
- setCurrentPlaying(null, false);
- } else {
- setCurrentPlaying(index, start);
- checkDownloads();
- if (start) {
- if (jukeboxEnabled) {
- jukeboxService.skip(getCurrentPlayingIndex(), 0);
- setPlayerState(STARTED);
- } else {
- bufferAndPlay();
- }
- }
- }
- }
-
- /** Plays or resumes the playback, depending on the current player state. */
- public synchronized void togglePlayPause()
- {
- if (playerState == PAUSED || playerState == COMPLETED) {
- start();
- } else if (playerState == STOPPED || playerState == IDLE) {
- play();
- } else if (playerState == STARTED) {
- pause();
- }
- }
-
- @Override
- public synchronized void seekTo(int position) {
- try {
- if (jukeboxEnabled) {
- jukeboxService.skip(getCurrentPlayingIndex(), position / 1000);
- } else {
- mediaPlayer.seekTo(position);
- }
- } catch (Exception x) {
- handleError(x);
- }
- }
-
- @Override
- public synchronized void previous() {
- int index = getCurrentPlayingIndex();
- if (index == -1) {
- return;
- }
-
- // Restart song if played more than five seconds.
- if (getPlayerPosition() > 5000 || index == 0) {
- play(index);
- } else {
- play(index - 1);
- }
- }
-
- @Override
- public synchronized void next() {
- int index = getCurrentPlayingIndex();
- if (index != -1) {
- play(index + 1);
- }
- }
-
- private void onSongCompleted() {
- int index = getCurrentPlayingIndex();
- if (index != -1) {
- switch (getRepeatMode()) {
- case OFF:
- play(index + 1);
- break;
- case ALL:
- play((index + 1) % size());
- break;
- case SINGLE:
- play(index);
- break;
- default:
- break;
- }
- }
- }
-
- @Override
- public synchronized void pause() {
- try {
- if (playerState == STARTED) {
- if (jukeboxEnabled) {
- jukeboxService.stop();
- } else {
- mediaPlayer.pause();
- }
- setPlayerState(PAUSED);
- }
- } catch (Exception x) {
- handleError(x);
- }
- }
-
- @Override
- public synchronized void start() {
- try {
- if (jukeboxEnabled) {
- jukeboxService.start();
- } else {
- mediaPlayer.start();
- }
- setPlayerState(STARTED);
- } catch (Exception x) {
- handleError(x);
- }
- }
-
- @Override
- public synchronized void reset() {
- if (bufferTask != null) {
- bufferTask.cancel();
- }
- try {
- mediaPlayer.reset();
- setPlayerState(IDLE);
- } catch (Exception x) {
- handleError(x);
- }
- }
-
- @Override
- public synchronized int getPlayerPosition() {
- try {
- if (playerState == IDLE || playerState == DOWNLOADING || playerState == PREPARING) {
- return 0;
- }
- if (jukeboxEnabled) {
- return jukeboxService.getPositionSeconds() * 1000;
- } else {
- return mediaPlayer.getCurrentPosition();
- }
- } catch (Exception x) {
- handleError(x);
- return 0;
- }
- }
-
- @Override
- public synchronized int getPlayerDuration() {
- if (currentPlaying != null) {
- Integer duration = currentPlaying.getSong().getDuration();
- if (duration != null) {
- return duration * 1000;
- }
- }
- if (playerState != IDLE && playerState != DOWNLOADING && playerState != PlayerState.PREPARING) {
- try {
- return mediaPlayer.getDuration();
- } catch (Exception x) {
- handleError(x);
- }
- }
- return 0;
- }
-
- @Override
- public PlayerState getPlayerState() {
- return playerState;
- }
-
- synchronized void setPlayerState(PlayerState playerState) {
- Log.i(TAG, this.playerState.name() + " -> " + playerState.name() + " (" + currentPlaying + ")");
-
- if (playerState == PAUSED) {
- lifecycleSupport.serializeDownloadQueue();
- }
-
- boolean show = this.playerState == PAUSED && playerState == PlayerState.STARTED;
- boolean hide = this.playerState == STARTED && playerState == PlayerState.PAUSED;
- Util.broadcastPlaybackStatusChange(this, playerState);
-
- this.playerState = playerState;
- if (show) {
- Util.showPlayingNotification(this, this, handler, currentPlaying.getSong());
- } else if (hide) {
- Util.hidePlayingNotification(this, this, handler);
- }
-
- if (playerState == STARTED) {
- scrobbler.scrobble(this, currentPlaying, false);
- } else if (playerState == COMPLETED) {
- scrobbler.scrobble(this, currentPlaying, true);
- }
- }
-
- @Override
- public void setSuggestedPlaylistName(String name) {
- this.suggestedPlaylistName = name;
- }
-
- @Override
- public String getSuggestedPlaylistName() {
- return suggestedPlaylistName;
- }
-
- @Override
- public EqualizerController getEqualizerController() {
- return equalizerController;
- }
-
- @Override
- public VisualizerController getVisualizerController() {
- return visualizerController;
- }
-
- @Override
- public boolean isJukeboxEnabled() {
- return jukeboxEnabled;
- }
-
- @Override
- public void setJukeboxEnabled(boolean jukeboxEnabled) {
- this.jukeboxEnabled = jukeboxEnabled;
- jukeboxService.setEnabled(jukeboxEnabled);
- if (jukeboxEnabled) {
- reset();
-
- // Cancel current download, if necessary.
- if (currentDownloading != null) {
- currentDownloading.cancelDownload();
- }
- }
- }
-
- @Override
- public void adjustJukeboxVolume(boolean up) {
- jukeboxService.adjustVolume(up);
- }
-
- private synchronized void bufferAndPlay() {
- reset();
-
- bufferTask = new BufferTask(currentPlaying, 0);
- bufferTask.start();
- }
-
- private synchronized void doPlay(final DownloadFile downloadFile, int position, boolean start) {
- try {
- final File file = downloadFile.isCompleteFileAvailable() ? downloadFile.getCompleteFile() : downloadFile.getPartialFile();
- downloadFile.updateModificationDate();
- mediaPlayer.setOnCompletionListener(null);
- mediaPlayer.reset();
- setPlayerState(IDLE);
- mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
- mediaPlayer.setDataSource(file.getPath());
- setPlayerState(PREPARING);
- mediaPlayer.prepare();
- setPlayerState(PREPARED);
-
- mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
- @Override
- public void onCompletion(MediaPlayer mediaPlayer) {
-
- // Acquire a temporary wakelock, since when we return from
- // this callback the MediaPlayer will release its wakelock
- // and allow the device to go to sleep.
- wakeLock.acquire(60000);
-
- setPlayerState(COMPLETED);
-
- // If COMPLETED and not playing partial file, we are *really" finished
- // with the song and can move on to the next.
- if (!file.equals(downloadFile.getPartialFile())) {
- onSongCompleted();
- return;
- }
-
- // If file is not completely downloaded, restart the playback from the current position.
- int pos = mediaPlayer.getCurrentPosition();
- synchronized (DownloadServiceImpl.this) {
-
- // Work-around for apparent bug on certain phones: If close (less than ten seconds) to the end
- // of the song, skip to the next rather than restarting it.
- Integer duration = downloadFile.getSong().getDuration() == null ? null : downloadFile.getSong().getDuration() * 1000;
- if (duration != null) {
- if (Math.abs(duration - pos) < 10000) {
- Log.i(TAG, "Skipping restart from " + pos + " of " + duration);
- onSongCompleted();
- return;
- }
- }
-
- Log.i(TAG, "Requesting restart from " + pos + " of " + duration);
- reset();
- bufferTask = new BufferTask(downloadFile, pos);
- bufferTask.start();
- }
- }
- });
-
- if (position != 0) {
- Log.i(TAG, "Restarting player from position " + position);
- mediaPlayer.seekTo(position);
- }
-
- if (start) {
- mediaPlayer.start();
- setPlayerState(STARTED);
- } else {
- setPlayerState(PAUSED);
- }
- lifecycleSupport.serializeDownloadQueue();
-
- } catch (Exception x) {
- handleError(x);
- }
- }
-
- private void handleError(Exception x) {
- Log.w(TAG, "Media player error: " + x, x);
- mediaPlayer.reset();
- setPlayerState(IDLE);
- }
-
- protected synchronized void checkDownloads() {
-
- if (!Util.isExternalStoragePresent() || !lifecycleSupport.isExternalStorageAvailable()) {
- return;
- }
-
- if (shufflePlay) {
- checkShufflePlay();
- }
-
- if (jukeboxEnabled || !Util.isNetworkConnected(this)) {
- return;
- }
-
- if (downloadList.isEmpty()) {
- return;
- }
-
- // Need to download current playing?
- if (currentPlaying != null &&
- currentPlaying != currentDownloading &&
- !currentPlaying.isCompleteFileAvailable()) {
-
- // Cancel current download, if necessary.
- if (currentDownloading != null) {
- currentDownloading.cancelDownload();
- }
-
- currentDownloading = currentPlaying;
- currentDownloading.download();
- cleanupCandidates.add(currentDownloading);
- }
-
- // Find a suitable target for download.
- else if (currentDownloading == null || currentDownloading.isWorkDone() || currentDownloading.isFailed()) {
-
- int n = size();
- if (n == 0) {
- return;
- }
-
- int preloaded = 0;
-
- int start = currentPlaying == null ? 0 : getCurrentPlayingIndex();
- int i = start;
- do {
- DownloadFile downloadFile = downloadList.get(i);
- if (!downloadFile.isWorkDone()) {
- if (downloadFile.shouldSave() || preloaded < Util.getPreloadCount(this)) {
- currentDownloading = downloadFile;
- currentDownloading.download();
- cleanupCandidates.add(currentDownloading);
- break;
- }
- } else if (currentPlaying != downloadFile) {
- preloaded++;
- }
-
- i = (i + 1) % n;
- } while (i != start);
- }
-
- // Delete obsolete .partial and .complete files.
- cleanup();
- }
-
- private synchronized void checkShufflePlay() {
-
- final int listSize = 20;
- boolean wasEmpty = downloadList.isEmpty();
-
- long revisionBefore = revision;
-
- // First, ensure that list is at least 20 songs long.
- int size = size();
- if (size < listSize) {
- for (MusicDirectory.Entry song : shufflePlayBuffer.get(listSize - size)) {
- DownloadFile downloadFile = new DownloadFile(this, song, false);
- downloadList.add(downloadFile);
- revision++;
- }
- }
-
- int currIndex = 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(this, song, false));
- downloadList.get(0).cancelDownload();
- downloadList.remove(0);
- revision++;
- }
- }
-
- if (revisionBefore != revision) {
- updateJukeboxPlaylist();
- }
-
- if (wasEmpty && !downloadList.isEmpty()) {
- play(0);
- }
- }
-
- public long getDownloadListUpdateRevision() {
- return revision;
- }
-
- private synchronized void cleanup() {
- Iterator<DownloadFile> iterator = cleanupCandidates.iterator();
- while (iterator.hasNext()) {
- DownloadFile downloadFile = iterator.next();
- if (downloadFile != currentPlaying && downloadFile != currentDownloading) {
- if (downloadFile.cleanup()) {
- iterator.remove();
- }
- }
- }
- }
-
- private class BufferTask extends CancellableTask {
-
- private static final int BUFFER_LENGTH_SECONDS = 5;
-
- private final DownloadFile downloadFile;
- private final int position;
- private final long expectedFileSize;
- private final File partialFile;
-
- public BufferTask(DownloadFile downloadFile, int position) {
- this.downloadFile = downloadFile;
- this.position = position;
- partialFile = downloadFile.getPartialFile();
-
- // Calculate roughly how many bytes BUFFER_LENGTH_SECONDS corresponds to.
- int bitRate = downloadFile.getBitRate();
- long byteCount = Math.max(100000, bitRate * 1024 / 8 * BUFFER_LENGTH_SECONDS);
-
- // Find out how large the file should grow before resuming playback.
- expectedFileSize = partialFile.length() + byteCount;
- }
-
- @Override
- public void execute() {
- setPlayerState(DOWNLOADING);
-
- while (!bufferComplete()) {
- Util.sleepQuietly(1000L);
- if (isCancelled()) {
- return;
- }
- }
- doPlay(downloadFile, position, true);
- }
-
- private boolean bufferComplete() {
- boolean completeFileAvailable = downloadFile.isCompleteFileAvailable();
- long size = partialFile.length();
-
- Log.i(TAG, "Buffering " + partialFile + " (" + size + "/" + expectedFileSize + ", " + completeFileAvailable + ")");
- return completeFileAvailable || size >= expectedFileSize;
- }
-
- @Override
- public String toString() {
- return "BufferTask (" + downloadFile + ")";
- }
- }
-}
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/DownloadServiceLifecycleSupport.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/DownloadServiceLifecycleSupport.java
deleted file mode 100644
index f6076059..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/DownloadServiceLifecycleSupport.java
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.telephony.PhoneStateListener;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-import android.view.KeyEvent;
-import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
-import net.sourceforge.subsonic.androidapp.domain.PlayerState;
-import net.sourceforge.subsonic.androidapp.util.CacheCleaner;
-import net.sourceforge.subsonic.androidapp.util.FileUtil;
-import net.sourceforge.subsonic.androidapp.util.Util;
-
-/**
- * @author Sindre Mehus
- */
-public class DownloadServiceLifecycleSupport {
-
- private static final String TAG = DownloadServiceLifecycleSupport.class.getSimpleName();
- private static final String FILENAME_DOWNLOADS_SER = "downloadstate.ser";
-
- private final DownloadServiceImpl downloadService;
- private ScheduledExecutorService executorService;
- private BroadcastReceiver headsetEventReceiver;
- private BroadcastReceiver ejectEventReceiver;
- private PhoneStateListener phoneStateListener;
- private boolean externalStorageAvailable= true;
-
- /**
- * This receiver manages the intent that could come from other applications.
- */
- private BroadcastReceiver intentReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- Log.i(TAG, "intentReceiver.onReceive: " + action);
- if (DownloadServiceImpl.CMD_PLAY.equals(action)) {
- downloadService.play();
- } else if (DownloadServiceImpl.CMD_NEXT.equals(action)) {
- downloadService.next();
- } else if (DownloadServiceImpl.CMD_PREVIOUS.equals(action)) {
- downloadService.previous();
- } else if (DownloadServiceImpl.CMD_TOGGLEPAUSE.equals(action)) {
- downloadService.togglePlayPause();
- } else if (DownloadServiceImpl.CMD_PAUSE.equals(action)) {
- downloadService.pause();
- } else if (DownloadServiceImpl.CMD_STOP.equals(action)) {
- downloadService.pause();
- downloadService.seekTo(0);
- }
- }
- };
-
-
- public DownloadServiceLifecycleSupport(DownloadServiceImpl downloadService) {
- this.downloadService = downloadService;
- }
-
- public void onCreate() {
- Runnable downloadChecker = new Runnable() {
- @Override
- public void run() {
- try {
- downloadService.checkDownloads();
- } catch (Throwable x) {
- Log.e(TAG, "checkDownloads() failed.", x);
- }
- }
- };
-
- executorService = Executors.newScheduledThreadPool(2);
- executorService.scheduleWithFixedDelay(downloadChecker, 5, 5, TimeUnit.SECONDS);
-
- // Pause when headset is unplugged.
- headsetEventReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.i(TAG, "Headset event for: " + intent.getExtras().get("name"));
- if (intent.getExtras().getInt("state") == 0) {
- downloadService.pause();
- }
- }
- };
- downloadService.registerReceiver(headsetEventReceiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
-
- // Stop when SD card is ejected.
- ejectEventReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- externalStorageAvailable = Intent.ACTION_MEDIA_MOUNTED.equals(intent.getAction());
- if (!externalStorageAvailable) {
- Log.i(TAG, "External media is ejecting. Stopping playback.");
- downloadService.reset();
- } else {
- Log.i(TAG, "External media is available.");
- }
- }
- };
- IntentFilter ejectFilter = new IntentFilter(Intent.ACTION_MEDIA_EJECT);
- ejectFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
- ejectFilter.addDataScheme("file");
- downloadService.registerReceiver(ejectEventReceiver, ejectFilter);
-
- // React to media buttons.
- Util.registerMediaButtonEventReceiver(downloadService);
-
- // Pause temporarily on incoming phone calls.
- phoneStateListener = new MyPhoneStateListener();
- TelephonyManager telephonyManager = (TelephonyManager) downloadService.getSystemService(Context.TELEPHONY_SERVICE);
- telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
-
- // Register the handler for outside intents.
- IntentFilter commandFilter = new IntentFilter();
- commandFilter.addAction(DownloadServiceImpl.CMD_PLAY);
- commandFilter.addAction(DownloadServiceImpl.CMD_TOGGLEPAUSE);
- commandFilter.addAction(DownloadServiceImpl.CMD_PAUSE);
- commandFilter.addAction(DownloadServiceImpl.CMD_STOP);
- commandFilter.addAction(DownloadServiceImpl.CMD_PREVIOUS);
- commandFilter.addAction(DownloadServiceImpl.CMD_NEXT);
- downloadService.registerReceiver(intentReceiver, commandFilter);
-
- deserializeDownloadQueue();
-
- new CacheCleaner(downloadService, downloadService).clean();
- }
-
- public void onStart(Intent intent) {
- if (intent != null && intent.getExtras() != null) {
- KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
- if (event != null) {
- handleKeyEvent(event);
- }
- }
- }
-
- public void onDestroy() {
- executorService.shutdown();
- serializeDownloadQueue();
- downloadService.clear(false);
- downloadService.unregisterReceiver(ejectEventReceiver);
- downloadService.unregisterReceiver(headsetEventReceiver);
- downloadService.unregisterReceiver(intentReceiver);
-
- TelephonyManager telephonyManager = (TelephonyManager) downloadService.getSystemService(Context.TELEPHONY_SERVICE);
- telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
- }
-
- public boolean isExternalStorageAvailable() {
- return externalStorageAvailable;
- }
-
- public void serializeDownloadQueue() {
- State state = new State();
- for (DownloadFile downloadFile : downloadService.getDownloads()) {
- state.songs.add(downloadFile.getSong());
- }
- state.currentPlayingIndex = downloadService.getCurrentPlayingIndex();
- state.currentPlayingPosition = downloadService.getPlayerPosition();
-
- Log.i(TAG, "Serialized currentPlayingIndex: " + state.currentPlayingIndex + ", currentPlayingPosition: " + state.currentPlayingPosition);
- FileUtil.serialize(downloadService, state, FILENAME_DOWNLOADS_SER);
- }
-
- private void deserializeDownloadQueue() {
- State state = FileUtil.deserialize(downloadService, FILENAME_DOWNLOADS_SER);
- if (state == null) {
- return;
- }
- Log.i(TAG, "Deserialized currentPlayingIndex: " + state.currentPlayingIndex + ", currentPlayingPosition: " + state.currentPlayingPosition);
- downloadService.restore(state.songs, state.currentPlayingIndex, state.currentPlayingPosition);
-
- // Work-around: Serialize again, as the restore() method creates a serialization without current playing info.
- serializeDownloadQueue();
- }
-
- private void handleKeyEvent(KeyEvent event) {
- if (event.getAction() != KeyEvent.ACTION_DOWN || event.getRepeatCount() > 0) {
- return;
- }
-
- switch (event.getKeyCode()) {
- case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
- case KeyEvent.KEYCODE_HEADSETHOOK:
- downloadService.togglePlayPause();
- break;
- case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
- downloadService.previous();
- break;
- case KeyEvent.KEYCODE_MEDIA_NEXT:
- if (downloadService.getCurrentPlayingIndex() < downloadService.size() - 1) {
- downloadService.next();
- }
- break;
- case KeyEvent.KEYCODE_MEDIA_STOP:
- downloadService.reset();
- break;
- case KeyEvent.KEYCODE_MEDIA_PLAY:
- downloadService.start();
- break;
- case KeyEvent.KEYCODE_MEDIA_PAUSE:
- downloadService.pause();
- default:
- break;
- }
- }
-
- /**
- * Logic taken from packages/apps/Music. Will pause when an incoming
- * call rings or if a call (incoming or outgoing) is connected.
- */
- private class MyPhoneStateListener extends PhoneStateListener {
- private boolean resumeAfterCall;
-
- @Override
- public void onCallStateChanged(int state, String incomingNumber) {
- switch (state) {
- case TelephonyManager.CALL_STATE_RINGING:
- case TelephonyManager.CALL_STATE_OFFHOOK:
- if (downloadService.getPlayerState() == PlayerState.STARTED) {
- resumeAfterCall = true;
- downloadService.pause();
- }
- break;
- case TelephonyManager.CALL_STATE_IDLE:
- if (resumeAfterCall) {
- resumeAfterCall = false;
- downloadService.start();
- }
- break;
- default:
- break;
- }
- }
- }
-
- private static class State implements Serializable {
- private static final long serialVersionUID = -6346438781062572270L;
-
- private List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>();
- private int currentPlayingIndex;
- private int currentPlayingPosition;
- }
-} \ No newline at end of file
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/JukeboxService.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/JukeboxService.java
deleted file mode 100644
index e3145f4e..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/JukeboxService.java
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service;
-
-import android.content.Context;
-import android.os.Handler;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ProgressBar;
-import android.widget.Toast;
-import net.sourceforge.subsonic.androidapp.R;
-import net.sourceforge.subsonic.androidapp.domain.JukeboxStatus;
-import net.sourceforge.subsonic.androidapp.domain.PlayerState;
-import net.sourceforge.subsonic.androidapp.service.parser.SubsonicRESTException;
-import net.sourceforge.subsonic.androidapp.util.Util;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * Provides an asynchronous interface to the remote jukebox on the Subsonic server.
- *
- * @author Sindre Mehus
- * @version $Id$
- */
-public class JukeboxService {
-
- private static final String TAG = JukeboxService.class.getSimpleName();
- private static final long STATUS_UPDATE_INTERVAL_SECONDS = 5L;
-
- private final Handler handler = new Handler();
- private final TaskQueue tasks = new TaskQueue();
- private final DownloadServiceImpl downloadService;
- private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
- private ScheduledFuture<?> statusUpdateFuture;
- private final AtomicLong timeOfLastUpdate = new AtomicLong();
- private JukeboxStatus jukeboxStatus;
- private float gain = 0.5f;
- private VolumeToast volumeToast;
-
- // TODO: Report warning if queue fills up.
- // TODO: Create shutdown method?
- // TODO: Disable repeat.
- // TODO: Persist RC state?
- // TODO: Minimize status updates.
-
- public JukeboxService(DownloadServiceImpl downloadService) {
- this.downloadService = downloadService;
- new Thread() {
- @Override
- public void run() {
- processTasks();
- }
- }.start();
- }
-
- private synchronized void startStatusUpdate() {
- stopStatusUpdate();
- Runnable updateTask = new Runnable() {
- @Override
- public void run() {
- tasks.remove(GetStatus.class);
- tasks.add(new GetStatus());
- }
- };
- statusUpdateFuture = executorService.scheduleWithFixedDelay(updateTask, STATUS_UPDATE_INTERVAL_SECONDS,
- STATUS_UPDATE_INTERVAL_SECONDS, TimeUnit.SECONDS);
- }
-
- private synchronized void stopStatusUpdate() {
- if (statusUpdateFuture != null) {
- statusUpdateFuture.cancel(false);
- statusUpdateFuture = null;
- }
- }
-
- private void processTasks() {
- while (true) {
- JukeboxTask task = null;
- try {
- task = tasks.take();
- JukeboxStatus status = task.execute();
- onStatusUpdate(status);
- } catch (Throwable x) {
- onError(task, x);
- }
- }
- }
-
- private void onStatusUpdate(JukeboxStatus jukeboxStatus) {
- timeOfLastUpdate.set(System.currentTimeMillis());
- this.jukeboxStatus = jukeboxStatus;
-
- // Track change?
- Integer index = jukeboxStatus.getCurrentPlayingIndex();
- if (index != null && index != -1 && index != downloadService.getCurrentPlayingIndex()) {
- downloadService.setCurrentPlaying(index, true);
- }
- }
-
- private void onError(JukeboxTask task, Throwable x) {
- if (x instanceof ServerTooOldException && !(task instanceof Stop)) {
- disableJukeboxOnError(x, R.string.download_jukebox_server_too_old);
- } else if (x instanceof OfflineException && !(task instanceof Stop)) {
- disableJukeboxOnError(x, R.string.download_jukebox_offline);
- } else if (x instanceof SubsonicRESTException && ((SubsonicRESTException) x).getCode() == 50 && !(task instanceof Stop)) {
- disableJukeboxOnError(x, R.string.download_jukebox_not_authorized);
- } else {
- Log.e(TAG, "Failed to process jukebox task: " + x, x);
- }
- }
-
- private void disableJukeboxOnError(Throwable x, final int resourceId) {
- Log.w(TAG, x.toString());
- handler.post(new Runnable() {
- @Override
- public void run() {
- Util.toast(downloadService, resourceId, false);
- }
- });
- downloadService.setJukeboxEnabled(false);
- }
-
- public void updatePlaylist() {
- tasks.remove(Skip.class);
- tasks.remove(Stop.class);
- tasks.remove(Start.class);
-
- List<String> ids = new ArrayList<String>();
- for (DownloadFile file : downloadService.getDownloads()) {
- ids.add(file.getSong().getId());
- }
- tasks.add(new SetPlaylist(ids));
- }
-
- public void skip(final int index, final int offsetSeconds) {
- tasks.remove(Skip.class);
- tasks.remove(Stop.class);
- tasks.remove(Start.class);
-
- startStatusUpdate();
- if (jukeboxStatus != null) {
- jukeboxStatus.setPositionSeconds(offsetSeconds);
- }
- tasks.add(new Skip(index, offsetSeconds));
- downloadService.setPlayerState(PlayerState.STARTED);
- }
-
- public void stop() {
- tasks.remove(Stop.class);
- tasks.remove(Start.class);
-
- stopStatusUpdate();
- tasks.add(new Stop());
- }
-
- public void start() {
- tasks.remove(Stop.class);
- tasks.remove(Start.class);
-
- startStatusUpdate();
- tasks.add(new Start());
- }
-
- public synchronized void adjustVolume(boolean up) {
- float delta = up ? 0.1f : -0.1f;
- gain += delta;
- gain = Math.max(gain, 0.0f);
- gain = Math.min(gain, 1.0f);
-
- tasks.remove(SetGain.class);
- tasks.add(new SetGain(gain));
-
- if (volumeToast == null) {
- volumeToast = new VolumeToast(downloadService);
- }
- volumeToast.setVolume(gain);
- }
-
- private MusicService getMusicService() {
- return MusicServiceFactory.getMusicService(downloadService);
- }
-
- public int getPositionSeconds() {
- if (jukeboxStatus == null || jukeboxStatus.getPositionSeconds() == null || timeOfLastUpdate.get() == 0) {
- return 0;
- }
-
- if (jukeboxStatus.isPlaying()) {
- int secondsSinceLastUpdate = (int) ((System.currentTimeMillis() - timeOfLastUpdate.get()) / 1000L);
- return jukeboxStatus.getPositionSeconds() + secondsSinceLastUpdate;
- }
-
- return jukeboxStatus.getPositionSeconds();
- }
-
- public void setEnabled(boolean enabled) {
- tasks.clear();
- if (enabled) {
- updatePlaylist();
- }
- stop();
- downloadService.setPlayerState(PlayerState.IDLE);
- }
-
- private static class TaskQueue {
-
- private final LinkedBlockingQueue<JukeboxTask> queue = new LinkedBlockingQueue<JukeboxTask>();
-
- void add(JukeboxTask jukeboxTask) {
- queue.add(jukeboxTask);
- }
-
- JukeboxTask take() throws InterruptedException {
- return queue.take();
- }
-
- void remove(Class<? extends JukeboxTask> clazz) {
- try {
- Iterator<JukeboxTask> iterator = queue.iterator();
- while (iterator.hasNext()) {
- JukeboxTask 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();
- }
- }
-
- private abstract class JukeboxTask {
-
- abstract JukeboxStatus execute() throws Exception;
-
- @Override
- public String toString() {
- return getClass().getSimpleName();
- }
- }
-
- private class GetStatus extends JukeboxTask {
- @Override
- JukeboxStatus execute() throws Exception {
- return getMusicService().getJukeboxStatus(downloadService, null);
- }
- }
-
- private class SetPlaylist extends JukeboxTask {
-
- private final List<String> ids;
-
- SetPlaylist(List<String> ids) {
- this.ids = ids;
- }
-
- @Override
- JukeboxStatus execute() throws Exception {
- return getMusicService().updateJukeboxPlaylist(ids, downloadService, null);
- }
- }
-
- private class Skip extends JukeboxTask {
- private final int index;
- private final int offsetSeconds;
-
- Skip(int index, int offsetSeconds) {
- this.index = index;
- this.offsetSeconds = offsetSeconds;
- }
-
- @Override
- JukeboxStatus execute() throws Exception {
- return getMusicService().skipJukebox(index, offsetSeconds, downloadService, null);
- }
- }
-
- private class Stop extends JukeboxTask {
- @Override
- JukeboxStatus execute() throws Exception {
- return getMusicService().stopJukebox(downloadService, null);
- }
- }
-
- private class Start extends JukeboxTask {
- @Override
- JukeboxStatus execute() throws Exception {
- return getMusicService().startJukebox(downloadService, null);
- }
- }
-
- private class SetGain extends JukeboxTask {
-
- private final float gain;
-
- private SetGain(float gain) {
- this.gain = gain;
- }
-
- @Override
- JukeboxStatus execute() throws Exception {
- return getMusicService().setJukeboxGain(gain, downloadService, null);
- }
- }
-
- private static class VolumeToast extends Toast {
-
- private final ProgressBar progressBar;
-
- public VolumeToast(Context context) {
- super(context);
- setDuration(Toast.LENGTH_SHORT);
- LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View view = inflater.inflate(R.layout.jukebox_volume, null);
- progressBar = (ProgressBar) view.findViewById(R.id.jukebox_volume_progress_bar);
-
- setView(view);
- setGravity(Gravity.TOP, 0, 0);
- }
-
- public void setVolume(float volume) {
- progressBar.setProgress(Math.round(100 * volume));
- show();
- }
- }
-}
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/MediaStoreService.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/MediaStoreService.java
deleted file mode 100644
index 775fa3f5..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/MediaStoreService.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service;
-
-import java.io.File;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.MediaStore;
-import android.util.Log;
-import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
-import net.sourceforge.subsonic.androidapp.util.FileUtil;
-
-/**
- * @author Sindre Mehus
- */
-public class MediaStoreService {
-
- private static final String TAG = MediaStoreService.class.getSimpleName();
- private static final Uri ALBUM_ART_URI = Uri.parse("content://media/external/audio/albumart");
-
- private final Context context;
-
- public MediaStoreService(Context context) {
- this.context = context;
- }
-
- public void saveInMediaStore(DownloadFile downloadFile) {
- MusicDirectory.Entry song = downloadFile.getSong();
- File songFile = downloadFile.getCompleteFile();
-
- // Delete existing row in case the song has been downloaded before.
- deleteFromMediaStore(downloadFile);
-
- ContentResolver contentResolver = context.getContentResolver();
- ContentValues values = new ContentValues();
- values.put(MediaStore.MediaColumns.TITLE, song.getTitle());
- values.put(MediaStore.Audio.AudioColumns.ARTIST, song.getArtist());
- values.put(MediaStore.Audio.AudioColumns.ALBUM, song.getAlbum());
- values.put(MediaStore.Audio.AudioColumns.TRACK, song.getTrack());
- values.put(MediaStore.Audio.AudioColumns.YEAR, song.getYear());
- values.put(MediaStore.MediaColumns.DATA, songFile.getAbsolutePath());
- values.put(MediaStore.MediaColumns.MIME_TYPE, song.getContentType());
- values.put(MediaStore.Audio.AudioColumns.IS_MUSIC, 1);
-
- Uri uri = contentResolver.insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values);
-
- // Look up album, and add cover art if found.
- Cursor cursor = contentResolver.query(uri, new String[]{MediaStore.Audio.AudioColumns.ALBUM_ID}, null, null, null);
- if (cursor.moveToFirst()) {
- int albumId = cursor.getInt(0);
- insertAlbumArt(albumId, downloadFile);
- }
- cursor.close();
- }
-
- public void deleteFromMediaStore(DownloadFile downloadFile) {
- ContentResolver contentResolver = context.getContentResolver();
- MusicDirectory.Entry song = downloadFile.getSong();
- File file = downloadFile.getCompleteFile();
-
- int n = contentResolver.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
- MediaStore.Audio.AudioColumns.TITLE_KEY + "=? AND " +
- MediaStore.MediaColumns.DATA + "=?",
- new String[]{MediaStore.Audio.keyFor(song.getTitle()), file.getAbsolutePath()});
- if (n > 0) {
- Log.i(TAG, "Deleting media store row for " + song);
- }
- }
-
- private void insertAlbumArt(int albumId, DownloadFile downloadFile) {
- ContentResolver contentResolver = context.getContentResolver();
-
- Cursor cursor = contentResolver.query(Uri.withAppendedPath(ALBUM_ART_URI, String.valueOf(albumId)), null, null, null, null);
- if (!cursor.moveToFirst()) {
-
- // No album art found, add it.
- File albumArtFile = FileUtil.getAlbumArtFile(context, downloadFile.getSong());
- if (albumArtFile.exists()) {
- ContentValues values = new ContentValues();
- values.put(MediaStore.Audio.AlbumColumns.ALBUM_ID, albumId);
- values.put(MediaStore.MediaColumns.DATA, albumArtFile.getPath());
- contentResolver.insert(ALBUM_ART_URI, values);
- Log.i(TAG, "Added album art: " + albumArtFile);
- }
- }
- cursor.close();
- }
-
-} \ No newline at end of file
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/MusicService.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/MusicService.java
deleted file mode 100644
index cb0c5709..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/MusicService.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service;
-
-import java.util.List;
-
-import org.apache.http.HttpResponse;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import net.sourceforge.subsonic.androidapp.domain.Indexes;
-import net.sourceforge.subsonic.androidapp.domain.JukeboxStatus;
-import net.sourceforge.subsonic.androidapp.domain.Lyrics;
-import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
-import net.sourceforge.subsonic.androidapp.domain.MusicFolder;
-import net.sourceforge.subsonic.androidapp.domain.Playlist;
-import net.sourceforge.subsonic.androidapp.domain.SearchCritera;
-import net.sourceforge.subsonic.androidapp.domain.SearchResult;
-import net.sourceforge.subsonic.androidapp.domain.Version;
-import net.sourceforge.subsonic.androidapp.util.CancellableTask;
-import net.sourceforge.subsonic.androidapp.util.ProgressListener;
-
-/**
- * @author Sindre Mehus
- */
-public interface MusicService {
-
- void ping(Context context, ProgressListener progressListener) throws Exception;
-
- boolean isLicenseValid(Context context, ProgressListener progressListener) throws Exception;
-
- List<MusicFolder> getMusicFolders(boolean refresh, Context context, ProgressListener progressListener) throws Exception;
-
- Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
-
- MusicDirectory getMusicDirectory(String id, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
-
- SearchResult search(SearchCritera criteria, Context context, ProgressListener progressListener) throws Exception;
-
- MusicDirectory getPlaylist(String id, String name, Context context, ProgressListener progressListener) throws Exception;
-
- List<Playlist> getPlaylists(boolean refresh, Context context, ProgressListener progressListener) throws Exception;
-
- void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries, Context context, ProgressListener progressListener) throws Exception;
-
- Lyrics getLyrics(String artist, String title, Context context, ProgressListener progressListener) throws Exception;
-
- void scrobble(String id, boolean submission, Context context, ProgressListener progressListener) throws Exception;
-
- MusicDirectory getAlbumList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception;
-
- MusicDirectory getRandomSongs(int size, Context context, ProgressListener progressListener) throws Exception;
-
- Bitmap getCoverArt(Context context, MusicDirectory.Entry entry, int size, boolean saveToFile, ProgressListener progressListener) throws Exception;
-
- HttpResponse getDownloadInputStream(Context context, MusicDirectory.Entry song, long offset, int maxBitrate, CancellableTask task) throws Exception;
-
- Version getLocalVersion(Context context) throws Exception;
-
- Version getLatestVersion(Context context, ProgressListener progressListener) throws Exception;
-
- String getVideoUrl(Context context, String id);
-
- JukeboxStatus updateJukeboxPlaylist(List<String> ids, Context context, ProgressListener progressListener) throws Exception;
-
- JukeboxStatus skipJukebox(int index, int offsetSeconds, Context context, ProgressListener progressListener) throws Exception;
-
- JukeboxStatus stopJukebox(Context context, ProgressListener progressListener) throws Exception;
-
- JukeboxStatus startJukebox(Context context, ProgressListener progressListener) throws Exception;
-
- JukeboxStatus getJukeboxStatus(Context context, ProgressListener progressListener) throws Exception;
-
- JukeboxStatus setJukeboxGain(float gain, Context context, ProgressListener progressListener) throws Exception;
-} \ No newline at end of file
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/MusicServiceFactory.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/MusicServiceFactory.java
deleted file mode 100644
index 552d1d32..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/MusicServiceFactory.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service;
-
-import android.content.Context;
-import net.sourceforge.subsonic.androidapp.util.Util;
-
-/**
- * @author Sindre Mehus
- * @version $Id$
- */
-public class MusicServiceFactory {
-
- private static final MusicService REST_MUSIC_SERVICE = new CachedMusicService(new RESTMusicService());
- private static final MusicService OFFLINE_MUSIC_SERVICE = new OfflineMusicService();
-
- public static MusicService getMusicService(Context context) {
- return Util.isOffline(context) ? OFFLINE_MUSIC_SERVICE : REST_MUSIC_SERVICE;
- }
-}
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/OfflineException.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/OfflineException.java
deleted file mode 100644
index 49c000bf..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/OfflineException.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service;
-
-/**
- * Thrown by service methods that are not available in offline mode.
- *
- * @author Sindre Mehus
- * @version $Id$
- */
-public class OfflineException extends Exception {
-
- public OfflineException(String message) {
- super(message);
- }
-}
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/OfflineMusicService.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/OfflineMusicService.java
deleted file mode 100644
index 79fee6d2..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/OfflineMusicService.java
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.io.Reader;
-import java.io.FileReader;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Random;
-import java.util.Set;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import net.sourceforge.subsonic.androidapp.domain.Artist;
-import net.sourceforge.subsonic.androidapp.domain.Indexes;
-import net.sourceforge.subsonic.androidapp.domain.JukeboxStatus;
-import net.sourceforge.subsonic.androidapp.domain.Lyrics;
-import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
-import net.sourceforge.subsonic.androidapp.domain.MusicFolder;
-import net.sourceforge.subsonic.androidapp.domain.Playlist;
-import net.sourceforge.subsonic.androidapp.domain.SearchCritera;
-import net.sourceforge.subsonic.androidapp.domain.SearchResult;
-import net.sourceforge.subsonic.androidapp.service.parser.PlaylistParser;
-import net.sourceforge.subsonic.androidapp.util.Constants;
-import net.sourceforge.subsonic.androidapp.util.FileUtil;
-import net.sourceforge.subsonic.androidapp.util.ProgressListener;
-import net.sourceforge.subsonic.androidapp.util.Util;
-
-/**
- * @author Sindre Mehus
- */
-public class OfflineMusicService extends RESTMusicService {
-
- @Override
- public boolean isLicenseValid(Context context, ProgressListener progressListener) throws Exception {
- return true;
- }
-
- @Override
- public Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
- List<Artist> artists = new ArrayList<Artist>();
- File root = FileUtil.getMusicDirectory(context);
- for (File file : FileUtil.listFiles(root)) {
- if (file.isDirectory()) {
- Artist artist = new Artist();
- artist.setId(file.getPath());
- artist.setIndex(file.getName().substring(0, 1));
- artist.setName(file.getName());
- artists.add(artist);
- }
- }
- return new Indexes(0L, Collections.<Artist>emptyList(), artists);
- }
-
- @Override
- public MusicDirectory getMusicDirectory(String id, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
- File dir = new File(id);
- MusicDirectory result = new MusicDirectory();
- result.setName(dir.getName());
-
- Set<String> names = new HashSet<String>();
-
- for (File file : FileUtil.listMusicFiles(dir)) {
- String name = getName(file);
- if (name != null & !names.contains(name)) {
- names.add(name);
- result.addChild(createEntry(context, file, name));
- }
- }
- return result;
- }
-
- private String getName(File file) {
- String name = file.getName();
- if (file.isDirectory()) {
- return name;
- }
-
- if (name.endsWith(".partial") || name.contains(".partial.") || name.equals(Constants.ALBUM_ART_FILE)) {
- return null;
- }
-
- name = name.replace(".complete", "");
- return FileUtil.getBaseName(name);
- }
-
- private MusicDirectory.Entry createEntry(Context context, File file, String name) {
- MusicDirectory.Entry entry = new MusicDirectory.Entry();
- entry.setDirectory(file.isDirectory());
- entry.setId(file.getPath());
- entry.setParent(file.getParent());
- entry.setSize(file.length());
- String root = FileUtil.getMusicDirectory(context).getPath();
- entry.setPath(file.getPath().replaceFirst("^" + root + "/" , ""));
- if (file.isFile()) {
- entry.setArtist(file.getParentFile().getParentFile().getName());
- entry.setAlbum(file.getParentFile().getName());
- }
- entry.setTitle(name);
- entry.setSuffix(FileUtil.getExtension(file.getName().replace(".complete", "")));
-
- File albumArt = FileUtil.getAlbumArtFile(context, entry);
- if (albumArt.exists()) {
- entry.setCoverArt(albumArt.getPath());
- }
- return entry;
- }
-
- @Override
- public Bitmap getCoverArt(Context context, MusicDirectory.Entry entry, int size, boolean saveToFile, ProgressListener progressListener) throws Exception {
- InputStream in = new FileInputStream(entry.getCoverArt());
- try {
- byte[] bytes = Util.toByteArray(in);
- Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
- return Bitmap.createScaledBitmap(bitmap, size, size, true);
- } finally {
- Util.close(in);
- }
- }
-
- @Override
- public List<MusicFolder> getMusicFolders(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
- throw new OfflineException("Music folders not available in offline mode");
- }
-
- @Override
- public SearchResult search(SearchCritera criteria, Context context, ProgressListener progressListener) throws Exception {
- throw new OfflineException("Search not available in offline mode");
- }
-
- @Override
- public List<Playlist> getPlaylists(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
- List<Playlist> playlists = new ArrayList<Playlist>();
- File root = FileUtil.getPlaylistDirectory();
- for (File file : FileUtil.listFiles(root)) {
- Playlist playlist = new Playlist(file.getName(), file.getName());
- playlists.add(playlist);
- }
- return playlists;
- }
-
- @Override
- public MusicDirectory getPlaylist(String id, String name, Context context, ProgressListener progressListener) throws Exception {
- DownloadService downloadService = DownloadServiceImpl.getInstance();
- if (downloadService == null) {
- return new MusicDirectory();
- }
-
- Reader reader = null;
- try {
- reader = new FileReader(FileUtil.getPlaylistFile(name));
- MusicDirectory fullList = new PlaylistParser(context).parse(reader, progressListener);
- MusicDirectory playlist = new MusicDirectory();
- for(MusicDirectory.Entry song: fullList.getChildren()) {
- DownloadFile downloadFile = downloadService.forSong(song);
- File completeFile = downloadFile.getCompleteFile();
- if(completeFile.exists()) {
- playlist.addChild(song);
- }
- }
- return playlist;
- } finally {
- Util.close(reader);
- }
- }
-
- @Override
- public void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries, Context context, ProgressListener progressListener) throws Exception {
- throw new OfflineException("Playlists not available in offline mode");
- }
-
- @Override
- public Lyrics getLyrics(String artist, String title, Context context, ProgressListener progressListener) throws Exception {
- throw new OfflineException("Lyrics not available in offline mode");
- }
-
- @Override
- public void scrobble(String id, boolean submission, Context context, ProgressListener progressListener) throws Exception {
- throw new OfflineException("Scrobbling not available in offline mode");
- }
-
- @Override
- public MusicDirectory getAlbumList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception {
- throw new OfflineException("Album lists not available in offline mode");
- }
-
- @Override
- public String getVideoUrl(Context context, String id) {
- return null;
- }
-
- @Override
- public JukeboxStatus updateJukeboxPlaylist(List<String> ids, Context context, ProgressListener progressListener) throws Exception {
- throw new OfflineException("Jukebox not available in offline mode");
- }
-
- @Override
- public JukeboxStatus skipJukebox(int index, int offsetSeconds, Context context, ProgressListener progressListener) throws Exception {
- throw new OfflineException("Jukebox not available in offline mode");
- }
-
- @Override
- public JukeboxStatus stopJukebox(Context context, ProgressListener progressListener) throws Exception {
- throw new OfflineException("Jukebox not available in offline mode");
- }
-
- @Override
- public JukeboxStatus startJukebox(Context context, ProgressListener progressListener) throws Exception {
- throw new OfflineException("Jukebox not available in offline mode");
- }
-
- @Override
- public JukeboxStatus getJukeboxStatus(Context context, ProgressListener progressListener) throws Exception {
- throw new OfflineException("Jukebox not available in offline mode");
- }
-
- @Override
- public JukeboxStatus setJukeboxGain(float gain, Context context, ProgressListener progressListener) throws Exception {
- throw new OfflineException("Jukebox not available in offline mode");
- }
-
- @Override
- public MusicDirectory getRandomSongs(int size, Context context, ProgressListener progressListener) throws Exception {
- File root = FileUtil.getMusicDirectory(context);
- List<File> children = new LinkedList<File>();
- listFilesRecursively(root, children);
- MusicDirectory result = new MusicDirectory();
-
- if (children.isEmpty()) {
- return result;
- }
- Random random = new Random();
- for (int i = 0; i < size; i++) {
- File file = children.get(random.nextInt(children.size()));
- result.addChild(createEntry(context, file, getName(file)));
- }
-
- return result;
- }
-
- private void listFilesRecursively(File parent, List<File> children) {
- for (File file : FileUtil.listMusicFiles(parent)) {
- if (file.isFile()) {
- children.add(file);
- } else {
- listFilesRecursively(file, children);
- }
- }
- }
-}
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/RESTMusicService.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/RESTMusicService.java
deleted file mode 100644
index a939feef..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/RESTMusicService.java
+++ /dev/null
@@ -1,785 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.FileReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpResponse;
-import org.apache.http.NameValuePair;
-import org.apache.http.auth.AuthScope;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.entity.UrlEncodedFormEntity;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.conn.params.ConnManagerParams;
-import org.apache.http.conn.params.ConnPerRouteBean;
-import org.apache.http.conn.scheme.PlainSocketFactory;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.scheme.SchemeRegistry;
-import org.apache.http.conn.scheme.SocketFactory;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
-import org.apache.http.message.BasicHeader;
-import org.apache.http.message.BasicNameValuePair;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.HttpConnectionParams;
-import org.apache.http.params.HttpParams;
-import org.apache.http.protocol.BasicHttpContext;
-import org.apache.http.protocol.ExecutionContext;
-import org.apache.http.protocol.HttpContext;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.pm.PackageInfo;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.util.Log;
-import net.sourceforge.subsonic.androidapp.R;
-import net.sourceforge.subsonic.androidapp.domain.Indexes;
-import net.sourceforge.subsonic.androidapp.domain.JukeboxStatus;
-import net.sourceforge.subsonic.androidapp.domain.Lyrics;
-import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
-import net.sourceforge.subsonic.androidapp.domain.MusicFolder;
-import net.sourceforge.subsonic.androidapp.domain.Playlist;
-import net.sourceforge.subsonic.androidapp.domain.SearchCritera;
-import net.sourceforge.subsonic.androidapp.domain.SearchResult;
-import net.sourceforge.subsonic.androidapp.domain.ServerInfo;
-import net.sourceforge.subsonic.androidapp.domain.Version;
-import net.sourceforge.subsonic.androidapp.service.parser.AlbumListParser;
-import net.sourceforge.subsonic.androidapp.service.parser.ErrorParser;
-import net.sourceforge.subsonic.androidapp.service.parser.IndexesParser;
-import net.sourceforge.subsonic.androidapp.service.parser.JukeboxStatusParser;
-import net.sourceforge.subsonic.androidapp.service.parser.LicenseParser;
-import net.sourceforge.subsonic.androidapp.service.parser.LyricsParser;
-import net.sourceforge.subsonic.androidapp.service.parser.MusicDirectoryParser;
-import net.sourceforge.subsonic.androidapp.service.parser.MusicFoldersParser;
-import net.sourceforge.subsonic.androidapp.service.parser.PlaylistParser;
-import net.sourceforge.subsonic.androidapp.service.parser.PlaylistsParser;
-import net.sourceforge.subsonic.androidapp.service.parser.RandomSongsParser;
-import net.sourceforge.subsonic.androidapp.service.parser.SearchResult2Parser;
-import net.sourceforge.subsonic.androidapp.service.parser.SearchResultParser;
-import net.sourceforge.subsonic.androidapp.service.parser.VersionParser;
-import net.sourceforge.subsonic.androidapp.service.ssl.SSLSocketFactory;
-import net.sourceforge.subsonic.androidapp.service.ssl.TrustSelfSignedStrategy;
-import net.sourceforge.subsonic.androidapp.util.CancellableTask;
-import net.sourceforge.subsonic.androidapp.util.Constants;
-import net.sourceforge.subsonic.androidapp.util.FileUtil;
-import net.sourceforge.subsonic.androidapp.util.ProgressListener;
-import net.sourceforge.subsonic.androidapp.util.Util;
-
-/**
- * @author Sindre Mehus
- */
-public class RESTMusicService implements MusicService {
-
- private static final String TAG = RESTMusicService.class.getSimpleName();
-
- private static final int SOCKET_CONNECT_TIMEOUT = 10 * 1000;
- private static final int SOCKET_READ_TIMEOUT_DEFAULT = 10 * 1000;
- private static final int SOCKET_READ_TIMEOUT_DOWNLOAD = 30 * 1000;
- private static final int SOCKET_READ_TIMEOUT_GET_RANDOM_SONGS = 60 * 1000;
- private static final int SOCKET_READ_TIMEOUT_GET_PLAYLIST = 60 * 1000;
-
- // Allow 20 seconds extra timeout per MB offset.
- private static final double TIMEOUT_MILLIS_PER_OFFSET_BYTE = 20000.0 / 1000000.0;
-
- /**
- * URL from which to fetch latest versions.
- */
- private static final String VERSION_URL = "http://subsonic.org/backend/version.view";
-
- private static final int HTTP_REQUEST_MAX_ATTEMPTS = 5;
- private static final long REDIRECTION_CHECK_INTERVAL_MILLIS = 60L * 60L * 1000L;
-
- private final DefaultHttpClient httpClient;
- private long redirectionLastChecked;
- private int redirectionNetworkType = -1;
- private String redirectFrom;
- private String redirectTo;
- private final ThreadSafeClientConnManager connManager;
-
- public RESTMusicService() {
-
- // Create and initialize default HTTP parameters
- HttpParams params = new BasicHttpParams();
- ConnManagerParams.setMaxTotalConnections(params, 20);
- ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(20));
- HttpConnectionParams.setConnectionTimeout(params, SOCKET_CONNECT_TIMEOUT);
- HttpConnectionParams.setSoTimeout(params, SOCKET_READ_TIMEOUT_DEFAULT);
-
- // Turn off stale checking. Our connections break all the time anyway,
- // and it's not worth it to pay the penalty of checking every time.
- HttpConnectionParams.setStaleCheckingEnabled(params, false);
-
- // Create and initialize scheme registry
- SchemeRegistry schemeRegistry = new SchemeRegistry();
- schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
- schemeRegistry.register(new Scheme("https", createSSLSocketFactory(), 443));
-
- // Create an HttpClient with the ThreadSafeClientConnManager.
- // This connection manager must be used if more than one thread will
- // be using the HttpClient.
- connManager = new ThreadSafeClientConnManager(params, schemeRegistry);
- httpClient = new DefaultHttpClient(connManager, params);
- }
-
- private SocketFactory createSSLSocketFactory() {
- try {
- return new SSLSocketFactory(new TrustSelfSignedStrategy(), SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
- } catch (Throwable x) {
- Log.e(TAG, "Failed to create custom SSL socket factory, using default.", x);
- return org.apache.http.conn.ssl.SSLSocketFactory.getSocketFactory();
- }
- }
-
- @Override
- public void ping(Context context, ProgressListener progressListener) throws Exception {
- Reader reader = getReader(context, progressListener, "ping", null);
- try {
- new ErrorParser(context).parse(reader);
- } finally {
- Util.close(reader);
- }
- }
-
- @Override
- public boolean isLicenseValid(Context context, ProgressListener progressListener) throws Exception {
- Reader reader = getReader(context, progressListener, "getLicense", null);
- try {
- ServerInfo serverInfo = new LicenseParser(context).parse(reader);
- return serverInfo.isLicenseValid();
- } finally {
- Util.close(reader);
- }
- }
-
- public List<MusicFolder> getMusicFolders(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
- List<MusicFolder> cachedMusicFolders = readCachedMusicFolders(context);
- if (cachedMusicFolders != null && !refresh) {
- return cachedMusicFolders;
- }
-
- Reader reader = getReader(context, progressListener, "getMusicFolders", null);
- try {
- List<MusicFolder> musicFolders = new MusicFoldersParser(context).parse(reader, progressListener);
- writeCachedMusicFolders(context, musicFolders);
- return musicFolders;
- } finally {
- Util.close(reader);
- }
- }
-
- @Override
- public Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
- Indexes cachedIndexes = readCachedIndexes(context, musicFolderId);
- if (cachedIndexes != null && !refresh) {
- return cachedIndexes;
- }
-
- long lastModified = cachedIndexes == null ? 0L : cachedIndexes.getLastModified();
-
- List<String> parameterNames = new ArrayList<String>();
- List<Object> parameterValues = new ArrayList<Object>();
-
- parameterNames.add("ifModifiedSince");
- parameterValues.add(lastModified);
-
- if (musicFolderId != null) {
- parameterNames.add("musicFolderId");
- parameterValues.add(musicFolderId);
- }
-
- Reader reader = getReader(context, progressListener, "getIndexes", null, parameterNames, parameterValues);
- try {
- Indexes indexes = new IndexesParser(context).parse(reader, progressListener);
- if (indexes != null) {
- writeCachedIndexes(context, indexes, musicFolderId);
- return indexes;
- }
- return cachedIndexes;
- } finally {
- Util.close(reader);
- }
- }
-
- private Indexes readCachedIndexes(Context context, String musicFolderId) {
- String filename = getCachedIndexesFilename(context, musicFolderId);
- return FileUtil.deserialize(context, filename);
- }
-
- private void writeCachedIndexes(Context context, Indexes indexes, String musicFolderId) {
- String filename = getCachedIndexesFilename(context, musicFolderId);
- FileUtil.serialize(context, indexes, filename);
- }
-
- private String getCachedIndexesFilename(Context context, String musicFolderId) {
- String s = Util.getRestUrl(context, null) + musicFolderId;
- return "indexes-" + Math.abs(s.hashCode()) + ".ser";
- }
-
- private ArrayList<MusicFolder> readCachedMusicFolders(Context context) {
- String filename = getCachedMusicFoldersFilename(context);
- return FileUtil.deserialize(context, filename);
- }
-
- private void writeCachedMusicFolders(Context context, List<MusicFolder> musicFolders) {
- String filename = getCachedMusicFoldersFilename(context);
- FileUtil.serialize(context, new ArrayList<MusicFolder>(musicFolders), filename);
- }
-
- private String getCachedMusicFoldersFilename(Context context) {
- String s = Util.getRestUrl(context, null);
- return "musicFolders-" + Math.abs(s.hashCode()) + ".ser";
- }
-
- @Override
- public MusicDirectory getMusicDirectory(String id, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
- Reader reader = getReader(context, progressListener, "getMusicDirectory", null, "id", id);
- try {
- return new MusicDirectoryParser(context).parse(reader, progressListener);
- } finally {
- Util.close(reader);
- }
- }
-
- @Override
- public SearchResult search(SearchCritera critera, Context context, ProgressListener progressListener) throws Exception {
- try {
- return searchNew(critera, context, progressListener);
- } catch (ServerTooOldException x) {
- // Ensure backward compatibility with REST 1.3.
- return searchOld(critera, context, progressListener);
- }
- }
-
- /**
- * Search using the "search" REST method.
- */
- private SearchResult searchOld(SearchCritera critera, Context context, ProgressListener progressListener) throws Exception {
- List<String> parameterNames = Arrays.asList("any", "songCount");
- List<Object> parameterValues = Arrays.<Object>asList(critera.getQuery(), critera.getSongCount());
- Reader reader = getReader(context, progressListener, "search", null, parameterNames, parameterValues);
- try {
- return new SearchResultParser(context).parse(reader, progressListener);
- } finally {
- Util.close(reader);
- }
- }
-
- /**
- * Search using the "search2" REST method, available in 1.4.0 and later.
- */
- private SearchResult searchNew(SearchCritera critera, Context context, ProgressListener progressListener) throws Exception {
- checkServerVersion(context, "1.4", null);
-
- List<String> parameterNames = Arrays.asList("query", "artistCount", "albumCount", "songCount");
- List<Object> parameterValues = Arrays.<Object>asList(critera.getQuery(), critera.getArtistCount(),
- critera.getAlbumCount(), critera.getSongCount());
- Reader reader = getReader(context, progressListener, "search2", null, parameterNames, parameterValues);
- try {
- return new SearchResult2Parser(context).parse(reader, progressListener);
- } finally {
- Util.close(reader);
- }
- }
-
- @Override
- public MusicDirectory getPlaylist(String id, String name, Context context, ProgressListener progressListener) throws Exception {
- HttpParams params = new BasicHttpParams();
- HttpConnectionParams.setSoTimeout(params, SOCKET_READ_TIMEOUT_GET_PLAYLIST);
-
- Reader reader = getReader(context, progressListener, "getPlaylist", params, "id", id);
- OutputStreamWriter out = null;
- try {
- out = new OutputStreamWriter(new FileOutputStream(FileUtil.getPlaylistFile(name)));
-
- char[] buff = new char[256];
- int n;
- while((n = reader.read(buff)) >= 0) {
- out.write(buff, 0, n);
- }
- } finally {
- Util.close(out);
- Util.close(reader);
- }
-
- try {
- reader = new FileReader(FileUtil.getPlaylistFile(name));
- return new PlaylistParser(context).parse(reader, progressListener);
- } finally {
- Util.close(reader);
- }
- }
-
- @Override
- public List<Playlist> getPlaylists(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
- Reader reader = getReader(context, progressListener, "getPlaylists", null);
- try {
- return new PlaylistsParser(context).parse(reader, progressListener);
- } finally {
- Util.close(reader);
- }
- }
-
- @Override
- public void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries, Context context, ProgressListener progressListener) throws Exception {
- List<String> parameterNames = new LinkedList<String>();
- List<Object> parameterValues = new LinkedList<Object>();
-
- if (id != null) {
- parameterNames.add("playlistId");
- parameterValues.add(id);
- }
- if (name != null) {
- parameterNames.add("name");
- parameterValues.add(name);
- }
- for (MusicDirectory.Entry entry : entries) {
- parameterNames.add("songId");
- parameterValues.add(entry.getId());
- }
-
- Reader reader = getReader(context, progressListener, "createPlaylist", null, parameterNames, parameterValues);
- try {
- new ErrorParser(context).parse(reader);
- } finally {
- Util.close(reader);
- }
- }
-
- @Override
- public Lyrics getLyrics(String artist, String title, Context context, ProgressListener progressListener) throws Exception {
- Reader reader = getReader(context, progressListener, "getLyrics", null, Arrays.asList("artist", "title"), Arrays.<Object>asList(artist, title));
- try {
- return new LyricsParser(context).parse(reader, progressListener);
- } finally {
- Util.close(reader);
- }
- }
-
- @Override
- public void scrobble(String id, boolean submission, Context context, ProgressListener progressListener) throws Exception {
- checkServerVersion(context, "1.5", "Scrobbling not supported.");
- Reader reader = getReader(context, progressListener, "scrobble", null, Arrays.asList("id", "submission"), Arrays.<Object>asList(id, submission));
- try {
- new ErrorParser(context).parse(reader);
- } finally {
- Util.close(reader);
- }
- }
-
- @Override
- public MusicDirectory getAlbumList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception {
- Reader reader = getReader(context, progressListener, "getAlbumList",
- null, Arrays.asList("type", "size", "offset"), Arrays.<Object>asList(type, size, offset));
- try {
- return new AlbumListParser(context).parse(reader, progressListener);
- } finally {
- Util.close(reader);
- }
- }
-
- @Override
- public MusicDirectory getRandomSongs(int size, Context context, ProgressListener progressListener) throws Exception {
- HttpParams params = new BasicHttpParams();
- HttpConnectionParams.setSoTimeout(params, SOCKET_READ_TIMEOUT_GET_RANDOM_SONGS);
-
- Reader reader = getReader(context, progressListener, "getRandomSongs", params, "size", size);
- try {
- return new RandomSongsParser(context).parse(reader, progressListener);
- } finally {
- Util.close(reader);
- }
- }
-
- @Override
- public Version getLocalVersion(Context context) throws Exception {
- PackageInfo packageInfo = context.getPackageManager().getPackageInfo("net.sourceforge.subsonic.androidapp", 0);
- return new Version(packageInfo.versionName);
- }
-
- @Override
- public Version getLatestVersion(Context context, ProgressListener progressListener) throws Exception {
- Reader reader = getReaderForURL(context, VERSION_URL, null, null, null, progressListener);
- try {
- return new VersionParser().parse(reader);
- } finally {
- Util.close(reader);
- }
- }
-
- private void checkServerVersion(Context context, String version, String text) throws ServerTooOldException {
- Version serverVersion = Util.getServerRestVersion(context);
- Version requiredVersion = new Version(version);
- boolean ok = serverVersion == null || serverVersion.compareTo(requiredVersion) >= 0;
-
- if (!ok) {
- throw new ServerTooOldException(text, serverVersion, requiredVersion);
- }
- }
-
- @Override
- public Bitmap getCoverArt(Context context, MusicDirectory.Entry entry, int size, boolean saveToFile, ProgressListener progressListener) throws Exception {
-
- // Synchronize on the entry so that we don't download concurrently for the same song.
- synchronized (entry) {
-
- // Use cached file, if existing.
- Bitmap bitmap = FileUtil.getAlbumArtBitmap(context, entry, size);
- if (bitmap != null) {
- return bitmap;
- }
-
- String url = Util.getRestUrl(context, "getCoverArt");
-
- InputStream in = null;
- try {
- List<String> parameterNames = Arrays.asList("id", "size");
- List<Object> parameterValues = Arrays.<Object>asList(entry.getCoverArt(), size);
- HttpEntity entity = getEntityForURL(context, url, null, parameterNames, parameterValues, progressListener);
- in = entity.getContent();
-
- // If content type is XML, an error occured. Get it.
- String contentType = Util.getContentType(entity);
- if (contentType != null && contentType.startsWith("text/xml")) {
- new ErrorParser(context).parse(new InputStreamReader(in, Constants.UTF_8));
- return null; // Never reached.
- }
-
- byte[] bytes = Util.toByteArray(in);
-
- if (saveToFile) {
- OutputStream out = null;
- try {
- out = new FileOutputStream(FileUtil.getAlbumArtFile(context, entry));
- out.write(bytes);
- } finally {
- Util.close(out);
- }
- }
-
- return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
-
- } finally {
- Util.close(in);
- }
- }
- }
-
- @Override
- public HttpResponse getDownloadInputStream(Context context, MusicDirectory.Entry song, long offset, int maxBitrate, CancellableTask task) throws Exception {
-
- String url = Util.getRestUrl(context, "stream");
-
- // Set socket read timeout. Note: The timeout increases as the offset gets larger. This is
- // to avoid the thrashing effect seen when offset is combined with transcoding/downsampling on the server.
- // In that case, the server uses a long time before sending any data, causing the client to time out.
- HttpParams params = new BasicHttpParams();
- int timeout = (int) (SOCKET_READ_TIMEOUT_DOWNLOAD + offset * TIMEOUT_MILLIS_PER_OFFSET_BYTE);
- HttpConnectionParams.setSoTimeout(params, timeout);
-
- // Add "Range" header if offset is given.
- List<Header> headers = new ArrayList<Header>();
- if (offset > 0) {
- headers.add(new BasicHeader("Range", "bytes=" + offset + "-"));
- }
- List<String> parameterNames = Arrays.asList("id", "maxBitRate");
- List<Object> parameterValues = Arrays.<Object>asList(song.getId(), maxBitrate);
- HttpResponse response = getResponseForURL(context, url, params, parameterNames, parameterValues, headers, null, task);
-
- // If content type is XML, an error occurred. Get it.
- String contentType = Util.getContentType(response.getEntity());
- if (contentType != null && contentType.startsWith("text/xml")) {
- InputStream in = response.getEntity().getContent();
- try {
- new ErrorParser(context).parse(new InputStreamReader(in, Constants.UTF_8));
- } finally {
- Util.close(in);
- }
- }
-
- return response;
- }
-
- @Override
- public String getVideoUrl(Context context, String id) {
- StringBuilder builder = new StringBuilder(Util.getRestUrl(context, "videoPlayer"));
- builder.append("&id=").append(id);
- builder.append("&maxBitRate=500");
- builder.append("&autoplay=true");
-
- String url = rewriteUrlWithRedirect(context, builder.toString());
- Log.i(TAG, "Using video URL: " + url);
- return url;
- }
-
- @Override
- public JukeboxStatus updateJukeboxPlaylist(List<String> ids, Context context, ProgressListener progressListener) throws Exception {
- int n = ids.size();
- List<String> parameterNames = new ArrayList<String>(n + 1);
- parameterNames.add("action");
- for (int i = 0; i < n; i++) {
- parameterNames.add("id");
- }
- List<Object> parameterValues = new ArrayList<Object>();
- parameterValues.add("set");
- parameterValues.addAll(ids);
-
- return executeJukeboxCommand(context, progressListener, parameterNames, parameterValues);
- }
-
- @Override
- public JukeboxStatus skipJukebox(int index, int offsetSeconds, Context context, ProgressListener progressListener) throws Exception {
- List<String> parameterNames = Arrays.asList("action", "index", "offset");
- List<Object> parameterValues = Arrays.<Object>asList("skip", index, offsetSeconds);
- return executeJukeboxCommand(context, progressListener, parameterNames, parameterValues);
- }
-
- @Override
- public JukeboxStatus stopJukebox(Context context, ProgressListener progressListener) throws Exception {
- return executeJukeboxCommand(context, progressListener, Arrays.asList("action"), Arrays.<Object>asList("stop"));
- }
-
- @Override
- public JukeboxStatus startJukebox(Context context, ProgressListener progressListener) throws Exception {
- return executeJukeboxCommand(context, progressListener, Arrays.asList("action"), Arrays.<Object>asList("start"));
- }
-
- @Override
- public JukeboxStatus getJukeboxStatus(Context context, ProgressListener progressListener) throws Exception {
- return executeJukeboxCommand(context, progressListener, Arrays.asList("action"), Arrays.<Object>asList("status"));
- }
-
- @Override
- public JukeboxStatus setJukeboxGain(float gain, Context context, ProgressListener progressListener) throws Exception {
- List<String> parameterNames = Arrays.asList("action", "gain");
- List<Object> parameterValues = Arrays.<Object>asList("setGain", gain);
- return executeJukeboxCommand(context, progressListener, parameterNames, parameterValues);
-
- }
-
- private JukeboxStatus executeJukeboxCommand(Context context, ProgressListener progressListener, List<String> parameterNames, List<Object> parameterValues) throws Exception {
- checkServerVersion(context, "1.7", "Jukebox not supported.");
- Reader reader = getReader(context, progressListener, "jukeboxControl", null, parameterNames, parameterValues);
- try {
- return new JukeboxStatusParser(context).parse(reader);
- } finally {
- Util.close(reader);
- }
- }
-
- private Reader getReader(Context context, ProgressListener progressListener, String method, HttpParams requestParams) throws Exception {
- return getReader(context, progressListener, method, requestParams, Collections.<String>emptyList(), Collections.emptyList());
- }
-
- private Reader getReader(Context context, ProgressListener progressListener, String method,
- HttpParams requestParams, String parameterName, Object parameterValue) throws Exception {
- return getReader(context, progressListener, method, requestParams, Arrays.asList(parameterName), Arrays.<Object>asList(parameterValue));
- }
-
- private Reader getReader(Context context, ProgressListener progressListener, String method,
- HttpParams requestParams, List<String> parameterNames, List<Object> parameterValues) throws Exception {
-
- if (progressListener != null) {
- progressListener.updateProgress(R.string.service_connecting);
- }
-
- String url = Util.getRestUrl(context, method);
- return getReaderForURL(context, url, requestParams, parameterNames, parameterValues, progressListener);
- }
-
- private Reader getReaderForURL(Context context, String url, HttpParams requestParams, List<String> parameterNames,
- List<Object> parameterValues, ProgressListener progressListener) throws Exception {
- HttpEntity entity = getEntityForURL(context, url, requestParams, parameterNames, parameterValues, progressListener);
- if (entity == null) {
- throw new RuntimeException("No entity received for URL " + url);
- }
-
- InputStream in = entity.getContent();
- return new InputStreamReader(in, Constants.UTF_8);
- }
-
- private HttpEntity getEntityForURL(Context context, String url, HttpParams requestParams, List<String> parameterNames,
- List<Object> parameterValues, ProgressListener progressListener) throws Exception {
- return getResponseForURL(context, url, requestParams, parameterNames, parameterValues, null, progressListener, null).getEntity();
- }
-
- private HttpResponse getResponseForURL(Context context, String url, HttpParams requestParams,
- List<String> parameterNames, List<Object> parameterValues,
- List<Header> headers, ProgressListener progressListener, CancellableTask task) throws Exception {
- Log.d(TAG, "Connections in pool: " + connManager.getConnectionsInPool());
-
- // If not too many parameters, extract them to the URL rather than relying on the HTTP POST request being
- // received intact. Remember, HTTP POST requests are converted to GET requests during HTTP redirects, thus
- // loosing its entity.
- if (parameterNames != null && parameterNames.size() < 10) {
- StringBuilder builder = new StringBuilder(url);
- for (int i = 0; i < parameterNames.size(); i++) {
- builder.append("&").append(parameterNames.get(i)).append("=");
- builder.append(URLEncoder.encode(String.valueOf(parameterValues.get(i)), "UTF-8"));
- }
- url = builder.toString();
- parameterNames = null;
- parameterValues = null;
- }
-
- String rewrittenUrl = rewriteUrlWithRedirect(context, url);
- return executeWithRetry(context, rewrittenUrl, url, requestParams, parameterNames, parameterValues, headers, progressListener, task);
- }
-
- private HttpResponse executeWithRetry(Context context, String url, String originalUrl, HttpParams requestParams,
- List<String> parameterNames, List<Object> parameterValues,
- List<Header> headers, ProgressListener progressListener, CancellableTask task) throws IOException {
- Log.i(TAG, "Using URL " + url);
-
- final AtomicReference<Boolean> cancelled = new AtomicReference<Boolean>(false);
- int attempts = 0;
- while (true) {
- attempts++;
- HttpContext httpContext = new BasicHttpContext();
- final HttpPost request = new HttpPost(url);
-
- if (task != null) {
- // Attempt to abort the HTTP request if the task is cancelled.
- task.setOnCancelListener(new CancellableTask.OnCancelListener() {
- @Override
- public void onCancel() {
- cancelled.set(true);
- request.abort();
- }
- });
- }
-
- if (parameterNames != null) {
- List<NameValuePair> params = new ArrayList<NameValuePair>();
- for (int i = 0; i < parameterNames.size(); i++) {
- params.add(new BasicNameValuePair(parameterNames.get(i), String.valueOf(parameterValues.get(i))));
- }
- request.setEntity(new UrlEncodedFormEntity(params, Constants.UTF_8));
- }
-
- if (requestParams != null) {
- request.setParams(requestParams);
- Log.d(TAG, "Socket read timeout: " + HttpConnectionParams.getSoTimeout(requestParams) + " ms.");
- }
-
- if (headers != null) {
- for (Header header : headers) {
- request.addHeader(header);
- }
- }
-
- // Set credentials to get through apache proxies that require authentication.
- SharedPreferences prefs = Util.getPreferences(context);
- int instance = prefs.getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1);
- String username = prefs.getString(Constants.PREFERENCES_KEY_USERNAME + instance, null);
- String password = prefs.getString(Constants.PREFERENCES_KEY_PASSWORD + instance, null);
- httpClient.getCredentialsProvider().setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
- new UsernamePasswordCredentials(username, password));
-
- try {
- HttpResponse response = httpClient.execute(request, httpContext);
- detectRedirect(originalUrl, context, httpContext);
- return response;
- } catch (IOException x) {
- request.abort();
- if (attempts >= HTTP_REQUEST_MAX_ATTEMPTS || cancelled.get()) {
- throw x;
- }
- if (progressListener != null) {
- String msg = context.getResources().getString(R.string.music_service_retry, attempts, HTTP_REQUEST_MAX_ATTEMPTS - 1);
- progressListener.updateProgress(msg);
- }
- Log.w(TAG, "Got IOException (" + attempts + "), will retry", x);
- increaseTimeouts(requestParams);
- Util.sleepQuietly(2000L);
- }
- }
- }
-
- private void increaseTimeouts(HttpParams requestParams) {
- if (requestParams != null) {
- int connectTimeout = HttpConnectionParams.getConnectionTimeout(requestParams);
- if (connectTimeout != 0) {
- HttpConnectionParams.setConnectionTimeout(requestParams, (int) (connectTimeout * 1.3F));
- }
- int readTimeout = HttpConnectionParams.getSoTimeout(requestParams);
- if (readTimeout != 0) {
- HttpConnectionParams.setSoTimeout(requestParams, (int) (readTimeout * 1.5F));
- }
- }
- }
-
- private void detectRedirect(String originalUrl, Context context, HttpContext httpContext) {
- HttpUriRequest request = (HttpUriRequest) httpContext.getAttribute(ExecutionContext.HTTP_REQUEST);
- HttpHost host = (HttpHost) httpContext.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
- String redirectedUrl = host.toURI() + request.getURI();
-
- redirectFrom = originalUrl.substring(0, originalUrl.indexOf("/rest/"));
- redirectTo = redirectedUrl.substring(0, redirectedUrl.indexOf("/rest/"));
-
- Log.i(TAG, redirectFrom + " redirects to " + redirectTo);
- redirectionLastChecked = System.currentTimeMillis();
- redirectionNetworkType = getCurrentNetworkType(context);
- }
-
- private String rewriteUrlWithRedirect(Context context, String url) {
-
- // Only cache for a certain time.
- if (System.currentTimeMillis() - redirectionLastChecked > REDIRECTION_CHECK_INTERVAL_MILLIS) {
- return url;
- }
-
- // Ignore cache if network type has changed.
- if (redirectionNetworkType != getCurrentNetworkType(context)) {
- return url;
- }
-
- if (redirectFrom == null || redirectTo == null) {
- return url;
- }
-
- return url.replace(redirectFrom, redirectTo);
- }
-
- private int getCurrentNetworkType(Context context) {
- ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo networkInfo = manager.getActiveNetworkInfo();
- return networkInfo == null ? -1 : networkInfo.getType();
- }
-}
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/Scrobbler.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/Scrobbler.java
deleted file mode 100644
index ce121a4b..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/Scrobbler.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package net.sourceforge.subsonic.androidapp.service;
-
-import android.content.Context;
-import android.util.Log;
-import net.sourceforge.subsonic.androidapp.util.Util;
-
-/**
- * Scrobbles played songs to Last.fm.
- *
- * @author Sindre Mehus
- * @version $Id$
- */
-public class Scrobbler {
-
- private static final String TAG = Scrobbler.class.getSimpleName();
-
- private String lastSubmission;
- private String lastNowPlaying;
-
- public void scrobble(final Context context, final DownloadFile song, final boolean submission) {
- if (song == null || !Util.isScrobblingEnabled(context)) {
- return;
- }
- final String id = song.getSong().getId();
-
- // Avoid duplicate registrations.
- if (submission && id.equals(lastSubmission)) {
- return;
- }
- if (!submission && id.equals(lastNowPlaying)) {
- return;
- }
- if (submission) {
- lastSubmission = id;
- } else {
- lastNowPlaying = id;
- }
-
- new Thread("Scrobble " + song) {
- @Override
- public void run() {
- MusicService service = MusicServiceFactory.getMusicService(context);
- try {
- service.scrobble(id, submission, context, null);
- Log.i(TAG, "Scrobbled '" + (submission ? "submission" : "now playing") + "' for " + song);
- } catch (Exception x) {
- Log.i(TAG, "Failed to scrobble'" + (submission ? "submission" : "now playing") + "' for " + song, x);
- }
- }
- }.start();
- }
-}
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ServerTooOldException.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ServerTooOldException.java
deleted file mode 100644
index 9d433385..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ServerTooOldException.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service;
-
-import net.sourceforge.subsonic.androidapp.domain.Version;
-
-/**
- * Thrown if the REST API version implemented by the server is too old.
- *
- * @author Sindre Mehus
- * @version $Id$
- */
-public class ServerTooOldException extends Exception {
-
- private final String text;
- private final Version serverVersion;
- private final Version requiredVersion;
-
- public ServerTooOldException(String text, Version serverVersion, Version requiredVersion) {
- this.text = text;
- this.serverVersion = serverVersion;
- this.requiredVersion = requiredVersion;
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- if (text != null) {
- builder.append(text).append(" ");
- }
- builder.append("Server API version too old. ");
- builder.append("Requires ").append(requiredVersion).append(" but is ").append(serverVersion).append(".");
- return builder.toString();
- }
-}
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/AbstractParser.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/AbstractParser.java
deleted file mode 100644
index 4ddff7e9..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/AbstractParser.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service.parser;
-
-import java.io.Reader;
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.content.Context;
-import android.util.Xml;
-import net.sourceforge.subsonic.androidapp.R;
-import net.sourceforge.subsonic.androidapp.domain.Version;
-import net.sourceforge.subsonic.androidapp.util.ProgressListener;
-import net.sourceforge.subsonic.androidapp.util.Util;
-
-/**
- * @author Sindre Mehus
- */
-public abstract class AbstractParser {
-
- private final Context context;
- private XmlPullParser parser;
- private boolean rootElementFound;
-
- public AbstractParser(Context context) {
- this.context = context;
- }
-
- protected Context getContext() {
- return context;
- }
-
- protected void handleError() throws Exception {
- int code = getInteger("code");
- String message;
- switch (code) {
- case 20:
- message = context.getResources().getString(R.string.parser_upgrade_client);
- break;
- case 30:
- message = context.getResources().getString(R.string.parser_upgrade_server);
- break;
- case 40:
- message = context.getResources().getString(R.string.parser_not_authenticated);
- break;
- case 50:
- message = context.getResources().getString(R.string.parser_not_authorized);
- break;
- default:
- message = get("message");
- break;
- }
- throw new SubsonicRESTException(code, message);
- }
-
- protected void updateProgress(ProgressListener progressListener, int messageId) {
- if (progressListener != null) {
- progressListener.updateProgress(messageId);
- }
- }
-
- protected void updateProgress(ProgressListener progressListener, String message) {
- if (progressListener != null) {
- progressListener.updateProgress(message);
- }
- }
-
- protected String getText() {
- return parser.getText();
- }
-
- protected String get(String name) {
- return parser.getAttributeValue(null, name);
- }
-
- protected boolean getBoolean(String name) {
- return "true".equals(get(name));
- }
-
- protected Integer getInteger(String name) {
- String s = get(name);
- return s == null ? null : Integer.valueOf(s);
- }
-
- protected Long getLong(String name) {
- String s = get(name);
- return s == null ? null : Long.valueOf(s);
- }
-
- protected Float getFloat(String name) {
- String s = get(name);
- return s == null ? null : Float.valueOf(s);
- }
-
- protected void init(Reader reader) throws Exception {
- parser = Xml.newPullParser();
- parser.setInput(reader);
- rootElementFound = false;
- }
-
- protected int nextParseEvent() throws Exception {
- return parser.next();
- }
-
- protected String getElementName() {
- String name = parser.getName();
- if ("subsonic-response".equals(name)) {
- rootElementFound = true;
- String version = get("version");
- if (version != null) {
- Util.setServerRestVersion(context, new Version(version));
- }
- }
- return name;
- }
-
- protected void validate() throws Exception {
- if (!rootElementFound) {
- throw new Exception(context.getResources().getString(R.string.background_task_parse_error));
- }
- }
-} \ No newline at end of file
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/AlbumListParser.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/AlbumListParser.java
deleted file mode 100644
index 298ef114..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/AlbumListParser.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service.parser;
-
-import android.content.Context;
-import net.sourceforge.subsonic.androidapp.R;
-import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
-import net.sourceforge.subsonic.androidapp.util.ProgressListener;
-import org.xmlpull.v1.XmlPullParser;
-
-import java.io.Reader;
-
-/**
- * @author Sindre Mehus
- */
-public class AlbumListParser extends MusicDirectoryEntryParser {
-
- public AlbumListParser(Context context) {
- super(context);
- }
-
- public MusicDirectory parse(Reader reader, ProgressListener progressListener) throws Exception {
-
- updateProgress(progressListener, R.string.parser_reading);
- init(reader);
-
- MusicDirectory dir = new MusicDirectory();
- int eventType;
- do {
- eventType = nextParseEvent();
- if (eventType == XmlPullParser.START_TAG) {
- String name = getElementName();
- if ("album".equals(name)) {
- dir.addChild(parseEntry());
- } else if ("error".equals(name)) {
- handleError();
- }
- }
- } while (eventType != XmlPullParser.END_DOCUMENT);
-
- validate();
- updateProgress(progressListener, R.string.parser_reading_done);
-
- return dir;
- }
-} \ No newline at end of file
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/ErrorParser.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/ErrorParser.java
deleted file mode 100644
index b2c61c5b..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/ErrorParser.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service.parser;
-
-import android.content.Context;
-import org.xmlpull.v1.XmlPullParser;
-
-import java.io.Reader;
-
-/**
- * @author Sindre Mehus
- */
-public class ErrorParser extends AbstractParser {
-
- public ErrorParser(Context context) {
- super(context);
- }
-
- public void parse(Reader reader) throws Exception {
-
- init(reader);
-
- int eventType;
- do {
- eventType = nextParseEvent();
- if (eventType == XmlPullParser.START_TAG && "error".equals(getElementName())) {
- handleError();
- }
- } while (eventType != XmlPullParser.END_DOCUMENT);
-
- validate();
- }
-} \ No newline at end of file
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/IndexesParser.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/IndexesParser.java
deleted file mode 100644
index 83ef3e77..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/IndexesParser.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service.parser;
-
-import java.io.Reader;
-import java.util.List;
-import java.util.ArrayList;
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.content.Context;
-import net.sourceforge.subsonic.androidapp.R;
-import net.sourceforge.subsonic.androidapp.domain.Artist;
-import net.sourceforge.subsonic.androidapp.domain.Indexes;
-import net.sourceforge.subsonic.androidapp.util.ProgressListener;
-import android.util.Log;
-
-/**
- * @author Sindre Mehus
- */
-public class IndexesParser extends AbstractParser {
- private static final String TAG = IndexesParser.class.getSimpleName();
-
- public IndexesParser(Context context) {
- super(context);
- }
-
- public Indexes parse(Reader reader, ProgressListener progressListener) throws Exception {
-
- long t0 = System.currentTimeMillis();
- updateProgress(progressListener, R.string.parser_reading);
- init(reader);
-
- List<Artist> artists = new ArrayList<Artist>();
- List<Artist> shortcuts = new ArrayList<Artist>();
- Long lastModified = null;
- int eventType;
- String index = "#";
- boolean changed = false;
-
- do {
- eventType = nextParseEvent();
- if (eventType == XmlPullParser.START_TAG) {
- String name = getElementName();
- if ("indexes".equals(name)) {
- changed = true;
- lastModified = getLong("lastModified");
- } else if ("index".equals(name)) {
- index = get("name");
-
- } else if ("artist".equals(name)) {
- Artist artist = new Artist();
- artist.setId(get("id"));
- artist.setName(get("name"));
- artist.setIndex(index);
- artists.add(artist);
-
- if (artists.size() % 10 == 0) {
- String msg = getContext().getResources().getString(R.string.parser_artist_count, artists.size());
- updateProgress(progressListener, msg);
- }
- } else if ("shortcut".equals(name)) {
- Artist shortcut = new Artist();
- shortcut.setId(get("id"));
- shortcut.setName(get("name"));
- shortcut.setIndex("*");
- shortcuts.add(shortcut);
- } else if ("error".equals(name)) {
- handleError();
- }
- }
- } while (eventType != XmlPullParser.END_DOCUMENT);
-
- validate();
-
- if (!changed) {
- return null;
- }
-
- long t1 = System.currentTimeMillis();
- Log.d(TAG, "Got " + artists.size() + " artist(s) in " + (t1 - t0) + "ms.");
-
- String msg = getContext().getResources().getString(R.string.parser_artist_count, artists.size());
- updateProgress(progressListener, msg);
-
- return new Indexes(lastModified == null ? 0L : lastModified, shortcuts, artists);
- }
-} \ No newline at end of file
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/JukeboxStatusParser.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/JukeboxStatusParser.java
deleted file mode 100644
index 2a61508d..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/JukeboxStatusParser.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service.parser;
-
-import java.io.Reader;
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.content.Context;
-import net.sourceforge.subsonic.androidapp.domain.JukeboxStatus;
-
-/**
- * @author Sindre Mehus
- */
-public class JukeboxStatusParser extends AbstractParser {
-
- public JukeboxStatusParser(Context context) {
- super(context);
- }
-
- public JukeboxStatus parse(Reader reader) throws Exception {
-
- init(reader);
-
- JukeboxStatus jukeboxStatus = new JukeboxStatus();
- int eventType;
- do {
- eventType = nextParseEvent();
- if (eventType == XmlPullParser.START_TAG) {
- String name = getElementName();
- if ("jukeboxPlaylist".equals(name) || "jukeboxStatus".equals(name)) {
- jukeboxStatus.setPositionSeconds(getInteger("position"));
- jukeboxStatus.setCurrentIndex(getInteger("currentIndex"));
- jukeboxStatus.setPlaying(getBoolean("playing"));
- jukeboxStatus.setGain(getFloat("gain"));
- } else if ("error".equals(name)) {
- handleError();
- }
- }
- } while (eventType != XmlPullParser.END_DOCUMENT);
-
- validate();
-
- return jukeboxStatus;
- }
-} \ No newline at end of file
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/LicenseParser.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/LicenseParser.java
deleted file mode 100644
index 636c3e6e..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/LicenseParser.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service.parser;
-
-import android.content.Context;
-import org.xmlpull.v1.XmlPullParser;
-
-import java.io.Reader;
-
-import net.sourceforge.subsonic.androidapp.domain.ServerInfo;
-import net.sourceforge.subsonic.androidapp.domain.Version;
-
-/**
- * @author Sindre Mehus
- */
-public class LicenseParser extends AbstractParser {
-
- public LicenseParser(Context context) {
- super(context);
- }
-
- public ServerInfo parse(Reader reader) throws Exception {
-
- init(reader);
-
- ServerInfo serverInfo = new ServerInfo();
- int eventType;
- do {
- eventType = nextParseEvent();
- if (eventType == XmlPullParser.START_TAG) {
- String name = getElementName();
- if ("subsonic-response".equals(name)) {
- serverInfo.setRestVersion(new Version(get("version")));
- } else if ("license".equals(name)) {
- serverInfo.setLicenseValid(getBoolean("valid"));
- } else if ("error".equals(name)) {
- handleError();
- }
- }
- } while (eventType != XmlPullParser.END_DOCUMENT);
-
- validate();
-
- return serverInfo;
- }
-} \ No newline at end of file
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/LyricsParser.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/LyricsParser.java
deleted file mode 100644
index 698fb4b8..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/LyricsParser.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2010 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service.parser;
-
-import android.content.Context;
-import net.sourceforge.subsonic.androidapp.R;
-import net.sourceforge.subsonic.androidapp.domain.Lyrics;
-import net.sourceforge.subsonic.androidapp.util.ProgressListener;
-import org.xmlpull.v1.XmlPullParser;
-
-import java.io.Reader;
-
-/**
- * @author Sindre Mehus
- */
-public class LyricsParser extends AbstractParser {
-
- public LyricsParser(Context context) {
- super(context);
- }
-
- public Lyrics parse(Reader reader, ProgressListener progressListener) throws Exception {
- updateProgress(progressListener, R.string.parser_reading);
- init(reader);
-
- Lyrics lyrics = null;
- int eventType;
- do {
- eventType = nextParseEvent();
- if (eventType == XmlPullParser.START_TAG) {
- String name = getElementName();
- if ("lyrics".equals(name)) {
- lyrics = new Lyrics();
- lyrics.setArtist(get("artist"));
- lyrics.setTitle(get("title"));
- } else if ("error".equals(name)) {
- handleError();
- }
- } else if (eventType == XmlPullParser.TEXT) {
- if (lyrics != null && lyrics.getText() == null) {
- lyrics.setText(getText());
- }
- }
- } while (eventType != XmlPullParser.END_DOCUMENT);
-
- validate();
- return lyrics;
- }
-}
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/MusicDirectoryEntryParser.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/MusicDirectoryEntryParser.java
deleted file mode 100644
index 3da90613..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/MusicDirectoryEntryParser.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service.parser;
-
-import android.content.Context;
-import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
-
-/**
- * @author Sindre Mehus
- */
-public class MusicDirectoryEntryParser extends AbstractParser {
-
- public MusicDirectoryEntryParser(Context context) {
- super(context);
- }
-
- protected MusicDirectory.Entry parseEntry() {
- MusicDirectory.Entry entry = new MusicDirectory.Entry();
- entry.setId(get("id"));
- entry.setParent(get("parent"));
- entry.setTitle(get("title"));
- entry.setDirectory(getBoolean("isDir"));
- entry.setCoverArt(get("coverArt"));
- entry.setArtist(get("artist"));
-
- if (!entry.isDirectory()) {
- entry.setAlbum(get("album"));
- entry.setTrack(getInteger("track"));
- entry.setYear(getInteger("year"));
- entry.setGenre(get("genre"));
- entry.setContentType(get("contentType"));
- entry.setSuffix(get("suffix"));
- entry.setTranscodedContentType(get("transcodedContentType"));
- entry.setTranscodedSuffix(get("transcodedSuffix"));
- entry.setSize(getLong("size"));
- entry.setDuration(getInteger("duration"));
- entry.setBitRate(getInteger("bitRate"));
- entry.setPath(get("path"));
- entry.setVideo(getBoolean("isVideo"));
- }
- return entry;
- }
-} \ No newline at end of file
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/MusicDirectoryParser.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/MusicDirectoryParser.java
deleted file mode 100644
index b818fc3d..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/MusicDirectoryParser.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service.parser;
-
-import android.content.Context;
-import android.util.Log;
-import net.sourceforge.subsonic.androidapp.R;
-import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
-import net.sourceforge.subsonic.androidapp.util.ProgressListener;
-import org.xmlpull.v1.XmlPullParser;
-
-import java.io.Reader;
-
-/**
- * @author Sindre Mehus
- */
-public class MusicDirectoryParser extends MusicDirectoryEntryParser {
-
- private static final String TAG = MusicDirectoryParser.class.getSimpleName();
-
- public MusicDirectoryParser(Context context) {
- super(context);
- }
-
- public MusicDirectory parse(Reader reader, ProgressListener progressListener) throws Exception {
-
- long t0 = System.currentTimeMillis();
- updateProgress(progressListener, R.string.parser_reading);
- init(reader);
-
- MusicDirectory dir = new MusicDirectory();
- int eventType;
- do {
- eventType = nextParseEvent();
- if (eventType == XmlPullParser.START_TAG) {
- String name = getElementName();
- if ("child".equals(name)) {
- dir.addChild(parseEntry());
- } else if ("directory".equals(name)) {
- dir.setName(get("name"));
- } else if ("error".equals(name)) {
- handleError();
- }
- }
- } while (eventType != XmlPullParser.END_DOCUMENT);
-
- validate();
- updateProgress(progressListener, R.string.parser_reading_done);
-
- long t1 = System.currentTimeMillis();
- Log.d(TAG, "Got music directory in " + (t1 - t0) + "ms.");
-
- return dir;
- }
-} \ No newline at end of file
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/MusicFoldersParser.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/MusicFoldersParser.java
deleted file mode 100644
index 35057bd9..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/MusicFoldersParser.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service.parser;
-
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.content.Context;
-import net.sourceforge.subsonic.androidapp.R;
-import net.sourceforge.subsonic.androidapp.domain.MusicFolder;
-import net.sourceforge.subsonic.androidapp.domain.Playlist;
-import net.sourceforge.subsonic.androidapp.util.ProgressListener;
-
-/**
- * @author Sindre Mehus
- */
-public class MusicFoldersParser extends AbstractParser {
-
- public MusicFoldersParser(Context context) {
- super(context);
- }
-
- public List<MusicFolder> parse(Reader reader, ProgressListener progressListener) throws Exception {
-
- updateProgress(progressListener, R.string.parser_reading);
- init(reader);
-
- List<MusicFolder> result = new ArrayList<MusicFolder>();
- int eventType;
- do {
- eventType = nextParseEvent();
- if (eventType == XmlPullParser.START_TAG) {
- String tag = getElementName();
- if ("musicFolder".equals(tag)) {
- String id = get("id");
- String name = get("name");
- result.add(new MusicFolder(id, name));
- } else if ("error".equals(tag)) {
- handleError();
- }
- }
- } while (eventType != XmlPullParser.END_DOCUMENT);
-
- validate();
- updateProgress(progressListener, R.string.parser_reading_done);
-
- return result;
- }
-
-} \ No newline at end of file
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/PlaylistParser.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/PlaylistParser.java
deleted file mode 100644
index ee829639..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/PlaylistParser.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service.parser;
-
-import android.content.Context;
-import net.sourceforge.subsonic.androidapp.R;
-import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
-import net.sourceforge.subsonic.androidapp.util.ProgressListener;
-import org.xmlpull.v1.XmlPullParser;
-
-import java.io.Reader;
-
-/**
- * @author Sindre Mehus
- */
-public class PlaylistParser extends MusicDirectoryEntryParser {
-
- public PlaylistParser(Context context) {
- super(context);
- }
-
- public MusicDirectory parse(Reader reader, ProgressListener progressListener) throws Exception {
- updateProgress(progressListener, R.string.parser_reading);
- init(reader);
-
- MusicDirectory dir = new MusicDirectory();
- int eventType;
- do {
- eventType = nextParseEvent();
- if (eventType == XmlPullParser.START_TAG) {
- String name = getElementName();
- if ("entry".equals(name)) {
- dir.addChild(parseEntry());
- } else if ("error".equals(name)) {
- handleError();
- }
- }
- } while (eventType != XmlPullParser.END_DOCUMENT);
-
- validate();
- updateProgress(progressListener, R.string.parser_reading_done);
-
- return dir;
- }
-
-} \ No newline at end of file
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/PlaylistsParser.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/PlaylistsParser.java
deleted file mode 100644
index c1b88b8c..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/PlaylistsParser.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service.parser;
-
-import android.content.Context;
-import net.sourceforge.subsonic.androidapp.R;
-import net.sourceforge.subsonic.androidapp.domain.Playlist;
-import net.sourceforge.subsonic.androidapp.util.ProgressListener;
-import org.xmlpull.v1.XmlPullParser;
-
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author Sindre Mehus
- */
-public class PlaylistsParser extends AbstractParser {
-
- public PlaylistsParser(Context context) {
- super(context);
- }
-
- public List<Playlist> parse(Reader reader, ProgressListener progressListener) throws Exception {
-
- updateProgress(progressListener, R.string.parser_reading);
- init(reader);
-
- List<Playlist> result = new ArrayList<Playlist>();
- int eventType;
- do {
- eventType = nextParseEvent();
- if (eventType == XmlPullParser.START_TAG) {
- String tag = getElementName();
- if ("playlist".equals(tag)) {
- String id = get("id");
- String name = get("name");
- result.add(new Playlist(id, name));
- } else if ("error".equals(tag)) {
- handleError();
- }
- }
- } while (eventType != XmlPullParser.END_DOCUMENT);
-
- validate();
- updateProgress(progressListener, R.string.parser_reading_done);
-
- return result;
- }
-
-} \ No newline at end of file
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/RandomSongsParser.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/RandomSongsParser.java
deleted file mode 100644
index 0bf422b7..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/RandomSongsParser.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service.parser;
-
-import android.content.Context;
-import net.sourceforge.subsonic.androidapp.R;
-import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
-import net.sourceforge.subsonic.androidapp.util.ProgressListener;
-import org.xmlpull.v1.XmlPullParser;
-
-import java.io.Reader;
-
-/**
- * @author Sindre Mehus
- */
-public class RandomSongsParser extends MusicDirectoryEntryParser {
-
- public RandomSongsParser(Context context) {
- super(context);
- }
-
- public MusicDirectory parse(Reader reader, ProgressListener progressListener) throws Exception {
- updateProgress(progressListener, R.string.parser_reading);
- init(reader);
-
- MusicDirectory dir = new MusicDirectory();
- int eventType;
- do {
- eventType = nextParseEvent();
- if (eventType == XmlPullParser.START_TAG) {
- String name = getElementName();
- if ("song".equals(name)) {
- dir.addChild(parseEntry());
- } else if ("error".equals(name)) {
- handleError();
- }
- }
- } while (eventType != XmlPullParser.END_DOCUMENT);
-
- validate();
- updateProgress(progressListener, R.string.parser_reading_done);
-
- return dir;
- }
-
-} \ No newline at end of file
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/SearchResult2Parser.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/SearchResult2Parser.java
deleted file mode 100644
index 01052f25..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/SearchResult2Parser.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service.parser;
-
-import android.content.Context;
-import net.sourceforge.subsonic.androidapp.R;
-import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
-import net.sourceforge.subsonic.androidapp.domain.SearchResult;
-import net.sourceforge.subsonic.androidapp.domain.Artist;
-import net.sourceforge.subsonic.androidapp.util.ProgressListener;
-import org.xmlpull.v1.XmlPullParser;
-
-import java.io.Reader;
-import java.util.List;
-import java.util.ArrayList;
-
-/**
- * @author Sindre Mehus
- */
-public class SearchResult2Parser extends MusicDirectoryEntryParser {
-
- public SearchResult2Parser(Context context) {
- super(context);
- }
-
- public SearchResult parse(Reader reader, ProgressListener progressListener) throws Exception {
- updateProgress(progressListener, R.string.parser_reading);
- init(reader);
-
- List<Artist> artists = new ArrayList<Artist>();
- List<MusicDirectory.Entry> albums = new ArrayList<MusicDirectory.Entry>();
- List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>();
- int eventType;
- do {
- eventType = nextParseEvent();
- if (eventType == XmlPullParser.START_TAG) {
- String name = getElementName();
- if ("artist".equals(name)) {
- Artist artist = new Artist();
- artist.setId(get("id"));
- artist.setName(get("name"));
- artists.add(artist);
- } else if ("album".equals(name)) {
- albums.add(parseEntry());
- } else if ("song".equals(name)) {
- songs.add(parseEntry());
- } else if ("error".equals(name)) {
- handleError();
- }
- }
- } while (eventType != XmlPullParser.END_DOCUMENT);
-
- validate();
- updateProgress(progressListener, R.string.parser_reading_done);
-
- return new SearchResult(artists, albums, songs);
- }
-
-} \ No newline at end of file
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/SearchResultParser.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/SearchResultParser.java
deleted file mode 100644
index c38b077f..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/SearchResultParser.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service.parser;
-
-import android.content.Context;
-import net.sourceforge.subsonic.androidapp.R;
-import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
-import net.sourceforge.subsonic.androidapp.domain.SearchResult;
-import net.sourceforge.subsonic.androidapp.domain.Artist;
-import net.sourceforge.subsonic.androidapp.util.ProgressListener;
-import org.xmlpull.v1.XmlPullParser;
-
-import java.io.Reader;
-import java.util.Collections;
-import java.util.List;
-import java.util.ArrayList;
-
-/**
- * @author Sindre Mehus
- */
-public class SearchResultParser extends MusicDirectoryEntryParser {
-
- public SearchResultParser(Context context) {
- super(context);
- }
-
- public SearchResult parse(Reader reader, ProgressListener progressListener) throws Exception {
- updateProgress(progressListener, R.string.parser_reading);
- init(reader);
-
- List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>();
- int eventType;
- do {
- eventType = nextParseEvent();
- if (eventType == XmlPullParser.START_TAG) {
- String name = getElementName();
- if ("match".equals(name)) {
- songs.add(parseEntry());
- } else if ("error".equals(name)) {
- handleError();
- }
- }
- } while (eventType != XmlPullParser.END_DOCUMENT);
-
- validate();
- updateProgress(progressListener, R.string.parser_reading_done);
-
- return new SearchResult(Collections.<Artist>emptyList(), Collections.<MusicDirectory.Entry>emptyList(), songs);
- }
-
-}
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/SubsonicRESTException.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/SubsonicRESTException.java
deleted file mode 100644
index b46b6f22..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/SubsonicRESTException.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package net.sourceforge.subsonic.androidapp.service.parser;
-
-/**
- * @author Sindre Mehus
- * @version $Id$
- */
-public class SubsonicRESTException extends Exception {
-
- private final int code;
-
- public SubsonicRESTException(int code, String message) {
- super(message);
- this.code = code;
- }
-
- public int getCode() {
- return code;
- }
-}
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/VersionParser.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/VersionParser.java
deleted file mode 100644
index b8a05531..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/parser/VersionParser.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.service.parser;
-
-import net.sourceforge.subsonic.androidapp.domain.Version;
-
-import java.io.BufferedReader;
-import java.io.Reader;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * @author Sindre Mehus
- */
-public class VersionParser {
-
- public Version parse(Reader reader) throws Exception {
-
- BufferedReader bufferedReader = new BufferedReader(reader);
- Pattern pattern = Pattern.compile("SUBSONIC_ANDROID_VERSION_BEGIN(.*)SUBSONIC_ANDROID_VERSION_END");
- String line = bufferedReader.readLine();
- while (line != null) {
- Matcher finalMatcher = pattern.matcher(line);
- if (finalMatcher.find()) {
- return new Version(finalMatcher.group(1));
- }
- line = bufferedReader.readLine();
- }
- return null;
- }
-} \ No newline at end of file
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ssl/SSLSocketFactory.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ssl/SSLSocketFactory.java
deleted file mode 100644
index 0e146650..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ssl/SSLSocketFactory.java
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package net.sourceforge.subsonic.androidapp.service.ssl;
-
-import org.apache.http.conn.ConnectTimeoutException;
-import org.apache.http.conn.scheme.HostNameResolver;
-import org.apache.http.conn.scheme.LayeredSocketFactory;
-import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
-import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
-import org.apache.http.conn.ssl.StrictHostnameVerifier;
-import org.apache.http.conn.ssl.X509HostnameVerifier;
-import org.apache.http.params.HttpConnectionParams;
-import org.apache.http.params.HttpParams;
-
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
-import java.security.KeyManagementException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.security.UnrecoverableKeyException;
-
-/**
- * Layered socket factory for TLS/SSL connections.
- * <p>
- * SSLSocketFactory can be used to validate the identity of the HTTPS server against a list of
- * trusted certificates and to authenticate to the HTTPS server using a private key.
- * <p>
- * SSLSocketFactory will enable server authentication when supplied with
- * a {@link KeyStore trust-store} file containing one or several trusted certificates. The client
- * secure socket will reject the connection during the SSL session handshake if the target HTTPS
- * server attempts to authenticate itself with a non-trusted certificate.
- * <p>
- * Use JDK keytool utility to import a trusted certificate and generate a trust-store file:
- * <pre>
- * keytool -import -alias "my server cert" -file server.crt -keystore my.truststore
- * </pre>
- * <p>
- * In special cases the standard trust verification process can be bypassed by using a custom
- * {@link TrustStrategy}. This interface is primarily intended for allowing self-signed
- * certificates to be accepted as trusted without having to add them to the trust-store file.
- * <p>
- * The following parameters can be used to customize the behavior of this
- * class:
- * <ul>
- * <li>{@link org.apache.http.params.CoreConnectionPNames#CONNECTION_TIMEOUT}</li>
- * <li>{@link org.apache.http.params.CoreConnectionPNames#SO_TIMEOUT}</li>
- * </ul>
- * <p>
- * SSLSocketFactory will enable client authentication when supplied with
- * a {@link KeyStore key-store} file containing a private key/public certificate
- * pair. The client secure socket will use the private key to authenticate
- * itself to the target HTTPS server during the SSL session handshake if
- * requested to do so by the server.
- * The target HTTPS server will in its turn verify the certificate presented
- * by the client in order to establish client's authenticity
- * <p>
- * Use the following sequence of actions to generate a key-store file
- * </p>
- * <ul>
- * <li>
- * <p>
- * Use JDK keytool utility to generate a new key
- * <pre>keytool -genkey -v -alias "my client key" -validity 365 -keystore my.keystore</pre>
- * For simplicity use the same password for the key as that of the key-store
- * </p>
- * </li>
- * <li>
- * <p>
- * Issue a certificate signing request (CSR)
- * <pre>keytool -certreq -alias "my client key" -file mycertreq.csr -keystore my.keystore</pre>
- * </p>
- * </li>
- * <li>
- * <p>
- * Send the certificate request to the trusted Certificate Authority for signature.
- * One may choose to act as her own CA and sign the certificate request using a PKI
- * tool, such as OpenSSL.
- * </p>
- * </li>
- * <li>
- * <p>
- * Import the trusted CA root certificate
- * <pre>keytool -import -alias "my trusted ca" -file caroot.crt -keystore my.keystore</pre>
- * </p>
- * </li>
- * <li>
- * <p>
- * Import the PKCS#7 file containg the complete certificate chain
- * <pre>keytool -import -alias "my client key" -file mycert.p7 -keystore my.keystore</pre>
- * </p>
- * </li>
- * <li>
- * <p>
- * Verify the content the resultant keystore file
- * <pre>keytool -list -v -keystore my.keystore</pre>
- * </p>
- * </li>
- * </ul>
- *
- * @since 4.0
- */
-public class SSLSocketFactory implements LayeredSocketFactory {
-
- public static final String TLS = "TLS";
- public static final String SSL = "SSL";
- public static final String SSLV2 = "SSLv2";
-
- public static final X509HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER
- = new AllowAllHostnameVerifier();
-
- public static final X509HostnameVerifier BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
- = new BrowserCompatHostnameVerifier();
-
- public static final X509HostnameVerifier STRICT_HOSTNAME_VERIFIER
- = new StrictHostnameVerifier();
-
- /**
- * The default factory using the default JVM settings for secure connections.
- */
- private static final SSLSocketFactory DEFAULT_FACTORY = new SSLSocketFactory();
-
- /**
- * Gets the default factory, which uses the default JVM settings for secure
- * connections.
- *
- * @return the default factory
- */
- public static SSLSocketFactory getSocketFactory() {
- return DEFAULT_FACTORY;
- }
-
- private final javax.net.ssl.SSLSocketFactory socketfactory;
- private final HostNameResolver nameResolver;
- // TODO: make final
- private volatile X509HostnameVerifier hostnameVerifier;
-
- private static SSLContext createSSLContext(
- String algorithm,
- final KeyStore keystore,
- final String keystorePassword,
- final KeyStore truststore,
- final SecureRandom random,
- final TrustStrategy trustStrategy)
- throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException, KeyManagementException {
- if (algorithm == null) {
- algorithm = TLS;
- }
- KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(
- KeyManagerFactory.getDefaultAlgorithm());
- kmfactory.init(keystore, keystorePassword != null ? keystorePassword.toCharArray(): null);
- KeyManager[] keymanagers = kmfactory.getKeyManagers();
- TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(
- TrustManagerFactory.getDefaultAlgorithm());
- tmfactory.init(keystore);
- TrustManager[] trustmanagers = tmfactory.getTrustManagers();
- if (trustmanagers != null && trustStrategy != null) {
- for (int i = 0; i < trustmanagers.length; i++) {
- TrustManager tm = trustmanagers[i];
- if (tm instanceof X509TrustManager) {
- trustmanagers[i] = new TrustManagerDecorator(
- (X509TrustManager) tm, trustStrategy);
- }
- }
- }
-
- SSLContext sslcontext = SSLContext.getInstance(algorithm);
- sslcontext.init(keymanagers, trustmanagers, random);
- return sslcontext;
- }
-
- /**
- * @deprecated Use {@link #SSLSocketFactory(String, KeyStore, String, KeyStore, SecureRandom, X509HostnameVerifier)}
- */
- @Deprecated
- public SSLSocketFactory(
- final String algorithm,
- final KeyStore keystore,
- final String keystorePassword,
- final KeyStore truststore,
- final SecureRandom random,
- final HostNameResolver nameResolver)
- throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
- this(createSSLContext(
- algorithm, keystore, keystorePassword, truststore, random, null),
- nameResolver);
- }
-
- /**
- * @since 4.1
- */
- public SSLSocketFactory(
- String algorithm,
- final KeyStore keystore,
- final String keystorePassword,
- final KeyStore truststore,
- final SecureRandom random,
- final X509HostnameVerifier hostnameVerifier)
- throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
- this(createSSLContext(
- algorithm, keystore, keystorePassword, truststore, random, null),
- hostnameVerifier);
- }
-
- /**
- * @since 4.1
- */
- public SSLSocketFactory(
- String algorithm,
- final KeyStore keystore,
- final String keystorePassword,
- final KeyStore truststore,
- final SecureRandom random,
- final TrustStrategy trustStrategy,
- final X509HostnameVerifier hostnameVerifier)
- throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
- this(createSSLContext(
- algorithm, keystore, keystorePassword, truststore, random, trustStrategy),
- hostnameVerifier);
- }
-
- public SSLSocketFactory(
- final KeyStore keystore,
- final String keystorePassword,
- final KeyStore truststore)
- throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
- this(TLS, keystore, keystorePassword, truststore, null, null, BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
- }
-
- public SSLSocketFactory(
- final KeyStore keystore,
- final String keystorePassword)
- throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException{
- this(TLS, keystore, keystorePassword, null, null, null, BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
- }
-
- public SSLSocketFactory(
- final KeyStore truststore)
- throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
- this(TLS, null, null, truststore, null, null, BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
- }
-
- /**
- * @since 4.1
- */
- public SSLSocketFactory(
- final TrustStrategy trustStrategy,
- final X509HostnameVerifier hostnameVerifier)
- throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
- this(TLS, null, null, null, null, trustStrategy, hostnameVerifier);
- }
-
- /**
- * @since 4.1
- */
- public SSLSocketFactory(
- final TrustStrategy trustStrategy)
- throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
- this(TLS, null, null, null, null, trustStrategy, BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
- }
-
- public SSLSocketFactory(final SSLContext sslContext) {
- this(sslContext, BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
- }
-
- /**
- * @deprecated Use {@link #SSLSocketFactory(SSLContext)}
- */
- @Deprecated
- public SSLSocketFactory(
- final SSLContext sslContext, final HostNameResolver nameResolver) {
- super();
- this.socketfactory = sslContext.getSocketFactory();
- this.hostnameVerifier = BROWSER_COMPATIBLE_HOSTNAME_VERIFIER;
- this.nameResolver = nameResolver;
- }
-
- /**
- * @since 4.1
- */
- public SSLSocketFactory(
- final SSLContext sslContext, final X509HostnameVerifier hostnameVerifier) {
- super();
- this.socketfactory = sslContext.getSocketFactory();
- this.hostnameVerifier = hostnameVerifier;
- this.nameResolver = null;
- }
-
- private SSLSocketFactory() {
- super();
- this.socketfactory = HttpsURLConnection.getDefaultSSLSocketFactory();
- this.hostnameVerifier = null;
- this.nameResolver = null;
- }
-
- /**
- * @param params Optional parameters. Parameters passed to this method will have no effect.
- * This method will create a unconnected instance of {@link Socket} class
- * using {@link javax.net.ssl.SSLSocketFactory#createSocket()} method.
- * @since 4.1
- */
- @SuppressWarnings("cast")
- public Socket createSocket(final HttpParams params) throws IOException {
- // the cast makes sure that the factory is working as expected
- return (SSLSocket) this.socketfactory.createSocket();
- }
-
- @SuppressWarnings("cast")
- public Socket createSocket() throws IOException {
- // the cast makes sure that the factory is working as expected
- return (SSLSocket) this.socketfactory.createSocket();
- }
-
- /**
- * @since 4.1
- */
- public Socket connectSocket(
- final Socket sock,
- final InetSocketAddress remoteAddress,
- final InetSocketAddress localAddress,
- final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
- if (remoteAddress == null) {
- throw new IllegalArgumentException("Remote address may not be null");
- }
- if (params == null) {
- throw new IllegalArgumentException("HTTP parameters may not be null");
- }
- SSLSocket sslsock = (SSLSocket) (sock != null ? sock : createSocket());
- if (localAddress != null) {
-// sslsock.setReuseAddress(HttpConnectionParams.getSoReuseaddr(params));
- sslsock.bind(localAddress);
- }
-
- int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
- int soTimeout = HttpConnectionParams.getSoTimeout(params);
-
- try {
- sslsock.connect(remoteAddress, connTimeout);
- } catch (SocketTimeoutException ex) {
- throw new ConnectTimeoutException("Connect to " + remoteAddress.getHostName() + "/"
- + remoteAddress.getAddress() + " timed out");
- }
- sslsock.setSoTimeout(soTimeout);
- if (this.hostnameVerifier != null) {
- try {
- this.hostnameVerifier.verify(remoteAddress.getHostName(), sslsock);
- // verifyHostName() didn't blowup - good!
- } catch (IOException iox) {
- // close the socket before re-throwing the exception
- try { sslsock.close(); } catch (Exception x) { /*ignore*/ }
- throw iox;
- }
- }
- return sslsock;
- }
-
-
- /**
- * Checks whether a socket connection is secure.
- * This factory creates TLS/SSL socket connections
- * which, by default, are considered secure.
- * <br/>
- * Derived classes may override this method to perform
- * runtime checks, for example based on the cypher suite.
- *
- * @param sock the connected socket
- *
- * @return <code>true</code>
- *
- * @throws IllegalArgumentException if the argument is invalid
- */
- public boolean isSecure(final Socket sock) throws IllegalArgumentException {
- if (sock == null) {
- throw new IllegalArgumentException("Socket may not be null");
- }
- // This instanceof check is in line with createSocket() above.
- if (!(sock instanceof SSLSocket)) {
- throw new IllegalArgumentException("Socket not created by this factory");
- }
- // This check is performed last since it calls the argument object.
- if (sock.isClosed()) {
- throw new IllegalArgumentException("Socket is closed");
- }
- return true;
- }
-
- /**
- * @since 4.1
- */
- public Socket createLayeredSocket(
- final Socket socket,
- final String host,
- final int port,
- final boolean autoClose) throws IOException, UnknownHostException {
- SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket(
- socket,
- host,
- port,
- autoClose
- );
- if (this.hostnameVerifier != null) {
- this.hostnameVerifier.verify(host, sslSocket);
- }
- // verifyHostName() didn't blowup - good!
- return sslSocket;
- }
-
- @Deprecated
- public void setHostnameVerifier(X509HostnameVerifier hostnameVerifier) {
- if ( hostnameVerifier == null ) {
- throw new IllegalArgumentException("Hostname verifier may not be null");
- }
- this.hostnameVerifier = hostnameVerifier;
- }
-
- public X509HostnameVerifier getHostnameVerifier() {
- return this.hostnameVerifier;
- }
-
- /**
- * @deprecated Use {@link #connectSocket(Socket, InetSocketAddress, InetSocketAddress, HttpParams)}
- */
- @Deprecated
- public Socket connectSocket(
- final Socket socket,
- final String host, int port,
- final InetAddress localAddress, int localPort,
- final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
- InetSocketAddress local = null;
- if (localAddress != null || localPort > 0) {
- // we need to bind explicitly
- if (localPort < 0) {
- localPort = 0; // indicates "any"
- }
- local = new InetSocketAddress(localAddress, localPort);
- }
- InetAddress remoteAddress;
- if (this.nameResolver != null) {
- remoteAddress = this.nameResolver.resolve(host);
- } else {
- remoteAddress = InetAddress.getByName(host);
- }
- InetSocketAddress remote = new InetSocketAddress(remoteAddress, port);
- return connectSocket(socket, remote, local, params);
- }
-
- /**
- * @deprecated Use {@link #createLayeredSocket(Socket, String, int, boolean)}
- */
- @Deprecated
- public Socket createSocket(
- final Socket socket,
- final String host, int port,
- boolean autoClose) throws IOException, UnknownHostException {
- return createLayeredSocket(socket, host, port, autoClose);
- }
-
-}
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ssl/TrustManagerDecorator.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ssl/TrustManagerDecorator.java
deleted file mode 100644
index 41d98249..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ssl/TrustManagerDecorator.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-package net.sourceforge.subsonic.androidapp.service.ssl;
-
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.X509TrustManager;
-
-
-/**
- * @since 4.1
- */
-class TrustManagerDecorator implements X509TrustManager {
-
- private final X509TrustManager trustManager;
- private final TrustStrategy trustStrategy;
-
- TrustManagerDecorator(final X509TrustManager trustManager, final TrustStrategy trustStrategy) {
- super();
- this.trustManager = trustManager;
- this.trustStrategy = trustStrategy;
- }
-
- public void checkClientTrusted(
- final X509Certificate[] chain, final String authType) throws CertificateException {
- this.trustManager.checkClientTrusted(chain, authType);
- }
-
- public void checkServerTrusted(
- final X509Certificate[] chain, final String authType) throws CertificateException {
- if (!this.trustStrategy.isTrusted(chain, authType)) {
- this.trustManager.checkServerTrusted(chain, authType);
- }
- }
-
- public X509Certificate[] getAcceptedIssuers() {
- return this.trustManager.getAcceptedIssuers();
- }
-
-}
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ssl/TrustSelfSignedStrategy.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ssl/TrustSelfSignedStrategy.java
deleted file mode 100644
index 4fdaaba2..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ssl/TrustSelfSignedStrategy.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-package net.sourceforge.subsonic.androidapp.service.ssl;
-
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-
-/**
- * A trust strategy that accepts self-signed certificates as trusted. Verification of all other
- * certificates is done by the trust manager configured in the SSL context.
- *
- * @since 4.1
- */
-public class TrustSelfSignedStrategy implements TrustStrategy {
-
- public boolean isTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {
- return true;
- }
-
-}
diff --git a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ssl/TrustStrategy.java b/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ssl/TrustStrategy.java
deleted file mode 100644
index 3cf75b68..00000000
--- a/subsonic-android/src/net/sourceforge/subsonic/androidapp/service/ssl/TrustStrategy.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-package net.sourceforge.subsonic.androidapp.service.ssl;
-
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-
-/**
- * A strategy to establish trustworthiness of certificates without consulting the trust manager
- * configured in the actual SSL context. This interface can be used to override the standard
- * JSSE certificate verification process.
- *
- * @since 4.1
- */
-public interface TrustStrategy {
-
- /**
- * Determines whether the certificate chain can be trusted without consulting the trust manager
- * configured in the actual SSL context. This method can be used to override the standard JSSE
- * certificate verification process.
- * <p>
- * Please note that, if this method returns <code>false</code>, the trust manager configured
- * in the actual SSL context can still clear the certificate as trusted.
- *
- * @param chain the peer certificate chain
- * @param authType the authentication type based on the client certificate
- * @return <code>true</code> if the certificate can be trusted without verification by
- * the trust manager, <code>false</code> otherwise.
- * @throws CertificateException thrown if the certificate is not trusted or invalid.
- */
- boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException;
-
-}