From 05f5608b7af443a251ebe543f890acef6a5fa8b9 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Sun, 10 Feb 2013 15:39:00 -0800 Subject: Start of using a streaming proxy server --- .../daneren2005/dsub/service/DownloadFile.java | 6 + .../dsub/service/DownloadServiceImpl.java | 21 +- .../daneren2005/dsub/service/StreamProxy.java | 240 +++++++++++++++++++++ 3 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadFile.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadFile.java index 59f78252..b87f2726 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadFile.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadFile.java @@ -59,6 +59,7 @@ public class DownloadFile { private boolean isPlaying = false; private boolean saveWhenDone = false; private boolean completeWhenDone = false; + private long size = 0; public DownloadFile(Context context, MusicDirectory.Entry song, boolean save) { this.context = context; @@ -211,6 +212,10 @@ public class DownloadFile { public boolean getPlaying() { return isPlaying; } + + public long getSize() { + return size; + } @Override public String toString() { @@ -268,6 +273,7 @@ public class DownloadFile { // 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(); + size = response.getEntity().getContentLength(); boolean partial = response.getStatusLine().getStatusCode() == HttpStatus.SC_PARTIAL_CONTENT; if (partial) { Log.i(TAG, "Executed partial HTTP GET, skipping " + partialFile.length() + " bytes"); diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index 72198850..ace24f83 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -113,6 +113,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { private boolean showVisualization; private boolean jukeboxEnabled; private ScheduledExecutorService executorService; + private StreamProxy proxy; private Timer sleepTimer; private int timerDuration; @@ -201,6 +202,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { @Override public void onDestroy() { super.onDestroy(); + proxy.stop(); if(currentPlaying != null) currentPlaying.setPlaying(false); if(sleepTimer != null){ sleepTimer.cancel(); @@ -826,12 +828,22 @@ public class DownloadServiceImpl extends Service implements DownloadService { private synchronized void doPlay(final DownloadFile downloadFile, final int position, final boolean start) { try { final File file = downloadFile.isCompleteFileAvailable() ? downloadFile.getCompleteFile() : downloadFile.getPartialFile(); + final boolean isPartial = file.equals(downloadFile.getPartialFile()); downloadFile.updateModificationDate(); mediaPlayer.setOnCompletionListener(null); mediaPlayer.reset(); setPlayerState(IDLE); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); - mediaPlayer.setDataSource(file.getPath()); + String dataSource = file.getPath(); + if(isPartial) { + if (proxy == null) { + proxy = new StreamProxy(this); + proxy.start(); + } + dataSource = String.format("http://127.0.0.1:%d/%s", proxy.getPort(), dataSource); + Log.i(TAG, "Data Source: " + dataSource); + } + mediaPlayer.setDataSource(dataSource); setPlayerState(PREPARING); mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @@ -916,6 +928,13 @@ public class DownloadServiceImpl extends Service implements DownloadService { } }); + mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() { + @Override + public void onBufferingUpdate(MediaPlayer mp, int percent) { + Log.i(TAG, "Buffered " + percent + "%"); + } + }); + mediaPlayer.prepareAsync(); } catch (Exception x) { handleError(x); diff --git a/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java b/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java new file mode 100644 index 00000000..318f9892 --- /dev/null +++ b/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java @@ -0,0 +1,240 @@ +package github.daneren2005.dsub.service; + +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.net.URLDecoder; +import java.net.UnknownHostException; +import java.util.StringTokenizer; + +import org.apache.http.HttpRequest; +import org.apache.http.message.BasicHttpRequest; + +import android.os.AsyncTask; +import android.os.Looper; +import android.util.Log; +import github.daneren2005.dsub.util.Constants; + +public class StreamProxy implements Runnable { + private static final String TAG = StreamProxy.class.getSimpleName(); + + private Thread thread; + private boolean isRunning; + private ServerSocket socket; + private int port; + private DownloadService downloadService; + + public StreamProxy(DownloadService downloadService) { + + // Create listening socket + try { + socket = new ServerSocket(0, 0, InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 })); + socket.setSoTimeout(5000); + port = socket.getLocalPort(); + this.downloadService = downloadService; + } catch (UnknownHostException e) { // impossible + } catch (IOException e) { + Log.e(TAG, "IOException initializing server", e); + } + } + + public int getPort() { + return port; + } + + public void start() { + thread = new Thread(this); + thread.start(); + } + + public void stop() { + isRunning = false; + thread.interrupt(); + try { + thread.join(5000); + } catch (InterruptedException e) { + Log.e(TAG, "Exception stopping server", e); + } + } + + @Override + public void run() { + Looper.prepare(); + isRunning = true; + while (isRunning) { + try { + Socket client = socket.accept(); + if (client == null) { + continue; + } + Log.d(TAG, "client connected"); + + StreamToMediaPlayerTask task = new StreamToMediaPlayerTask(client); + if (task.processRequest()) { + task.execute(); + } + + } catch (SocketTimeoutException e) { + // Do nothing + } catch (IOException e) { + Log.e(TAG, "Error connecting to client", e); + } + } + Log.d(TAG, "Proxy interrupted. Shutting down."); + } + + private class StreamToMediaPlayerTask extends AsyncTask { + + String localPath; + Socket client; + int cbSkip; + + public StreamToMediaPlayerTask(Socket client) { + this.client = client; + } + + private HttpRequest readRequest() { + HttpRequest request = null; + InputStream is; + String firstLine; + try { + is = client.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(is), 8192); + firstLine = reader.readLine(); + } catch (IOException e) { + Log.e(TAG, "Error parsing request", e); + return request; + } + + if (firstLine == null) { + Log.i(TAG, "Proxy client closed connection without a request."); + return request; + } + + StringTokenizer st = new StringTokenizer(firstLine); + String method = st.nextToken(); + String uri = st.nextToken(); + Log.d(TAG, uri); + String realUri = uri.substring(1); + Log.d(TAG, realUri); + request = new BasicHttpRequest(method, realUri); + return request; + } + + public boolean processRequest() { + HttpRequest request = readRequest(); + if (request == null) { + return false; + } + + // Read HTTP headers + Log.d(TAG, "Processing request"); + + try { + localPath = URLDecoder.decode(request.getRequestLine().getUri(), Constants.UTF_8); + } catch (UnsupportedEncodingException e) { + Log.e(TAG, "Unsupported encoding", e); + return false; + } + + File file = new File(localPath); + if (!file.exists()) { + Log.e(TAG, "File " + localPath + " does not exist"); + return false; + } + + return true; + } + + @Override + protected Integer doInBackground(String... params) { + long fileSize = downloadService.getCurrentPlaying().getSong().getSize(); + // long fileSize = downloadService.getCurrentPlaying().getSize(); + Log.i(TAG, "Streaming fileSize: " + fileSize); + + // Create HTTP header + String headers = "HTTP/1.0 200 OK\r\n"; + headers += "Content-Type: " + "application/octet-stream" + "\r\n"; + + if (fileSize > 0) { + headers += "Content-Length: " + fileSize + "\r\n"; + } + + headers += "Connection: close\r\n"; + headers += "\r\n"; + + long cbToSend = fileSize - cbSkip; + OutputStream output = null; + byte[] buff = new byte[64 * 1024]; + try { + output = new BufferedOutputStream(client.getOutputStream(), 32*1024); + output.write(headers.getBytes()); + + // Loop as long as there's stuff to send + while (isRunning && cbToSend>0 && !client.isClosed()) { + + // See if there's more to send + File file = new File(localPath); + int cbSentThisBatch = 0; + if (file.exists()) { + FileInputStream input = new FileInputStream(file); + input.skip(cbSkip); + int cbToSendThisBatch = input.available(); + while (cbToSendThisBatch > 0) { + int cbToRead = Math.min(cbToSendThisBatch, buff.length); + int cbRead = input.read(buff, 0, cbToRead); + if (cbRead == -1) { + break; + } + cbToSendThisBatch -= cbRead; + cbToSend -= cbRead; + output.write(buff, 0, cbRead); + output.flush(); + cbSkip += cbRead; + cbSentThisBatch += cbRead; + } + input.close(); + } + + // If we did nothing this batch, block for a second + if (cbSentThisBatch == 0) { + Log.d(TAG, "Blocking until more data appears (" + cbToSend + ")"); + Thread.sleep(1000); + } + } + } + catch (SocketException socketException) { + Log.e(TAG, "SocketException() thrown, proxy client has probably closed. This can exit harmlessly"); + } + catch (Exception e) { + Log.e(TAG, "Exception thrown from streaming task:"); + Log.e(TAG, e.getClass().getName() + " : " + e.getLocalizedMessage()); + } + + // Cleanup + try { + if (output != null) { + output.close(); + } + client.close(); + } + catch (IOException e) { + Log.e(TAG, "IOException while cleaning up streaming task:"); + Log.e(TAG, e.getClass().getName() + " : " + e.getLocalizedMessage()); + } + + return 1; + } + } +} \ No newline at end of file -- cgit v1.2.3 From 57014b91bb50c3133cb1d5607fbce56f2eacf3fb Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Sun, 10 Feb 2013 15:57:24 -0800 Subject: Stability fixes --- .../src/github/daneren2005/dsub/service/DownloadServiceImpl.java | 8 +++++++- .../src/github/daneren2005/dsub/service/StreamProxy.java | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index ace24f83..6fdc2db3 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -202,7 +202,9 @@ public class DownloadServiceImpl extends Service implements DownloadService { @Override public void onDestroy() { super.onDestroy(); - proxy.stop(); + if(proxy != null) { + proxy.stop(); + } if(currentPlaying != null) currentPlaying.setPlaying(false); if(sleepTimer != null){ sleepTimer.cancel(); @@ -667,6 +669,10 @@ public class DownloadServiceImpl extends Service implements DownloadService { if (bufferTask != null) { bufferTask.cancel(); } + if(proxy != null) { + proxy.stop(); + proxy = null; + } try { setPlayerState(IDLE); mediaPlayer.setOnErrorListener(null); diff --git a/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java b/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java index 318f9892..bafa55c3 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java @@ -159,6 +159,7 @@ public class StreamProxy implements Runnable { @Override protected Integer doInBackground(String... params) { + DownloadFile downloadFile = downloadService.getCurrentPlaying(); long fileSize = downloadService.getCurrentPlaying().getSong().getSize(); // long fileSize = downloadService.getCurrentPlaying().getSize(); Log.i(TAG, "Streaming fileSize: " + fileSize); @@ -206,6 +207,11 @@ public class StreamProxy implements Runnable { } input.close(); } + + // Done regardless of whether or not it thinks it is + if(downloadFile.isWorkDone()) { + break; + } // If we did nothing this batch, block for a second if (cbSentThisBatch == 0) { -- cgit v1.2.3 From e2e2e81624af3dd486f10b3838c48e9d87beb0df Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Sun, 10 Feb 2013 17:11:04 -0800 Subject: Better estimate file length --- .../src/github/daneren2005/dsub/service/DownloadFile.java | 6 ------ .../src/github/daneren2005/dsub/service/StreamProxy.java | 5 +++-- 2 files changed, 3 insertions(+), 8 deletions(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadFile.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadFile.java index b87f2726..59f78252 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadFile.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadFile.java @@ -59,7 +59,6 @@ public class DownloadFile { private boolean isPlaying = false; private boolean saveWhenDone = false; private boolean completeWhenDone = false; - private long size = 0; public DownloadFile(Context context, MusicDirectory.Entry song, boolean save) { this.context = context; @@ -212,10 +211,6 @@ public class DownloadFile { public boolean getPlaying() { return isPlaying; } - - public long getSize() { - return size; - } @Override public String toString() { @@ -273,7 +268,6 @@ public class DownloadFile { // 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(); - size = response.getEntity().getContentLength(); boolean partial = response.getStatusLine().getStatusCode() == HttpStatus.SC_PARTIAL_CONTENT; if (partial) { Log.i(TAG, "Executed partial HTTP GET, skipping " + partialFile.length() + " bytes"); diff --git a/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java b/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java index bafa55c3..1cb087ac 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java @@ -24,6 +24,7 @@ import org.apache.http.message.BasicHttpRequest; import android.os.AsyncTask; import android.os.Looper; import android.util.Log; +import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.util.Constants; public class StreamProxy implements Runnable { @@ -160,8 +161,8 @@ public class StreamProxy implements Runnable { @Override protected Integer doInBackground(String... params) { DownloadFile downloadFile = downloadService.getCurrentPlaying(); - long fileSize = downloadService.getCurrentPlaying().getSong().getSize(); - // long fileSize = downloadService.getCurrentPlaying().getSize(); + MusicDirectory.Entry song = downloadFile.getSong(); + long fileSize = downloadFile.getBitRate() * song.getDuration() * 1000 / 8; Log.i(TAG, "Streaming fileSize: " + fileSize); // Create HTTP header -- cgit v1.2.3 From 853043b06fcfed651b0e4f8023875e7e72d27fb1 Mon Sep 17 00:00:00 2001 From: daneren2005 Date: Fri, 8 Mar 2013 10:37:19 -0800 Subject: Don't call start on play event if it's already playing --- .../daneren2005/dsub/service/DownloadServiceLifecycleSupport.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java index 6c9a84ad..765e216b 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java @@ -237,7 +237,9 @@ public class DownloadServiceLifecycleSupport { break; case RemoteControlClient.FLAG_KEY_MEDIA_PLAY: case KeyEvent.KEYCODE_MEDIA_PLAY: - downloadService.start(); + if(downloadService.getPlayerState() != PlayerState.STARTED) { + downloadService.start(); + } break; case RemoteControlClient.FLAG_KEY_MEDIA_PAUSE: case KeyEvent.KEYCODE_MEDIA_PAUSE: -- cgit v1.2.3 From 2870338049268cf1297a95ee9299f0dbac44d5cb Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Fri, 8 Mar 2013 18:12:48 -0800 Subject: Updated version 3.8 --- subsonic-android/AndroidManifest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'subsonic-android') diff --git a/subsonic-android/AndroidManifest.xml b/subsonic-android/AndroidManifest.xml index b8513db8..3dccdb3b 100644 --- a/subsonic-android/AndroidManifest.xml +++ b/subsonic-android/AndroidManifest.xml @@ -2,8 +2,8 @@ + android:versionCode="38" + android:versionName="3.8.0"> -- cgit v1.2.3 From e641470a614f5c69c4fbf2574643691060ae0f47 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Sat, 9 Mar 2013 09:37:43 -0800 Subject: Fixes #13 Get the bitrate when starting to download for the first time --- subsonic-android/src/github/daneren2005/dsub/service/DownloadFile.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadFile.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadFile.java index 834b85d9..3fa38bdf 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadFile.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadFile.java @@ -93,6 +93,9 @@ public class DownloadFile { public synchronized void download() { FileUtil.createDirectoryForParent(saveFile); failed = false; + if(!partialFile.exists()) { + bitRate = Util.getMaxBitrate(context); + } downloadTask = new DownloadTask(); downloadTask.start(); } -- cgit v1.2.3 From 26caf5a01f0f1a5eff89c15c67eda5148d47a261 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Mon, 11 Mar 2013 07:50:08 -0700 Subject: Base EQ/Visualizer showing off of API to avoid equalizer fx library loading --- .../daneren2005/dsub/service/DownloadServiceImpl.java | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index 91a3a5ea..058b8eef 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -125,20 +125,10 @@ public class DownloadServiceImpl extends Service implements DownloadService { private int timerDuration; static { - try { - EqualizerController.checkAvailable(); - equalizerAvailable = true; - } catch (Throwable t) { - equalizerAvailable = false; - } - } - static { - try { - VisualizerController.checkAvailable(); - visualizerAvailable = true; - } catch (Throwable t) { - visualizerAvailable = false; - } + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { + equalizerAvailable = true; + visualizerAvailable = true; + } } @Override -- cgit v1.2.3 From 9d6def926aa6019c87b4c30d82e659b481b31c21 Mon Sep 17 00:00:00 2001 From: daneren2005 Date: Mon, 11 Mar 2013 10:29:58 -0700 Subject: Stop updater from running every startup --- subsonic-android/src/github/daneren2005/dsub/updates/Updater.java | 1 + 1 file changed, 1 insertion(+) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/updates/Updater.java b/subsonic-android/src/github/daneren2005/dsub/updates/Updater.java index 69cdb642..3f8876b9 100644 --- a/subsonic-android/src/github/daneren2005/dsub/updates/Updater.java +++ b/subsonic-android/src/github/daneren2005/dsub/updates/Updater.java @@ -50,6 +50,7 @@ public class Updater { if(version > lastVersion) { SharedPreferences.Editor editor = prefs.edit(); editor.putInt(Constants.LAST_VERSION, version); + editor.commit(); Log.i(TAG, "Updating from version " + lastVersion + " to " + version); for(Updater updater: updaters) { -- cgit v1.2.3 From dc63abf439994255fff6f6c972a4acf3c872fdbe Mon Sep 17 00:00:00 2001 From: daneren2005 Date: Mon, 11 Mar 2013 14:22:30 -0700 Subject: Don't require bluetooth to buy from market --- subsonic-android/AndroidManifest.xml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'subsonic-android') diff --git a/subsonic-android/AndroidManifest.xml b/subsonic-android/AndroidManifest.xml index 3dccdb3b..8b6b704d 100644 --- a/subsonic-android/AndroidManifest.xml +++ b/subsonic-android/AndroidManifest.xml @@ -15,6 +15,8 @@ + + -- cgit v1.2.3 From 640fa0455ec3695eb375080232fb8703642f6678 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Mon, 11 Mar 2013 19:20:22 -0700 Subject: Don't check position in UI thread --- .../daneren2005/dsub/service/DownloadServiceImpl.java | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index 058b8eef..5a097ef7 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -811,18 +811,13 @@ public class DownloadServiceImpl extends Service implements DownloadService { Runnable runnable = new Runnable() { @Override public void run() { - handler.post(new Runnable() { - @Override - public void run() { - if(mediaPlayer != null && getPlayerState() == STARTED) { - try { - cachedPosition = mediaPlayer.getCurrentPosition(); - } catch(Exception e) { - executorService.shutdown(); - } - } + if(mediaPlayer != null && getPlayerState() == STARTED) { + try { + cachedPosition = mediaPlayer.getCurrentPosition(); + } catch(Exception e) { + executorService.shutdown(); } - }); + } } }; executorService = Executors.newSingleThreadScheduledExecutor(); -- cgit v1.2.3 From 95011bd13d04caef14e27a0078c1e7e610ecf6f2 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Mon, 11 Mar 2013 19:32:34 -0700 Subject: Fix stopped cachedPosition marking --- .../src/github/daneren2005/dsub/service/DownloadServiceImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index 5a097ef7..a0b9c899 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -777,7 +777,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { return playerState; } - public synchronized void setPlayerState(PlayerState playerState) { + public synchronized void setPlayerState(final PlayerState playerState) { Log.i(TAG, this.playerState.name() + " -> " + playerState.name() + " (" + currentPlaying + ")"); if (playerState == PAUSED) { @@ -811,7 +811,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { Runnable runnable = new Runnable() { @Override public void run() { - if(mediaPlayer != null && getPlayerState() == STARTED) { + if(mediaPlayer != null && playerState == STARTED) { try { cachedPosition = mediaPlayer.getCurrentPosition(); } catch(Exception e) { @@ -822,7 +822,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { }; executorService = Executors.newSingleThreadScheduledExecutor(); executorService.scheduleWithFixedDelay(runnable, 200L, 200L, TimeUnit.MILLISECONDS); - } else { + } else if(playerState != STARTED) { if(executorService != null && !executorService.isShutdown()) { executorService.shutdownNow(); } -- cgit v1.2.3 From 4881c10a96c9aa2eff339e461a97a8cd75bf90ed Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Tue, 12 Mar 2013 06:58:22 -0700 Subject: Use cached play position instead of regetting it --- .../src/github/daneren2005/dsub/service/DownloadServiceImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index a0b9c899..759757cb 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -644,6 +644,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { jukeboxService.skip(getCurrentPlayingIndex(), position / 1000); } else { mediaPlayer.seekTo(position); + cachedPosition = position; } } catch (Exception x) { handleError(x); @@ -746,7 +747,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { if (jukeboxEnabled) { return jukeboxService.getPositionSeconds() * 1000; } else { - return mediaPlayer.getCurrentPosition(); + return cachedPosition; } } catch (Exception x) { handleError(x); -- cgit v1.2.3 From fd5c4cb01d2f49bfa7b64941f30f8ef706f33cd6 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Tue, 12 Mar 2013 07:22:35 -0700 Subject: Don't drag n' drop on Recently added, etc... --- .../src/github/daneren2005/dsub/activity/SelectAlbumActivity.java | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/activity/SelectAlbumActivity.java b/subsonic-android/src/github/daneren2005/dsub/activity/SelectAlbumActivity.java index 46a32ed4..5016135c 100644 --- a/subsonic-android/src/github/daneren2005/dsub/activity/SelectAlbumActivity.java +++ b/subsonic-android/src/github/daneren2005/dsub/activity/SelectAlbumActivity.java @@ -403,6 +403,10 @@ public class SelectAlbumActivity extends SubsonicTabActivity { } else if ("starred".equals(albumListType)) { setTitle(R.string.main_albums_starred); } + + if (!"starred".equals(albumListType)) { + entryList.setDragEnabled(false); + } new LoadTask() { @Override -- cgit v1.2.3 From 0c04f81bfc304eee7a2090fb2343c1d2437e9cab Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Tue, 12 Mar 2013 20:01:24 -0700 Subject: Stop buffering update from running forever --- .../src/github/daneren2005/dsub/service/DownloadServiceImpl.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index ad6591a5..10872627 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -954,6 +954,9 @@ public class DownloadServiceImpl extends Service implements DownloadService { mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() { public void onBufferingUpdate(MediaPlayer mp, int percent) { Log.i(TAG, "Buffered " + percent + "%"); + if(percent == 100) { + mediaPlayer.setOnBufferingUpdateListener(null); + } } }); -- cgit v1.2.3 From 830eaacb5e082d39b51d5a8de401f97211a2c6e4 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Tue, 12 Mar 2013 20:12:17 -0700 Subject: Kill old proxy when no longer in use --- .../src/github/daneren2005/dsub/service/DownloadServiceImpl.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index 10872627..eee56aad 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -947,6 +947,9 @@ public class DownloadServiceImpl extends Service implements DownloadService { } dataSource = String.format("http://127.0.0.1:%d/%s", proxy.getPort(), dataSource); Log.i(TAG, "Data Source: " + dataSource); + } else { + proxy.stop(); + proxy = null; } mediaPlayer.setDataSource(dataSource); setPlayerState(PREPARING); -- cgit v1.2.3 From bc1766a4967ad60fcdd78aec7991816268336c13 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Tue, 12 Mar 2013 20:15:59 -0700 Subject: Fix proxy killing --- .../src/github/daneren2005/dsub/service/DownloadServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index eee56aad..95cbae2b 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -947,7 +947,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { } dataSource = String.format("http://127.0.0.1:%d/%s", proxy.getPort(), dataSource); Log.i(TAG, "Data Source: " + dataSource); - } else { + } else if(proxy != null) { proxy.stop(); proxy = null; } -- cgit v1.2.3 From 61bf15569c8d5683d105e19352b3756cb0cdba28 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Tue, 12 Mar 2013 20:20:54 -0700 Subject: Get rid of code which is never reached --- .../dsub/service/DownloadServiceImpl.java | 101 ++++++++++----------- 1 file changed, 46 insertions(+), 55 deletions(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index 95cbae2b..5a6a1985 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -927,69 +927,60 @@ public class DownloadServiceImpl extends Service implements DownloadService { isPartial = file.equals(downloadFile.getPartialFile()); downloadFile.updateModificationDate(); - if(playerState == PlayerState.PREPARED) { - if (start) { - mediaPlayer.start(); - setPlayerState(STARTED); - } else { - setPlayerState(PAUSED); + mediaPlayer.setOnCompletionListener(null); + mediaPlayer.reset(); + setPlayerState(IDLE); + mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); + String dataSource = file.getPath(); + if(isPartial) { + if (proxy == null) { + proxy = new StreamProxy(this); + proxy.start(); } - } else { - mediaPlayer.setOnCompletionListener(null); - mediaPlayer.reset(); - setPlayerState(IDLE); - mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); - String dataSource = file.getPath(); - if(isPartial) { - if (proxy == null) { - proxy = new StreamProxy(this); - proxy.start(); + dataSource = String.format("http://127.0.0.1:%d/%s", proxy.getPort(), dataSource); + Log.i(TAG, "Data Source: " + dataSource); + } else if(proxy != null) { + proxy.stop(); + proxy = null; + } + mediaPlayer.setDataSource(dataSource); + setPlayerState(PREPARING); + + mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() { + public void onBufferingUpdate(MediaPlayer mp, int percent) { + Log.i(TAG, "Buffered " + percent + "%"); + if(percent == 100) { + mediaPlayer.setOnBufferingUpdateListener(null); } - dataSource = String.format("http://127.0.0.1:%d/%s", proxy.getPort(), dataSource); - Log.i(TAG, "Data Source: " + dataSource); - } else if(proxy != null) { - proxy.stop(); - proxy = null; } - mediaPlayer.setDataSource(dataSource); - setPlayerState(PREPARING); - - mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() { - public void onBufferingUpdate(MediaPlayer mp, int percent) { - Log.i(TAG, "Buffered " + percent + "%"); - if(percent == 100) { - mediaPlayer.setOnBufferingUpdateListener(null); - } - } - }); + }); - mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { - public void onPrepared(MediaPlayer mediaPlayer) { - try { - setPlayerState(PREPARED); - - synchronized (DownloadServiceImpl.this) { - if (position != 0) { - Log.i(TAG, "Restarting player from position " + position); - mediaPlayer.seekTo(position); - } - cachedPosition = position; - - if (start) { - mediaPlayer.start(); - setPlayerState(STARTED); - } else { - setPlayerState(PAUSED); - } + mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + public void onPrepared(MediaPlayer mediaPlayer) { + try { + setPlayerState(PREPARED); + + synchronized (DownloadServiceImpl.this) { + if (position != 0) { + Log.i(TAG, "Restarting player from position " + position); + mediaPlayer.seekTo(position); } + cachedPosition = position; - lifecycleSupport.serializeDownloadQueue(); - } catch (Exception x) { - handleError(x); + if (start) { + mediaPlayer.start(); + setPlayerState(STARTED); + } else { + setPlayerState(PAUSED); + } } + + lifecycleSupport.serializeDownloadQueue(); + } catch (Exception x) { + handleError(x); } - }); - } + } + }); setupHandlers(downloadFile, isPartial); -- cgit v1.2.3 From 23516f631c4fe068583c343a8ed248924a487f9b Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Tue, 12 Mar 2013 20:35:13 -0700 Subject: Add buffer time before next player tries to prepare --- .../src/github/daneren2005/dsub/service/DownloadServiceImpl.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index 5a6a1985..00eb9739 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -1375,6 +1375,8 @@ public class DownloadServiceImpl extends Service implements DownloadService { return; } + // Do an initial sleep so this prepare can't compete with main prepare + Util.sleepQuietly(5000L); while (!bufferComplete()) { Util.sleepQuietly(5000L); if (isCancelled()) { -- cgit v1.2.3 From 84d0f85f1023c2a1f9c753a8470272b21a834d19 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Tue, 12 Mar 2013 20:43:05 -0700 Subject: Stop proxy server when mediaPlayer chaining as well --- .../src/github/daneren2005/dsub/service/DownloadServiceImpl.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index 00eb9739..516e70de 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -625,6 +625,12 @@ public class DownloadServiceImpl extends Service implements DownloadService { setPlayerState(PlayerState.STARTED); setupHandlers(currentPlaying, false); setNextPlaying(); + + // Proxy should not be being used here since the next player was already setup to play + if(proxy != null) { + proxy.stop(); + proxy = null; + } } /** Plays or resumes the playback, depending on the current player state. */ -- cgit v1.2.3 From 16fa6c8fa98146fd960abd8d2f1ae1197438672f Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Tue, 12 Mar 2013 20:48:11 -0700 Subject: Fixed an odd edge case that could stop playback --- .../src/github/daneren2005/dsub/service/DownloadServiceImpl.java | 1 + 1 file changed, 1 insertion(+) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index 516e70de..93cedae0 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -526,6 +526,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { } } + nextSetup = false; if(index < size() && index != -1) { nextPlaying = downloadList.get(index); nextPlayingTask = new CheckCompletionTask(nextPlaying); -- cgit v1.2.3 From 3cb3db540af116fcf512762d3af9ed160fcbf221 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Tue, 12 Mar 2013 20:52:24 -0700 Subject: With stuttering fixed, can now chain even on streamed songs --- .../src/github/daneren2005/dsub/service/DownloadServiceImpl.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index 93cedae0..e84cfb33 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -1013,8 +1013,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { public void onPrepared(MediaPlayer mediaPlayer) { try { setNextPlayerState(PREPARED); - // TODO: Whenever the completing early issue is fixed, remove !isPartial to get gapless playback on streams as well - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && playerState == PlayerState.STARTED && !isPartial) { + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && playerState == PlayerState.STARTED) { DownloadServiceImpl.this.mediaPlayer.setNextMediaPlayer(nextMediaPlayer); nextSetup = true; } -- cgit v1.2.3 From 62f3add1a698e060e70b70c91db0e970f506ae18 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Tue, 12 Mar 2013 20:53:32 -0700 Subject: Don't specify a content-length since no way to estimate it well --- subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java | 4 ---- 1 file changed, 4 deletions(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java b/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java index 1cb087ac..0972ecf2 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java @@ -169,10 +169,6 @@ public class StreamProxy implements Runnable { String headers = "HTTP/1.0 200 OK\r\n"; headers += "Content-Type: " + "application/octet-stream" + "\r\n"; - if (fileSize > 0) { - headers += "Content-Length: " + fileSize + "\r\n"; - } - headers += "Connection: close\r\n"; headers += "\r\n"; -- cgit v1.2.3 From adb4bcb8908a8fa09d1f8a813b1922521d98facd Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Wed, 13 Mar 2013 19:09:51 -0700 Subject: Fix underestimating filesize screwing up stream --- .../src/github/daneren2005/dsub/service/StreamProxy.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java b/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java index 0972ecf2..0c5f9c2f 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java @@ -180,7 +180,7 @@ public class StreamProxy implements Runnable { output.write(headers.getBytes()); // Loop as long as there's stuff to send - while (isRunning && cbToSend>0 && !client.isClosed()) { + while (isRunning && !downloadFile.isWorkDone() && !client.isClosed()) { // See if there's more to send File file = new File(localPath); @@ -204,11 +204,6 @@ public class StreamProxy implements Runnable { } input.close(); } - - // Done regardless of whether or not it thinks it is - if(downloadFile.isWorkDone()) { - break; - } // If we did nothing this batch, block for a second if (cbSentThisBatch == 0) { -- cgit v1.2.3 From 926fa8765ff163f66605fdea1758dd5b4655e3ef Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Wed, 13 Mar 2013 19:25:52 -0700 Subject: Fix last commit --- .../src/github/daneren2005/dsub/service/StreamProxy.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java b/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java index 0c5f9c2f..b3c05a66 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java @@ -180,7 +180,7 @@ public class StreamProxy implements Runnable { output.write(headers.getBytes()); // Loop as long as there's stuff to send - while (isRunning && !downloadFile.isWorkDone() && !client.isClosed()) { + while (isRunning && !client.isClosed()) { // See if there's more to send File file = new File(localPath); @@ -204,6 +204,11 @@ public class StreamProxy implements Runnable { } input.close(); } + + // Done regardless of whether or not it thinks it is + if(downloadFile.isWorkDone()) { + break; + } // If we did nothing this batch, block for a second if (cbSentThisBatch == 0) { -- cgit v1.2.3 From caf6f4b4e24c65bc5d905f47c5bb2c53d4e918f4 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Wed, 13 Mar 2013 19:26:05 -0700 Subject: Get rid of more dead code --- .../src/github/daneren2005/dsub/service/DownloadServiceImpl.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index e84cfb33..0fc707a2 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -991,9 +991,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { setupHandlers(downloadFile, isPartial); - if(playerState == PREPARING) { - mediaPlayer.prepareAsync(); - } + mediaPlayer.prepareAsync(); } catch (Exception x) { handleError(x); } -- cgit v1.2.3 From 22eef7d99ae73c8a811d55aa37468abdca5cfc19 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Wed, 13 Mar 2013 19:57:45 -0700 Subject: Older devices don't do transparent encoding apparently --- .../src/github/daneren2005/dsub/service/DownloadServiceImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index 0fc707a2..0e3df9c8 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -61,6 +61,7 @@ import android.os.IBinder; import android.os.PowerManager; import android.util.Log; import github.daneren2005.dsub.activity.SubsonicTabActivity; +import java.net.URLEncoder; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -944,7 +945,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { proxy = new StreamProxy(this); proxy.start(); } - dataSource = String.format("http://127.0.0.1:%d/%s", proxy.getPort(), dataSource); + dataSource = String.format("http://127.0.0.1:%d/%s", proxy.getPort(), URLEncoder.encode(dataSource, Constants.UTF_8)); Log.i(TAG, "Data Source: " + dataSource); } else if(proxy != null) { proxy.stop(); -- cgit v1.2.3 From 486364133ef35fafe12854ca4968fa56d4d35a2a Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Wed, 13 Mar 2013 20:41:21 -0700 Subject: Fix for devices sending repeated requests for more data after already having sent everything --- .../daneren2005/dsub/service/StreamProxy.java | 81 +++++++++++----------- 1 file changed, 42 insertions(+), 39 deletions(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java b/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java index b3c05a66..88815706 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java @@ -126,9 +126,8 @@ public class StreamProxy implements Runnable { StringTokenizer st = new StringTokenizer(firstLine); String method = st.nextToken(); String uri = st.nextToken(); - Log.d(TAG, uri); String realUri = uri.substring(1); - Log.d(TAG, realUri); + Log.i(TAG, realUri); request = new BasicHttpRequest(method, realUri); return request; } @@ -140,7 +139,7 @@ public class StreamProxy implements Runnable { } // Read HTTP headers - Log.d(TAG, "Processing request"); + Log.i(TAG, "Processing request"); try { localPath = URLDecoder.decode(request.getRequestLine().getUri(), Constants.UTF_8); @@ -179,43 +178,47 @@ public class StreamProxy implements Runnable { output = new BufferedOutputStream(client.getOutputStream(), 32*1024); output.write(headers.getBytes()); - // Loop as long as there's stuff to send - while (isRunning && !client.isClosed()) { - - // See if there's more to send - File file = new File(localPath); - int cbSentThisBatch = 0; - if (file.exists()) { - FileInputStream input = new FileInputStream(file); - input.skip(cbSkip); - int cbToSendThisBatch = input.available(); - while (cbToSendThisBatch > 0) { - int cbToRead = Math.min(cbToSendThisBatch, buff.length); - int cbRead = input.read(buff, 0, cbToRead); - if (cbRead == -1) { - break; - } - cbToSendThisBatch -= cbRead; - cbToSend -= cbRead; - output.write(buff, 0, cbRead); - output.flush(); - cbSkip += cbRead; - cbSentThisBatch += cbRead; - } - input.close(); - } - - // Done regardless of whether or not it thinks it is - if(downloadFile.isWorkDone()) { - break; + if(!downloadFile.isWorkDone()) { + // Loop as long as there's stuff to send + while (isRunning && !client.isClosed()) { + + // See if there's more to send + File file = new File(localPath); + int cbSentThisBatch = 0; + if (file.exists()) { + FileInputStream input = new FileInputStream(file); + input.skip(cbSkip); + int cbToSendThisBatch = input.available(); + while (cbToSendThisBatch > 0) { + int cbToRead = Math.min(cbToSendThisBatch, buff.length); + int cbRead = input.read(buff, 0, cbToRead); + if (cbRead == -1) { + break; + } + cbToSendThisBatch -= cbRead; + cbToSend -= cbRead; + output.write(buff, 0, cbRead); + output.flush(); + cbSkip += cbRead; + cbSentThisBatch += cbRead; + } + input.close(); + } + + // Done regardless of whether or not it thinks it is + if(downloadFile.isWorkDone()) { + break; + } + + // If we did nothing this batch, block for a second + if (cbSentThisBatch == 0) { + Log.d(TAG, "Blocking until more data appears (" + cbToSend + ")"); + Thread.sleep(1000); + } } - - // If we did nothing this batch, block for a second - if (cbSentThisBatch == 0) { - Log.d(TAG, "Blocking until more data appears (" + cbToSend + ")"); - Thread.sleep(1000); - } - } + } else { + Log.w(TAG, "Requesting data for completely downloaded file"); + } } catch (SocketException socketException) { Log.e(TAG, "SocketException() thrown, proxy client has probably closed. This can exit harmlessly"); -- cgit v1.2.3 From 44391bcbb50c551f75f0ea1d73d240599b46cf72 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Thu, 14 Mar 2013 18:50:08 -0700 Subject: Fix buffer = 0 -> then StreamProxy shouldn't be being used --- .../src/github/daneren2005/dsub/service/DownloadServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index 0e3df9c8..4e7bbbb0 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -497,7 +497,6 @@ public class DownloadServiceImpl extends Service implements DownloadService { if (currentPlaying != null) { Util.broadcastNewTrackInfo(this, currentPlaying.getSong()); - currentPlaying.setPlaying(true); mRemoteControl.updateMetadata(this, currentPlaying.getSong()); } else { Util.broadcastNewTrackInfo(this, null); @@ -931,6 +930,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { private synchronized void doPlay(final DownloadFile downloadFile, final int position, final boolean start) { try { + downloadFile.setPlaying(true); final File file = downloadFile.isCompleteFileAvailable() ? downloadFile.getCompleteFile() : downloadFile.getPartialFile(); isPartial = file.equals(downloadFile.getPartialFile()); downloadFile.updateModificationDate(); -- cgit v1.2.3 From 0f36cd43d5e5ad53925d772fa15687c39a2156c1 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Thu, 14 Mar 2013 19:01:19 -0700 Subject: Add a check to make sure that 100% of the file is sent before closing connection --- subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java b/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java index 88815706..1b422d5a 100644 --- a/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java +++ b/subsonic-android/src/github/daneren2005/dsub/service/StreamProxy.java @@ -206,7 +206,7 @@ public class StreamProxy implements Runnable { } // Done regardless of whether or not it thinks it is - if(downloadFile.isWorkDone()) { + if(downloadFile.isWorkDone() && cbSkip >= file.length()) { break; } -- cgit v1.2.3 From c0feea2f650c453c51cb04168c28dce4a47bdd5e Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Thu, 14 Mar 2013 21:02:11 -0700 Subject: Display Artist instead of album on lockscreen widget --- .../src/github/daneren2005/dsub/util/compat/RemoteControlClientICS.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'subsonic-android') diff --git a/subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientICS.java b/subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientICS.java index e6528d1b..52361fd4 100644 --- a/subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientICS.java +++ b/subsonic-android/src/github/daneren2005/dsub/util/compat/RemoteControlClientICS.java @@ -62,7 +62,7 @@ public class RemoteControlClientICS extends RemoteControlClientHelper { // Update the remote controls mRemoteControl.editMetadata(true) .putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, (currentSong == null) ? null : currentSong.getArtist()) - .putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, (currentSong == null) ? null : currentSong.getAlbum()) + .putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, (currentSong == null) ? null : currentSong.getArtist()) .putString(MediaMetadataRetriever.METADATA_KEY_TITLE, (currentSong) == null ? null : currentSong.getTitle()) .putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, (currentSong == null) ? 0 : ((currentSong.getDuration() == null) ? 0 : currentSong.getDuration())) -- cgit v1.2.3