aboutsummaryrefslogtreecommitdiff
path: root/subsonic-android
diff options
context:
space:
mode:
authorScott Jackson <daneren2005@gmail.com>2013-05-01 20:26:11 -0700
committerScott Jackson <daneren2005@gmail.com>2013-05-01 20:26:11 -0700
commit934fb55b72424d1710ef3d237062242e034a23d7 (patch)
treeeb4d0eeb54fdc27baee06bbbafdf575625b15d9a /subsonic-android
parent93d03bc7ab2b078e48baad33257606e06875f994 (diff)
parent442f5839a79f1c823445921b7e7f8f3c634dfd58 (diff)
downloaddsub-934fb55b72424d1710ef3d237062242e034a23d7.tar.gz
dsub-934fb55b72424d1710ef3d237062242e034a23d7.tar.bz2
dsub-934fb55b72424d1710ef3d237062242e034a23d7.zip
Merge branch 'master' of https://github.com/daneren2005/Subsonic.git into Fragments
Diffstat (limited to 'subsonic-android')
-rw-r--r--subsonic-android/AndroidManifest.xml4
-rw-r--r--subsonic-android/res/values/strings.xml2
-rw-r--r--subsonic-android/res/xml/settings.xml6
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java27
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/util/Constants.java1
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/util/FileUtil.java19
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/view/SongView.java22
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/view/UpdateView.java67
8 files changed, 117 insertions, 31 deletions
diff --git a/subsonic-android/AndroidManifest.xml b/subsonic-android/AndroidManifest.xml
index 7f29832e..18197d58 100644
--- a/subsonic-android/AndroidManifest.xml
+++ b/subsonic-android/AndroidManifest.xml
@@ -2,8 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="github.daneren2005.dsub"
android:installLocation="internalOnly"
- android:versionCode="41"
- android:versionName="3.8.3">
+ android:versionCode="42"
+ android:versionName="3.8.4">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
diff --git a/subsonic-android/res/values/strings.xml b/subsonic-android/res/values/strings.xml
index 4e96ad5a..c9c7c991 100644
--- a/subsonic-android/res/values/strings.xml
+++ b/subsonic-android/res/values/strings.xml
@@ -267,6 +267,8 @@
<string name="settings.temp_loss_nothing">Do Nothing</string>
<string name="settings.persistent_title">Persistent Notification</string>
<string name="settings.persistent_summary">Show the notification even after pausing. Press the stop button to clear it away.</string>
+ <string name="settings.gapless_playback">Gapless Playback</string>
+ <string name="settings.gapless_playback_summary">The Galaxy S3 seems to be experiencing freezes/other weird issue since the introduction of gapless playback. Turn this off to fix the issue.</string>
<string name="shuffle.startYear">Start Year:</string>
<string name="shuffle.endYear">End Year:</string>
diff --git a/subsonic-android/res/xml/settings.xml b/subsonic-android/res/xml/settings.xml
index a2ae7b20..d21f928f 100644
--- a/subsonic-android/res/xml/settings.xml
+++ b/subsonic-android/res/xml/settings.xml
@@ -239,6 +239,12 @@
android:key="screenLitOnDownload"
android:defaultValue="true"/>
+ <CheckBoxPreference
+ android:title="@string/settings.gapless_playback"
+ android:summary="@string/settings.gapless_playback_summary"
+ android:key="gaplessPlayback"
+ android:defaultValue="true"/>
+
<Preference
android:key="clearSearchHistory"
android:title="@string/settings.clear_search_history"
diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java
index 8136114f..bdd1d4e1 100644
--- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java
+++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java
@@ -63,6 +63,7 @@ import android.os.Looper;
import android.os.PowerManager;
import android.util.Log;
import github.daneren2005.dsub.activity.SubsonicTabActivity;
+import github.daneren2005.dsub.util.FileUtil;
import java.net.URLEncoder;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -334,7 +335,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
}
@Override
- public synchronized boolean isShufflePlayEnabled() {
+ public boolean isShufflePlayEnabled() {
return shufflePlay;
}
@@ -570,7 +571,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
}
@Override
- public synchronized List<DownloadFile> getSongs() {
+ public List<DownloadFile> getSongs() {
return downloadList;
}
@@ -583,7 +584,7 @@ public class DownloadServiceImpl extends Service implements DownloadService {
}
@Override
- public synchronized List<DownloadFile> getBackgroundDownloads() {
+ public List<DownloadFile> getBackgroundDownloads() {
return backgroundDownloadList;
}
@@ -869,19 +870,14 @@ public class DownloadServiceImpl extends Service implements DownloadService {
private class PositionCache implements Runnable {
boolean isRunning = true;
- Thread thread;
public void stop() {
isRunning = false;
- if(thread != null) {
- // Make it stop right NOW
- thread.interrupt();
- }
}
@Override
public void run() {
- thread = Thread.currentThread();
+ // Stop checking position before the song reaches completion
while(isRunning) {
try {
if(mediaPlayer != null && playerState == STARTED) {
@@ -889,11 +885,6 @@ public class DownloadServiceImpl extends Service implements DownloadService {
}
Thread.sleep(200L);
}
- catch (InterruptedException e) {
- // Purposely interrupted, don't log error
- isRunning = false;
- positionCache = null;
- }
catch(Exception e) {
Log.w(TAG, "Crashed getting current position", e);
isRunning = false;
@@ -1085,7 +1076,10 @@ public class DownloadServiceImpl extends Service implements DownloadService {
public void onPrepared(MediaPlayer mp) {
try {
setNextPlayerState(PREPARED);
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && (playerState == PlayerState.STARTED || playerState == PlayerState.PAUSED)) {
+
+ SharedPreferences prefs = Util.getPreferences(DownloadServiceImpl.this);
+ boolean gaplessPlayback = prefs.getBoolean(Constants.PREFERENCES_KEY_GAPLESS_PLAYBACK, true);
+ if(gaplessPlayback && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && (playerState == PlayerState.STARTED || playerState == PlayerState.PAUSED)) {
mediaPlayer.setNextMediaPlayer(nextMediaPlayer);
nextSetup = true;
}
@@ -1286,6 +1280,9 @@ public class DownloadServiceImpl extends Service implements DownloadService {
if(n != 0) {
int start = currentPlaying == null ? 0 : getCurrentPlayingIndex();
+ if(start == -1) {
+ start = 0;
+ }
int i = start;
do {
DownloadFile downloadFile = downloadList.get(i);
diff --git a/subsonic-android/src/github/daneren2005/dsub/util/Constants.java b/subsonic-android/src/github/daneren2005/dsub/util/Constants.java
index ae88a2ef..a35573a6 100644
--- a/subsonic-android/src/github/daneren2005/dsub/util/Constants.java
+++ b/subsonic-android/src/github/daneren2005/dsub/util/Constants.java
@@ -91,6 +91,7 @@ public final class Constants {
public static final String PREFERENCES_EQUALIZER_ON = "equalizerOn";
public static final String PREFERENCES_EQUALIZER_SETTINGS = "equalizerSettings";
public static final String PREFERENCES_KEY_PERSISTENT_NOTIFICATION = "persistentNotification";
+ public static final String PREFERENCES_KEY_GAPLESS_PLAYBACK = "gaplessPlayback";
// Name of the preferences file.
public static final String PREFERENCES_FILE_NAME = "github.daneren2005.dsub_preferences";
diff --git a/subsonic-android/src/github/daneren2005/dsub/util/FileUtil.java b/subsonic-android/src/github/daneren2005/dsub/util/FileUtil.java
index bb89a4d3..65f5a37f 100644
--- a/subsonic-android/src/github/daneren2005/dsub/util/FileUtil.java
+++ b/subsonic-android/src/github/daneren2005/dsub/util/FileUtil.java
@@ -50,6 +50,25 @@ public class FileUtil {
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");
+
+ public static File getAnySong(Context context) {
+ File dir = getMusicDirectory(context);
+ return getAnySong(context, dir);
+ }
+ private static File getAnySong(Context context, File dir) {
+ for(File file: dir.listFiles()) {
+ if(file.isDirectory()) {
+ return getAnySong(context, file);
+ }
+
+ String extension = getExtension(file.getName());
+ if(MUSIC_FILE_EXTENSIONS.contains(extension)) {
+ return file;
+ }
+ }
+
+ return null;
+ }
public static File getSongFile(Context context, MusicDirectory.Entry song) {
File dir = getAlbumDirectory(context, song);
diff --git a/subsonic-android/src/github/daneren2005/dsub/view/SongView.java b/subsonic-android/src/github/daneren2005/dsub/view/SongView.java
index 7cefae23..51927304 100644
--- a/subsonic-android/src/github/daneren2005/dsub/view/SongView.java
+++ b/subsonic-android/src/github/daneren2005/dsub/view/SongView.java
@@ -52,6 +52,9 @@ public class SongView extends UpdateView implements Checkable {
private TextView statusTextView;
private ImageButton starButton;
private ImageView moreButton;
+
+ private DownloadService downloadService;
+ private DownloadFile downloadFile;
public SongView(Context context) {
super(context);
@@ -122,18 +125,29 @@ public class SongView extends UpdateView implements Checkable {
}
});
+ updateBackground();
update();
}
+
+ @Override
+ protected void updateBackground() {
+ if (downloadService == null) {
+ downloadService = DownloadServiceImpl.getInstance();
+ if(downloadService == null) {
+ return;
+ }
+ }
+
+ downloadFile = downloadService.forSong(song);
+ }
@Override
protected void update() {
- starButton.setVisibility((Util.isOffline(getContext()) || !song.isStarred()) ? View.GONE : View.VISIBLE);
- DownloadService downloadService = DownloadServiceImpl.getInstance();
if (downloadService == null) {
return;
}
-
- DownloadFile downloadFile = downloadService.forSong(song);
+
+ starButton.setVisibility((Util.isOffline(getContext()) || !song.isStarred()) ? View.GONE : View.VISIBLE);
File partialFile = downloadFile.getPartialFile();
int leftImage = 0;
diff --git a/subsonic-android/src/github/daneren2005/dsub/view/UpdateView.java b/subsonic-android/src/github/daneren2005/dsub/view/UpdateView.java
index 9fbaccf6..7ce27f06 100644
--- a/subsonic-android/src/github/daneren2005/dsub/view/UpdateView.java
+++ b/subsonic-android/src/github/daneren2005/dsub/view/UpdateView.java
@@ -20,16 +20,22 @@ package github.daneren2005.dsub.view;
import android.content.Context;
import android.os.Handler;
+import android.os.Looper;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.LinearLayout;
+import java.util.ArrayList;
+import java.util.List;
import java.util.WeakHashMap;
public class UpdateView extends LinearLayout {
private static final String TAG = UpdateView.class.getSimpleName();
private static final WeakHashMap<UpdateView, ?> INSTANCES = new WeakHashMap<UpdateView, Object>();
- private static Handler handler;
+
+ private static Handler backgroundHandler;
+ private static Handler uiHandler;
+ private static Runnable updateRunnable;
public UpdateView(Context context) {
super(context);
@@ -53,33 +59,74 @@ public class UpdateView extends LinearLayout {
}
private static synchronized void startUpdater() {
- if (handler != null) {
- return;
- }
-
- handler = new Handler();
- Runnable runnable = new Runnable() {
+ if(uiHandler != null) {
+ return;
+ }
+
+ uiHandler = new Handler();
+ updateRunnable = new Runnable() {
@Override
public void run() {
updateAll();
- handler.postDelayed(this, 1000L);
}
};
- handler.postDelayed(runnable, 1000L);
+
+ new Thread(new Runnable() {
+ public void run() {
+ Looper.prepare();
+ backgroundHandler = new Handler(Looper.myLooper());
+ uiHandler.post(updateRunnable);
+ Looper.loop();
+ }
+ }).start();
}
private static void updateAll() {
try {
+ List<UpdateView> views = new ArrayList<UpdateView>();;
for (UpdateView view : INSTANCES.keySet()) {
if (view.isShown()) {
- view.update();
+ views.add(view);
}
}
+ updateAllLive(views);
} catch (Throwable x) {
Log.w(TAG, "Error when updating song views.", x);
}
}
+ private static void updateAllLive(final List<UpdateView> views) {
+ final Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ for(UpdateView view: views) {
+ view.update();
+ }
+ } catch (Throwable x) {
+ Log.w(TAG, "Error when updating song views.", x);
+ }
+ uiHandler.postDelayed(updateRunnable, 1000L);
+ }
+ };
+
+ backgroundHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ for(UpdateView view: views) {
+ view.updateBackground();
+ }
+ uiHandler.post(runnable);
+ } catch (Throwable x) {
+ Log.w(TAG, "Error when updating song views.", x);
+ }
+ }
+ });
+ }
+ protected void updateBackground() {
+
+ }
protected void update() {
}