aboutsummaryrefslogtreecommitdiff
path: root/subsonic-android/src
diff options
context:
space:
mode:
authorScott Jackson <daneren2005@gmail.com>2012-11-25 12:09:19 -0800
committerScott Jackson <daneren2005@gmail.com>2012-11-25 12:09:19 -0800
commitf208d0562a619596ebf0ba982599564e7f860756 (patch)
tree2086621d0ca152e80eac35e4e8438d6b758ce057 /subsonic-android/src
parent4770337d1e8c78facb5fe4f5bf7bfcd428e2cfa9 (diff)
parent836141bc69e30848adf049a50a95cf4d81c38cc1 (diff)
downloaddsub-f208d0562a619596ebf0ba982599564e7f860756.tar.gz
dsub-f208d0562a619596ebf0ba982599564e7f860756.tar.bz2
dsub-f208d0562a619596ebf0ba982599564e7f860756.zip
Merge branch 'master' of https://github.com/daneren2005/Subsonic.git
Diffstat (limited to 'subsonic-android/src')
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/activity/PlayVideoActivity.java147
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/activity/SelectAlbumActivity.java114
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/service/CachedMusicService.java17
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/service/DownloadService.java2
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java5
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/service/MusicService.java6
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java23
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java46
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/util/FileUtil.java18
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/util/ShufflePlayBuffer.java12
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/util/Util.java11
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/view/SongView.java10
12 files changed, 228 insertions, 183 deletions
diff --git a/subsonic-android/src/github/daneren2005/dsub/activity/PlayVideoActivity.java b/subsonic-android/src/github/daneren2005/dsub/activity/PlayVideoActivity.java
deleted file mode 100644
index 7a77736e..00000000
--- a/subsonic-android/src/github/daneren2005/dsub/activity/PlayVideoActivity.java
+++ /dev/null
@@ -1,147 +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 github.daneren2005.dsub.activity;
-
-import java.lang.reflect.Method;
-
-import android.app.Activity;
-import android.graphics.Bitmap;
-import android.media.AudioManager;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.Window;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import github.daneren2005.dsub.R;
-import github.daneren2005.dsub.service.MusicServiceFactory;
-import github.daneren2005.dsub.util.Constants;
-import github.daneren2005.dsub.util.Util;
-
-/**
- * Plays videos in a web page.
- *
- * @author Sindre Mehus
- */
-public final class PlayVideoActivity extends Activity {
-
- private static final String TAG = PlayVideoActivity.class.getSimpleName();
- private WebView webView;
-
- @Override
- protected void onCreate(Bundle bundle) {
- super.onCreate(bundle);
- getWindow().requestFeature(Window.FEATURE_NO_TITLE);
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
-
- setContentView(R.layout.play_video);
-
- webView = (WebView) findViewById(R.id.play_video_contents);
- webView.getSettings().setJavaScriptEnabled(true);
- webView.getSettings().setPluginsEnabled(true);
- webView.getSettings().setAllowFileAccess(true);
- webView.getSettings().setSupportZoom(true);
- webView.getSettings().setBuiltInZoomControls(true);
-
- webView.setWebViewClient(new Client());
- if (bundle != null) {
- webView.restoreState(bundle);
- } else {
- webView.loadUrl(getVideoUrl());
- }
-
- // Show warning if Flash plugin is not installed.
- if (isFlashPluginInstalled()) {
- Util.toast(this, R.string.play_video_loading, false);
- } else {
- Util.toast(this, R.string.play_video_noplugin, false);
- }
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- callHiddenWebViewMethod("onPause");
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- callHiddenWebViewMethod("onResume");
- }
-
- private String getVideoUrl() {
- String id = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ID);
- return MusicServiceFactory.getMusicService(this).getVideoUrl(this, id);
- }
-
- @Override
- protected void onSaveInstanceState(Bundle state) {
- webView.saveState(state);
- }
-
- private void callHiddenWebViewMethod(String name){
- if( webView != null ){
- try {
- Method method = WebView.class.getMethod(name);
- method.invoke(webView);
- } catch (Throwable x) {
- Log.e(TAG, "Failed to invoke " + name, x);
- }
- }
- }
-
- private boolean isFlashPluginInstalled() {
- try {
- PackageInfo packageInfo = getPackageManager().getPackageInfo("com.adobe.flashplayer", 0);
- return packageInfo != null;
- } catch (PackageManager.NameNotFoundException x) {
- return false;
- }
- }
-
- private final class Client extends WebViewClient {
-
- @Override
- public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
- Util.toast(PlayVideoActivity.this, description);
- Log.e(TAG, "Error: " + description);
- }
-
- @Override
- public void onLoadResource(WebView view, String url) {
- super.onLoadResource(view, url);
- Log.d(TAG, "onLoadResource: " + url);
- }
-
- @Override
- public void onPageStarted(WebView view, String url, Bitmap favicon) {
- super.onPageStarted(view, url, favicon);
- Log.d(TAG, "onPageStarted: " + url);
- }
-
- @Override
- public void onPageFinished(WebView view, String url) {
- super.onPageFinished(view, url);
- Log.d(TAG, "onPageFinished: " + url);
- }
- }
-}
diff --git a/subsonic-android/src/github/daneren2005/dsub/activity/SelectAlbumActivity.java b/subsonic-android/src/github/daneren2005/dsub/activity/SelectAlbumActivity.java
index ccd5d5af..891c2edd 100644
--- a/subsonic-android/src/github/daneren2005/dsub/activity/SelectAlbumActivity.java
+++ b/subsonic-android/src/github/daneren2005/dsub/activity/SelectAlbumActivity.java
@@ -34,14 +34,11 @@ import android.widget.*;
import com.actionbarsherlock.view.Menu;
import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.MusicDirectory;
-import github.daneren2005.dsub.service.MusicService;
-import github.daneren2005.dsub.service.MusicServiceFactory;
+import github.daneren2005.dsub.service.*;
import github.daneren2005.dsub.util.*;
+import java.io.File;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
public class SelectAlbumActivity extends SubsonicTabActivity {
@@ -78,7 +75,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, entry.getTitle());
Util.startActivityWithoutTransition(SelectAlbumActivity.this, intent);
} else if (entry.isVideo()) {
- playVideo(entry);
+ playExternalPlayer(entry);
}
}
}
@@ -113,10 +110,17 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
inflater.inflate(R.menu.select_album, menu);
hideButtons = false;
} else {
- if(Util.isOffline(this))
+ if(Util.isOffline(this)) {
inflater.inflate(R.menu.select_song_offline, menu);
- else
+ }
+ else {
inflater.inflate(R.menu.select_song, menu);
+
+ String playlistId = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID);
+ if(playlistId == null) {
+ menu.removeItem(R.id.menu_remove_playlist);
+ }
+ }
}
return true;
}
@@ -155,6 +159,11 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
case R.id.menu_add_playlist:
addToPlaylist(getSelectedSongs());
return true;
+ case R.id.menu_remove_playlist:
+ String playlistId = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID);
+ String playlistName = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME);
+ removeFromPlaylist(playlistId, playlistName, getSelectedIndexes());
+ return true;
case R.id.menu_exit:
intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -222,13 +231,25 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
inflater.inflate(R.menu.select_album_context_offline, menu);
else
inflater.inflate(R.menu.select_album_context, menu);
- } else {
+ } else if(!entry.isVideo()) {
MenuInflater inflater = getMenuInflater();
- if(Util.isOffline(this))
+ if(Util.isOffline(this)) {
inflater.inflate(R.menu.select_song_context_offline, menu);
- else
+ }
+ else {
inflater.inflate(R.menu.select_song_context, menu);
- }
+ String playlistId = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID);
+ if(playlistId == null) {
+ menu.removeItem(R.id.song_menu_remove_playlist);
+ }
+ }
+ } else {
+ MenuInflater inflater = getMenuInflater();
+ if(Util.isOffline(this))
+ inflater.inflate(R.menu.select_video_context_offline, menu);
+ else
+ inflater.inflate(R.menu.select_video_context, menu);
+ }
if (!Util.isOffline(this)) {
menu.findItem(entry.isDirectory() ? R.id.album_menu_star : R.id.song_menu_star).setTitle(entry.isStarred() ? R.string.common_unstar : R.string.common_star);
@@ -284,6 +305,17 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
case R.id.song_menu_star:
toggleStarred(entry);
break;
+ case R.id.song_menu_webview:
+ playWebView(entry);
+ break;
+ case R.id.song_menu_play_external:
+ playExternalPlayer(entry);
+ break;
+ case R.id.song_menu_remove_playlist:
+ String playlistId = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID);
+ String playlistName = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME);
+ removeFromPlaylist(playlistId, playlistName, Arrays.<Integer>asList(info.position - 1));
+ break;
default:
return super.onContextItemSelected(menuItem);
}
@@ -411,6 +443,19 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
}
return songs;
}
+
+ private List<Integer> getSelectedIndexes() {
+ List<Integer> indexes = new ArrayList<Integer>();
+
+ int count = entryList.getCount();
+ for (int i = 0; i < count; i++) {
+ if (entryList.isItemChecked(i)) {
+ indexes.add(i - 1);
+ }
+ }
+
+ return indexes;
+ }
private void download(final boolean append, final boolean save, final boolean autoplay, final boolean playNext, final boolean shuffle) {
if (getDownloadService() == null) {
@@ -483,12 +528,22 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
}
}
- private void playVideo(MusicDirectory.Entry entry) {
+ private void playWebView(MusicDirectory.Entry entry) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(MusicServiceFactory.getMusicService(this).getVideoUrl(this, entry.getId())));
-
+
startActivity(intent);
}
+ private void playExternalPlayer(MusicDirectory.Entry entry) {
+ DownloadFile check = new DownloadFile(this, entry, false);
+ if(!check.isCompleteFileAvailable()) {
+ Util.toast(this, R.string.download_need_download);
+ } else {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setDataAndType(Uri.parse(entry.getPath()), "video/*");
+ startActivity(intent);
+ }
+ }
private void checkLicenseAndTrialPeriod(Runnable onValid) {
if (licenseValid) {
@@ -627,4 +682,33 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
return header;
}
+
+ public void removeFromPlaylist(final String id, final String name, final List<Integer> indexes) {
+ new LoadingTask<Void>(this, true) {
+ @Override
+ protected Void doInBackground() throws Throwable {
+ MusicService musicService = MusicServiceFactory.getMusicService(SelectAlbumActivity.this);
+ musicService.removeFromPlaylist(id, indexes, SelectAlbumActivity.this, null);
+ return null;
+ }
+
+ @Override
+ protected void done(Void result) {
+ refresh();
+ Util.toast(SelectAlbumActivity.this, getResources().getString(R.string.removed_playlist, indexes.size(), name));
+ }
+
+ @Override
+ protected void error(Throwable error) {
+ String msg;
+ if (error instanceof OfflineException || error instanceof ServerTooOldException) {
+ msg = getErrorMessage(error);
+ } else {
+ msg = getResources().getString(R.string.updated_playlist_error, name) + " " + getErrorMessage(error);
+ }
+
+ Util.toast(SelectAlbumActivity.this, msg, false);
+ }
+ }.execute();
+ }
}
diff --git a/subsonic-android/src/github/daneren2005/dsub/service/CachedMusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/CachedMusicService.java
index 798cf8e6..fe0a3f19 100644
--- a/subsonic-android/src/github/daneren2005/dsub/service/CachedMusicService.java
+++ b/subsonic-android/src/github/daneren2005/dsub/service/CachedMusicService.java
@@ -53,7 +53,7 @@ public class CachedMusicService implements 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<Playlist>> cachedPlaylists = new TimeLimitedCache<List<Playlist>>(3600, TimeUnit.SECONDS);
private final TimeLimitedCache<List<MusicFolder>> cachedMusicFolders = new TimeLimitedCache<List<MusicFolder>>(10 * 3600, TimeUnit.SECONDS);
private String restUrl;
@@ -146,6 +146,7 @@ public class CachedMusicService implements MusicService {
@Override
public void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries, Context context, ProgressListener progressListener) throws Exception {
+ cachedPlaylists.clear();
musicService.createPlaylist(id, name, entries, context, progressListener);
}
@@ -160,6 +161,11 @@ public class CachedMusicService implements MusicService {
}
@Override
+ public void removeFromPlaylist(String id, List<Integer> toRemove, Context context, ProgressListener progressListener) throws Exception {
+ musicService.removeFromPlaylist(id, toRemove, context, progressListener);
+ }
+
+ @Override
public void updatePlaylist(String id, String name, String comment, Context context, ProgressListener progressListener) throws Exception {
musicService.updatePlaylist(id, name, comment, context, progressListener);
}
@@ -185,8 +191,8 @@ public class CachedMusicService implements MusicService {
}
@Override
- public MusicDirectory getRandomSongs(int size, String folder, Context context, ProgressListener progressListener) throws Exception {
- return musicService.getRandomSongs(size, folder, context, progressListener);
+ public MusicDirectory getRandomSongs(int size, String folder, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception {
+ return musicService.getRandomSongs(size, folder, genre, startYear, endYear, context, progressListener);
}
@Override
@@ -213,6 +219,11 @@ public class CachedMusicService implements MusicService {
public String getVideoUrl(Context context, String id) {
return musicService.getVideoUrl(context, id);
}
+
+ @Override
+ public String getVideoStreamUrl(Context context, String id) {
+ return musicService.getVideoStreamUrl(context, id);
+ }
@Override
public JukeboxStatus updateJukeboxPlaylist(List<String> ids, Context context, ProgressListener progressListener) throws Exception {
diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadService.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadService.java
index d11c8285..f68f8db6 100644
--- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadService.java
+++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadService.java
@@ -38,6 +38,8 @@ public interface DownloadService {
void setShufflePlayEnabled(boolean enabled);
boolean isShufflePlayEnabled();
+
+ void setShuffleParams(String genre, String startYear, String endYear);
void shuffle();
diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java
index 38b3fe03..aae4829a 100644
--- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java
+++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java
@@ -299,6 +299,11 @@ public class DownloadServiceImpl extends Service implements DownloadService {
public synchronized boolean isShufflePlayEnabled() {
return shufflePlay;
}
+
+ @Override
+ public void setShuffleParams(String genre, String startYear, String endYear) {
+ shufflePlayBuffer.setOptions(genre, startYear, endYear);
+ }
@Override
public synchronized void shuffle() {
diff --git a/subsonic-android/src/github/daneren2005/dsub/service/MusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/MusicService.java
index 1dc247f1..98951853 100644
--- a/subsonic-android/src/github/daneren2005/dsub/service/MusicService.java
+++ b/subsonic-android/src/github/daneren2005/dsub/service/MusicService.java
@@ -65,6 +65,8 @@ public interface MusicService {
void addToPlaylist(String id, List<MusicDirectory.Entry> toAdd, Context context, ProgressListener progressListener) throws Exception;
+ void removeFromPlaylist(String id, List<Integer> toRemove, Context context, ProgressListener progressListener) throws Exception;
+
void updatePlaylist(String id, String name, String comment, Context context, ProgressListener progressListener) throws Exception;
Lyrics getLyrics(String artist, String title, Context context, ProgressListener progressListener) throws Exception;
@@ -73,7 +75,7 @@ public interface MusicService {
MusicDirectory getAlbumList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception;
- MusicDirectory getRandomSongs(int size, String folder, Context context, ProgressListener progressListener) throws Exception;
+ MusicDirectory getRandomSongs(int size, String folder, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception;
Bitmap getCoverArt(Context context, MusicDirectory.Entry entry, int size, boolean saveToFile, ProgressListener progressListener) throws Exception;
@@ -84,6 +86,8 @@ public interface MusicService {
Version getLatestVersion(Context context, ProgressListener progressListener) throws Exception;
String getVideoUrl(Context context, String id);
+
+ String getVideoStreamUrl(Context context, String id);
JukeboxStatus updateJukeboxPlaylist(List<String> ids, Context context, ProgressListener progressListener) throws Exception;
diff --git a/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java
index 29249268..a12a169e 100644
--- a/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java
+++ b/subsonic-android/src/github/daneren2005/dsub/service/OfflineMusicService.java
@@ -86,7 +86,7 @@ public class OfflineMusicService extends RESTMusicService {
Set<String> names = new HashSet<String>();
- for (File file : FileUtil.listMusicFiles(dir)) {
+ for (File file : FileUtil.listMediaFiles(dir)) {
String name = getName(file);
if (name != null & !names.contains(name)) {
names.add(name);
@@ -129,6 +129,9 @@ public class OfflineMusicService extends RESTMusicService {
if (albumArt.exists()) {
entry.setCoverArt(albumArt.getPath());
}
+ if(FileUtil.isVideoFile(file)) {
+ entry.setVideo(true);
+ }
return entry;
}
@@ -174,7 +177,7 @@ public class OfflineMusicService extends RESTMusicService {
}
private void recursiveAlbumSearch(String artistName, File file, SearchCritera criteria, Context context, List<MusicDirectory.Entry> albums, List<MusicDirectory.Entry> songs) {
- for(File albumFile : FileUtil.listMusicFiles(file)) {
+ for(File albumFile : FileUtil.listMediaFiles(file)) {
if(albumFile.isDirectory()) {
String albumName = getName(albumFile);
if(matchCriteria(criteria, albumName)) {
@@ -183,7 +186,7 @@ public class OfflineMusicService extends RESTMusicService {
albums.add(album);
}
- for(File songFile : FileUtil.listMusicFiles(albumFile)) {
+ for(File songFile : FileUtil.listMediaFiles(albumFile)) {
String songName = getName(songFile);
if(songFile.isDirectory()) {
recursiveAlbumSearch(artistName, songFile, criteria, context, albums, songs);
@@ -292,6 +295,11 @@ public class OfflineMusicService extends RESTMusicService {
}
@Override
+ public void removeFromPlaylist(String id, List<Integer> toRemove, Context context, ProgressListener progressListener) throws Exception {
+ throw new OfflineException("Removing from playlist not available in offline mode");
+ }
+
+ @Override
public void updatePlaylist(String id, String name, String comment, Context context, ProgressListener progressListener) throws Exception {
throw new OfflineException("Updating playlist not available in offline mode");
}
@@ -315,6 +323,11 @@ public class OfflineMusicService extends RESTMusicService {
public String getVideoUrl(Context context, String id) {
return null;
}
+
+ @Override
+ public String getVideoStreamUrl(Context context, String id) {
+ return null;
+ }
@Override
public JukeboxStatus updateJukeboxPlaylist(List<String> ids, Context context, ProgressListener progressListener) throws Exception {
@@ -352,7 +365,7 @@ public class OfflineMusicService extends RESTMusicService {
}
@Override
- public MusicDirectory getRandomSongs(int size, String folder, Context context, ProgressListener progressListener) throws Exception {
+ public MusicDirectory getRandomSongs(int size, String folder, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception {
File root = FileUtil.getMusicDirectory(context);
List<File> children = new LinkedList<File>();
listFilesRecursively(root, children);
@@ -371,7 +384,7 @@ public class OfflineMusicService extends RESTMusicService {
}
private void listFilesRecursively(File parent, List<File> children) {
- for (File file : FileUtil.listMusicFiles(parent)) {
+ for (File file : FileUtil.listMediaFiles(parent)) {
if (file.isFile()) {
children.add(file);
} else {
diff --git a/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java b/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java
index 60cffc7b..75ec6142 100644
--- a/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java
+++ b/subsonic-android/src/github/daneren2005/dsub/service/RESTMusicService.java
@@ -214,7 +214,7 @@ public class RESTMusicService implements MusicService {
return cachedIndexes;
}
- long lastModified = cachedIndexes == null ? 0L : cachedIndexes.getLastModified();
+ long lastModified = (cachedIndexes == null || refresh) ? 0L : cachedIndexes.getLastModified();
List<String> parameterNames = new ArrayList<String>();
List<Object> parameterValues = new ArrayList<Object>();
@@ -423,6 +423,25 @@ public class RESTMusicService implements MusicService {
}
@Override
+ public void removeFromPlaylist(String id, List<Integer> toRemove, Context context, ProgressListener progressListener) throws Exception {
+ checkServerVersion(context, "1.8", "Updating playlists is not supported.");
+ List<String> names = new ArrayList<String>();
+ List<Object> values = new ArrayList<Object>();
+ names.add("playlistId");
+ values.add(id);
+ for(Integer song: toRemove) {
+ names.add("songIndexToRemove");
+ values.add(song);
+ }
+ Reader reader = getReader(context, progressListener, "updatePlaylist", null, names, values);
+ try {
+ new ErrorParser(context).parse(reader);
+ } finally {
+ Util.close(reader);
+ }
+ }
+
+ @Override
public void updatePlaylist(String id, String name, String comment, Context context, ProgressListener progressListener) throws Exception {
checkServerVersion(context, "1.8", "Updating playlists is not supported.");
Reader reader = getReader(context, progressListener, "updatePlaylist", null, Arrays.asList("playlistId", "name", "comment"), Arrays.<Object>asList(id, name, comment));
@@ -476,7 +495,7 @@ public class RESTMusicService implements MusicService {
}
@Override
- public MusicDirectory getRandomSongs(int size, String musicFolderId, Context context, ProgressListener progressListener) throws Exception {
+ public MusicDirectory getRandomSongs(int size, String musicFolderId, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception {
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setSoTimeout(params, SOCKET_READ_TIMEOUT_GET_RANDOM_SONGS);
@@ -490,6 +509,18 @@ public class RESTMusicService implements MusicService {
names.add("musicFolderId");
values.add(musicFolderId);
}
+ if(genre != null) {
+ names.add("genre");
+ values.add(genre);
+ }
+ if(startYear != null) {
+ names.add("fromYear");
+ values.add(startYear);
+ }
+ if(endYear != null) {
+ names.add("toYear");
+ values.add(endYear);
+ }
Reader reader = getReader(context, progressListener, "getRandomSongs", params, names, values);
try {
@@ -619,6 +650,17 @@ public class RESTMusicService implements MusicService {
Log.i(TAG, "Using video URL: " + url);
return url;
}
+
+ @Override
+ public String getVideoStreamUrl(Context context, String id) {
+ StringBuilder builder = new StringBuilder(Util.getRestUrl(context, "stream"));
+ builder.append("&id=").append(id);
+ builder.append("&maxBitRate=500");
+
+ 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 {
diff --git a/subsonic-android/src/github/daneren2005/dsub/util/FileUtil.java b/subsonic-android/src/github/daneren2005/dsub/util/FileUtil.java
index da7c8fdc..890420fc 100644
--- a/subsonic-android/src/github/daneren2005/dsub/util/FileUtil.java
+++ b/subsonic-android/src/github/daneren2005/dsub/util/FileUtil.java
@@ -46,6 +46,7 @@ public class FileUtil {
private static final String[] FILE_SYSTEM_UNSAFE = {"/", "\\", "..", ":", "\"", "?", "*", "<", ">", "|"};
private static final String[] FILE_SYSTEM_UNSAFE_DIR = {"\\", "..", ":", "\"", "?", "*", "<", ">", "|"};
private static final List<String> MUSIC_FILE_EXTENSIONS = Arrays.asList("mp3", "ogg", "aac", "flac", "m4a", "wav", "wma");
+ private static final List<String> VIDEO_FILE_EXTENSIONS = Arrays.asList("flv", "mp4", "m4v", "wmv", "avi", "mov", "mpg", "mkv");
private static final List<String> PLAYLIST_FILE_EXTENSIONS = Arrays.asList("m3u");
private static final File DEFAULT_MUSIC_DIR = createDirectory("music");
@@ -237,23 +238,32 @@ public class FileUtil {
return new TreeSet<File>(Arrays.asList(files));
}
- public static SortedSet<File> listMusicFiles(File dir) {
+ public static SortedSet<File> listMediaFiles(File dir) {
SortedSet<File> files = listFiles(dir);
Iterator<File> iterator = files.iterator();
while (iterator.hasNext()) {
File file = iterator.next();
- if (!file.isDirectory() && !isMusicFile(file)) {
+ if (!file.isDirectory() && !isMediaFile(file)) {
iterator.remove();
}
}
return files;
}
- private static boolean isMusicFile(File file) {
+ private static boolean isMediaFile(File file) {
String extension = getExtension(file.getName());
- return MUSIC_FILE_EXTENSIONS.contains(extension);
+ return MUSIC_FILE_EXTENSIONS.contains(extension) || VIDEO_FILE_EXTENSIONS.contains(extension);
}
+ public static boolean isMusicFile(File file) {
+ String extension = getExtension(file.getName());
+ return MUSIC_FILE_EXTENSIONS.contains(extension);
+ }
+ public static boolean isVideoFile(File file) {
+ String extension = getExtension(file.getName());
+ return VIDEO_FILE_EXTENSIONS.contains(extension);
+ }
+
public static boolean isPlaylistFile(File file) {
String extension = getExtension(file.getName());
return PLAYLIST_FILE_EXTENSIONS.contains(extension);
diff --git a/subsonic-android/src/github/daneren2005/dsub/util/ShufflePlayBuffer.java b/subsonic-android/src/github/daneren2005/dsub/util/ShufflePlayBuffer.java
index f30f3d6d..3cc26057 100644
--- a/subsonic-android/src/github/daneren2005/dsub/util/ShufflePlayBuffer.java
+++ b/subsonic-android/src/github/daneren2005/dsub/util/ShufflePlayBuffer.java
@@ -45,6 +45,10 @@ public class ShufflePlayBuffer {
private Context context;
private int currentServer;
private String currentFolder;
+
+ private String genre;
+ private String startYear;
+ private String endYear;
public ShufflePlayBuffer(Context context) {
this.context = context;
@@ -88,7 +92,7 @@ public class ShufflePlayBuffer {
MusicService service = MusicServiceFactory.getMusicService(context);
int n = CAPACITY - buffer.size();
String folder = Util.getSelectedMusicFolderId(context);
- MusicDirectory songs = service.getRandomSongs(n, folder, context, null);
+ MusicDirectory songs = service.getRandomSongs(n, folder, genre, startYear, endYear, context, null);
synchronized (buffer) {
buffer.addAll(songs.getChildren());
@@ -108,5 +112,11 @@ public class ShufflePlayBuffer {
}
}
}
+
+ public void setOptions(String genre, String startYear, String endYear) {
+ this.genre = genre;
+ this.startYear = startYear;
+ this.endYear = endYear;
+ }
}
diff --git a/subsonic-android/src/github/daneren2005/dsub/util/Util.java b/subsonic-android/src/github/daneren2005/dsub/util/Util.java
index f8d108d3..2bdd969e 100644
--- a/subsonic-android/src/github/daneren2005/dsub/util/Util.java
+++ b/subsonic-android/src/github/daneren2005/dsub/util/Util.java
@@ -466,10 +466,17 @@ public final class Util {
return null;
}
- int minutes = seconds / 60;
+ int hours = seconds / 3600;
+ int minutes = (seconds / 60) % 60;
int secs = seconds % 60;
- StringBuilder builder = new StringBuilder(6);
+ StringBuilder builder = new StringBuilder(7);
+ if(hours > 0) {
+ builder.append(hours).append(":");
+ if(minutes < 10) {
+ builder.append("0");
+ }
+ }
builder.append(minutes).append(":");
if (secs < 10) {
builder.append("0");
diff --git a/subsonic-android/src/github/daneren2005/dsub/view/SongView.java b/subsonic-android/src/github/daneren2005/dsub/view/SongView.java
index f1701822..98ceebba 100644
--- a/subsonic-android/src/github/daneren2005/dsub/view/SongView.java
+++ b/subsonic-android/src/github/daneren2005/dsub/view/SongView.java
@@ -78,9 +78,13 @@ public class SongView extends UpdateView implements Checkable {
fileFormat = song.getSuffix();
}
- artist.append(song.getArtist()).append(" (")
- .append(String.format(getContext().getString(R.string.song_details_all), bitRate == null ? "" : bitRate, fileFormat))
- .append(")");
+ if(!song.isVideo()) {
+ artist.append(song.getArtist()).append(" (")
+ .append(String.format(getContext().getString(R.string.song_details_all), bitRate == null ? "" : bitRate, fileFormat))
+ .append(")");
+ } else {
+ artist.append(String.format(getContext().getString(R.string.song_details_all), bitRate == null ? "" : bitRate, fileFormat));
+ }
titleTextView.setText(song.getTitle());
artistTextView.setText(artist);