Handle unplayable files for gapless playback.
Remove the recursion in open() and replace it with a loop, and handle
the various cases a nonplayable file can be encountered during playback.
Change-Id: Ia4d13d5573f678c87f53ae090366cf61c38f6a45
diff --git a/src/com/android/music/MediaPlaybackService.java b/src/com/android/music/MediaPlaybackService.java
index 6e0e085..f872da2 100644
--- a/src/com/android/music/MediaPlaybackService.java
+++ b/src/com/android/music/MediaPlaybackService.java
@@ -1023,24 +1023,40 @@
}
stop(false);
- Cursor c = getCursorForId(mPlayList[mPlayPos]);
-
- if (c != null) {
- mCursor = c;
- open(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI + "/" + mCursor.getLong(IDCOLIDX));
- // go to bookmark if needed
- if (isPodcast()) {
- long bookmark = getBookmark();
- // Start playing a little bit before the bookmark,
- // so it's easier to get back in to the narrative.
- seek(bookmark - 5000);
- }
- mNextPlayPos = getNextPosition(false);
- if (mNextPlayPos >= 0) {
- long id = mPlayList[mNextPlayPos];
- mPlayer.setNextDataSource(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI + "/" + id);
+ mCursor = getCursorForId(mPlayList[mPlayPos]);
+ while(!open(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI + "/" + mCursor.getLong(IDCOLIDX))) {
+ if (mOpenFailedCounter++ < 10 && mPlayListLen > 1) {
+ int pos = getNextPosition(false);
+ if (pos < 0) {
+ gotoIdleState();
+ if (mIsSupposedToBePlaying) {
+ mIsSupposedToBePlaying = false;
+ notifyChange(PLAYSTATE_CHANGED);
+ }
+ return;
+ }
+ mPlayPos = pos;
+ stop(false);
+ mPlayPos = pos;
+ mCursor = getCursorForId(mPlayList[mPlayPos]);
+ } else {
+ mOpenFailedCounter = 0;
+ if (!mQuietMode) {
+ Toast.makeText(this, R.string.playback_failed, Toast.LENGTH_SHORT).show();
+ }
+ Log.d(LOGTAG, "Failed to open file for playback");
+ return;
}
}
+
+ // go to bookmark if needed
+ if (isPodcast()) {
+ long bookmark = getBookmark();
+ // Start playing a little bit before the bookmark,
+ // so it's easier to get back in to the narrative.
+ seek(bookmark - 5000);
+ }
+ setNextTrack();
}
}
@@ -1057,10 +1073,10 @@
*
* @param path The full path of the file to be opened.
*/
- public void open(String path) {
+ public boolean open(String path) {
synchronized (this) {
if (path == null) {
- return;
+ return false;
}
// if mCursor is null, try to associate path with a database cursor
@@ -1099,23 +1115,12 @@
}
mFileToPlay = path;
mPlayer.setDataSource(mFileToPlay);
- if (! mPlayer.isInitialized()) {
- stop(true);
- if (mOpenFailedCounter++ < 10 && mPlayListLen > 1) {
- // beware: this ends up being recursive because next() calls open() again.
- gotoNext(false);
- }
- if (! mPlayer.isInitialized() && mOpenFailedCounter != 0) {
- // need to make sure we only shows this once
- mOpenFailedCounter = 0;
- if (!mQuietMode) {
- Toast.makeText(this, R.string.playback_failed, Toast.LENGTH_SHORT).show();
- }
- Log.d(LOGTAG, "Failed to open file for playback");
- }
- } else {
+ if (mPlayer.isInitialized()) {
mOpenFailedCounter = 0;
+ return true;
}
+ stop(true);
+ return false;
}
}
@@ -1844,11 +1849,13 @@
}
public void setDataSource(String path) {
- setDataSource(mCurrentMediaPlayer, path);
- setNextDataSource(null);
+ mIsInitialized = setDataSourceImpl(mCurrentMediaPlayer, path);
+ if (mIsInitialized) {
+ setNextDataSource(null);
+ }
}
- public void setDataSource(MediaPlayer player, String path) {
+ private boolean setDataSourceImpl(MediaPlayer player, String path) {
try {
player.reset();
player.setOnPreparedListener(null);
@@ -1861,12 +1868,10 @@
player.prepare();
} catch (IOException ex) {
// TODO: notify the user why the file couldn't be opened
- mIsInitialized = false;
- return;
+ return false;
} catch (IllegalArgumentException ex) {
// TODO: notify the user why the file couldn't be opened
- mIsInitialized = false;
- return;
+ return false;
}
player.setOnCompletionListener(listener);
player.setOnErrorListener(errorListener);
@@ -1874,7 +1879,7 @@
i.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, getAudioSessionId());
i.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, getPackageName());
sendBroadcast(i);
- mIsInitialized = true;
+ return true;
}
public void setNextDataSource(String path) {
@@ -1889,8 +1894,14 @@
mNextMediaPlayer = new CompatMediaPlayer();
mNextMediaPlayer.setWakeMode(MediaPlaybackService.this, PowerManager.PARTIAL_WAKE_LOCK);
mNextMediaPlayer.setAudioSessionId(getAudioSessionId());
- setDataSource(mNextMediaPlayer, path);
- mCurrentMediaPlayer.setNextMediaPlayer(mNextMediaPlayer);
+ if (setDataSourceImpl(mNextMediaPlayer, path)) {
+ mCurrentMediaPlayer.setNextMediaPlayer(mNextMediaPlayer);
+ } else {
+ // failed to open next, we'll transition the old fashioned way,
+ // which will skip over the faulty file
+ mNextMediaPlayer.release();
+ mNextMediaPlayer = null;
+ }
}
public boolean isInitialized() {