Create interface for PlaybackServiceMediaPlayer

This commit is contained in:
Domingos Lopes 2016-03-19 11:37:37 -04:00 committed by Domingos Lopes
parent 8061d94c1b
commit afbae2a7ef
5 changed files with 197 additions and 92 deletions

View File

@ -20,14 +20,15 @@ import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.FeedPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackServiceMediaPlayer;
import de.danoeh.antennapod.core.service.playback.IPlaybackServiceMediaPlayer;
import de.danoeh.antennapod.core.service.playback.LocalPSMP;
import de.danoeh.antennapod.core.service.playback.PlayerStatus;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.test.antennapod.util.service.download.HTTPBin;
/**
* Test class for PlaybackServiceMediaPlayer
* Test class for LocalPSMP
*/
public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
private static final String TAG = "PlaybackServiceMediaPlayerTest";
@ -85,7 +86,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
assertEquals(0, httpServer.serveFile(dest));
}
private void checkPSMPInfo(PlaybackServiceMediaPlayer.PSMPInfo info) {
private void checkPSMPInfo(LocalPSMP.PSMPInfo info) {
try {
switch (info.playerStatus) {
case PLAYING:
@ -111,7 +112,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
public void testInit() {
final Context c = getInstrumentation().getTargetContext();
PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, defaultCallback);
IPlaybackServiceMediaPlayer psmp = new LocalPSMP(c, defaultCallback);
psmp.shutdown();
}
@ -137,9 +138,9 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
public void testPlayMediaObjectStreamNoStartNoPrepare() throws InterruptedException {
final Context c = getInstrumentation().getTargetContext();
final CountDownLatch countDownLatch = new CountDownLatch(2);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
IPlaybackServiceMediaPlayer.PSMPCallback callback = new IPlaybackServiceMediaPlayer.PSMPCallback() {
@Override
public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
try {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR)
@ -200,7 +201,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
};
PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
IPlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
psmp.playMediaObject(p, true, false, false);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
@ -216,9 +217,9 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
public void testPlayMediaObjectStreamStartNoPrepare() throws InterruptedException {
final Context c = getInstrumentation().getTargetContext();
final CountDownLatch countDownLatch = new CountDownLatch(2);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
IPlaybackServiceMediaPlayer.PSMPCallback callback = new IPlaybackServiceMediaPlayer.PSMPCallback() {
@Override
public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
try {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR)
@ -278,7 +279,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
IPlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
psmp.playMediaObject(p, true, true, false);
@ -295,9 +296,9 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
public void testPlayMediaObjectStreamNoStartPrepare() throws InterruptedException {
final Context c = getInstrumentation().getTargetContext();
final CountDownLatch countDownLatch = new CountDownLatch(4);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
IPlaybackServiceMediaPlayer.PSMPCallback callback = new IPlaybackServiceMediaPlayer.PSMPCallback() {
@Override
public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
try {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR)
@ -360,7 +361,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
IPlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
psmp.playMediaObject(p, true, false, true);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
@ -375,9 +376,9 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
public void testPlayMediaObjectStreamStartPrepare() throws InterruptedException {
final Context c = getInstrumentation().getTargetContext();
final CountDownLatch countDownLatch = new CountDownLatch(5);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
IPlaybackServiceMediaPlayer.PSMPCallback callback = new IPlaybackServiceMediaPlayer.PSMPCallback() {
@Override
public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
try {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR)
@ -444,7 +445,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
};
PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
IPlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
psmp.playMediaObject(p, true, true, true);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
@ -458,9 +459,9 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
public void testPlayMediaObjectLocalNoStartNoPrepare() throws InterruptedException {
final Context c = getInstrumentation().getTargetContext();
final CountDownLatch countDownLatch = new CountDownLatch(2);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
IPlaybackServiceMediaPlayer.PSMPCallback callback = new IPlaybackServiceMediaPlayer.PSMPCallback() {
@Override
public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
try {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR)
@ -521,7 +522,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
};
PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
IPlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
psmp.playMediaObject(p, false, false, false);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
@ -536,9 +537,9 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
public void testPlayMediaObjectLocalStartNoPrepare() throws InterruptedException {
final Context c = getInstrumentation().getTargetContext();
final CountDownLatch countDownLatch = new CountDownLatch(2);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
IPlaybackServiceMediaPlayer.PSMPCallback callback = new IPlaybackServiceMediaPlayer.PSMPCallback() {
@Override
public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
try {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR)
@ -598,7 +599,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
IPlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
psmp.playMediaObject(p, false, true, false);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
@ -613,9 +614,9 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
public void testPlayMediaObjectLocalNoStartPrepare() throws InterruptedException {
final Context c = getInstrumentation().getTargetContext();
final CountDownLatch countDownLatch = new CountDownLatch(4);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
IPlaybackServiceMediaPlayer.PSMPCallback callback = new IPlaybackServiceMediaPlayer.PSMPCallback() {
@Override
public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
try {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR)
@ -678,7 +679,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
IPlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
psmp.playMediaObject(p, false, false, true);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
@ -692,9 +693,9 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
public void testPlayMediaObjectLocalStartPrepare() throws InterruptedException {
final Context c = getInstrumentation().getTargetContext();
final CountDownLatch countDownLatch = new CountDownLatch(5);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
IPlaybackServiceMediaPlayer.PSMPCallback callback = new IPlaybackServiceMediaPlayer.PSMPCallback() {
@Override
public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
try {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR)
@ -761,7 +762,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
IPlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
psmp.playMediaObject(p, false, true, true);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
@ -773,9 +774,9 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
private final PlaybackServiceMediaPlayer.PSMPCallback defaultCallback = new PlaybackServiceMediaPlayer.PSMPCallback() {
private final IPlaybackServiceMediaPlayer.PSMPCallback defaultCallback = new IPlaybackServiceMediaPlayer.PSMPCallback() {
@Override
public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
checkPSMPInfo(newInfo);
}
@ -823,9 +824,9 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
final int latchCount = (stream && reinit) ? 2 : 1;
final CountDownLatch countDownLatch = new CountDownLatch(latchCount);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
IPlaybackServiceMediaPlayer.PSMPCallback callback = new IPlaybackServiceMediaPlayer.PSMPCallback() {
@Override
public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR) {
if (assertionError == null)
@ -899,7 +900,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
IPlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
if (initialState == PlayerStatus.PLAYING) {
psmp.playMediaObject(p, stream, true, true);
@ -954,9 +955,9 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
(initialState == PlayerStatus.PREPARED) ? 1 : 0;
final CountDownLatch countDownLatch = new CountDownLatch(latchCount);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
IPlaybackServiceMediaPlayer.PSMPCallback callback = new IPlaybackServiceMediaPlayer.PSMPCallback() {
@Override
public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR) {
if (assertionError == null)
@ -1015,7 +1016,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
IPlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
if (initialState == PlayerStatus.PREPARED || initialState == PlayerStatus.PLAYING || initialState == PlayerStatus.PAUSED) {
boolean startWhenPrepared = (initialState != PlayerStatus.PREPARED);
psmp.playMediaObject(writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL), false, startWhenPrepared, true);
@ -1047,9 +1048,9 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
final Context c = getInstrumentation().getTargetContext();
final int latchCount = 1;
final CountDownLatch countDownLatch = new CountDownLatch(latchCount);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
IPlaybackServiceMediaPlayer.PSMPCallback callback = new IPlaybackServiceMediaPlayer.PSMPCallback() {
@Override
public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR) {
if (assertionError == null)
@ -1106,7 +1107,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
IPlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
if (initialState == PlayerStatus.INITIALIZED
|| initialState == PlayerStatus.PLAYING
@ -1152,9 +1153,9 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
final Context c = getInstrumentation().getTargetContext();
final int latchCount = 2;
final CountDownLatch countDownLatch = new CountDownLatch(latchCount);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
IPlaybackServiceMediaPlayer.PSMPCallback callback = new IPlaybackServiceMediaPlayer.PSMPCallback() {
@Override
public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR) {
if (assertionError == null)
@ -1210,7 +1211,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
return false;
}
};
PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
IPlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
boolean prepareImmediately = initialState != PlayerStatus.INITIALIZED;
boolean startImmediately = initialState != PlayerStatus.PREPARED;

View File

@ -0,0 +1,108 @@
package de.danoeh.antennapod.core.service.playback;
import android.support.annotation.NonNull;
import android.support.v4.media.session.MediaSessionCompat;
import android.util.Pair;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.util.playback.Playable;
/**
* Interface that allows for different implementations of the PlaybackServiceMediaPlayer for local
* and remote (cast devices) playback.
*/
public interface IPlaybackServiceMediaPlayer {
void playMediaObject(@NonNull Playable playable, boolean stream, boolean startWhenPrepared, boolean prepareImmediately);
void resume();
void pause(boolean abandonFocus, boolean reinit);
void prepare();
void reinit();
void seekTo(int t);
void seekDelta(int d);
void seekToChapter(@NonNull Chapter c);
int getDuration();
int getPosition();
boolean isStartWhenPrepared();
void setStartWhenPrepared(boolean startWhenPrepared);
boolean canSetSpeed();
void setSpeed(float speed);
float getPlaybackSpeed();
void setVolume(float volumeLeft, float volumeRight);
boolean canDownmix();
void setDownmix(boolean enable);
MediaType getCurrentMediaType();
boolean isStreaming();
void shutdown();
void setVideoSurface(SurfaceHolder surface);
void resetVideoSurface();
Pair<Integer, Integer> getVideoSize();
PSMPInfo getPSMPInfo();
PlayerStatus getPlayerStatus();
Playable getPlayable();
void endPlayback(boolean wasSkipped);
void stop();
interface PSMPCallback {
void statusChanged(PSMPInfo newInfo);
void shouldStop();
void playbackSpeedChanged(float s);
void setSpeedAbilityChanged();
void onBufferingUpdate(int percent);
void updateMediaSessionMetadata(Playable p);
boolean onMediaPlayerInfo(int code);
boolean onMediaPlayerError(Object inObj, int what, int extra);
boolean endPlayback(boolean playNextEpisode, boolean wasSkipped);
}
/**
* Holds information about a PSMP object.
*/
class PSMPInfo {
public PlayerStatus playerStatus;
public Playable playable;
public PSMPInfo(PlayerStatus playerStatus, Playable playable) {
this.playerStatus = playerStatus;
this.playable = playable;
}
}
}

View File

@ -36,7 +36,7 @@ import de.danoeh.antennapod.core.util.playback.VideoPlayer;
/**
* Manages the MediaPlayer object of the PlaybackService.
*/
public class PlaybackServiceMediaPlayer {
public class LocalPSMP implements IPlaybackServiceMediaPlayer {
public static final String TAG = "PlaybackSvcMediaPlayer";
/**
@ -74,8 +74,8 @@ public class PlaybackServiceMediaPlayer {
*/
private WifiManager.WifiLock wifiLock;
public PlaybackServiceMediaPlayer(@NonNull Context context,
@NonNull PSMPCallback callback) {
public LocalPSMP(@NonNull Context context,
@NonNull PSMPCallback callback) {
this.context = context;
this.callback = callback;
this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
@ -124,6 +124,7 @@ public class PlaybackServiceMediaPlayer {
* for playback immediately (see 'prepareImmediately' parameter for more details)
* @param prepareImmediately Set to true if the method should also prepare the episode for playback.
*/
@Override
public void playMediaObject(@NonNull final Playable playable, final boolean stream, final boolean startWhenPrepared, final boolean prepareImmediately) {
Log.d(TAG, "playMediaObject(...)");
executor.submit(() -> {
@ -194,7 +195,7 @@ public class PlaybackServiceMediaPlayer {
this.mediaType = media.getMediaType();
this.videoSize = null;
createMediaPlayer();
PlaybackServiceMediaPlayer.this.startWhenPrepared.set(startWhenPrepared);
LocalPSMP.this.startWhenPrepared.set(startWhenPrepared);
setPlayerStatus(PlayerStatus.INITIALIZING, media);
try {
media.loadMetadata();
@ -224,6 +225,7 @@ public class PlaybackServiceMediaPlayer {
* <p/>
* This method is executed on an internal executor service.
*/
@Override
public void resume() {
executor.submit(() -> {
playerLock.lock();
@ -280,6 +282,7 @@ public class PlaybackServiceMediaPlayer {
* @param reinit is true if service should reinit after pausing if the media
* file is being streamed
*/
@Override
public void pause(final boolean abandonFocus, final boolean reinit) {
executor.submit(() -> {
playerLock.lock();
@ -310,6 +313,7 @@ public class PlaybackServiceMediaPlayer {
* <p/>
* This method is executed on an internal executor service.
*/
@Override
public void prepare() {
executor.submit(() -> {
playerLock.lock();
@ -370,6 +374,7 @@ public class PlaybackServiceMediaPlayer {
* <p/>
* This method is executed on an internal executor service.
*/
@Override
public void reinit() {
executor.submit(() -> {
playerLock.lock();
@ -434,6 +439,7 @@ public class PlaybackServiceMediaPlayer {
* <p/>
* This method is executed on an internal executor service.
*/
@Override
public void seekTo(final int t) {
executor.submit(() -> seekToSync(t));
}
@ -443,6 +449,7 @@ public class PlaybackServiceMediaPlayer {
*
* @param d offset from current position (positive or negative)
*/
@Override
public void seekDelta(final int d) {
executor.submit(() -> {
playerLock.lock();
@ -460,6 +467,7 @@ public class PlaybackServiceMediaPlayer {
/**
* Seek to the start of the specified chapter.
*/
@Override
public void seekToChapter(@NonNull Chapter c) {
seekTo((int) c.getStart());
}
@ -467,6 +475,7 @@ public class PlaybackServiceMediaPlayer {
/**
* Returns the duration of the current media object or INVALID_TIME if the duration could not be retrieved.
*/
@Override
public int getDuration() {
if (!playerLock.tryLock()) {
return INVALID_TIME;
@ -488,6 +497,7 @@ public class PlaybackServiceMediaPlayer {
/**
* Returns the position of the current media object or INVALID_TIME if the position could not be retrieved.
*/
@Override
public int getPosition() {
try {
if (!playerLock.tryLock(50, TimeUnit.MILLISECONDS)) {
@ -513,10 +523,12 @@ public class PlaybackServiceMediaPlayer {
return retVal;
}
@Override
public boolean isStartWhenPrepared() {
return startWhenPrepared.get();
}
@Override
public void setStartWhenPrepared(boolean startWhenPrepared) {
this.startWhenPrepared.set(startWhenPrepared);
}
@ -524,6 +536,7 @@ public class PlaybackServiceMediaPlayer {
/**
* Returns true if the playback speed can be adjusted.
*/
@Override
public boolean canSetSpeed() {
boolean retVal = false;
if (mediaPlayer != null && media != null && media.getMediaType() == MediaType.AUDIO) {
@ -552,6 +565,7 @@ public class PlaybackServiceMediaPlayer {
* Sets the playback speed.
* This method is executed on an internal executor service.
*/
@Override
public void setSpeed(final float speed) {
executor.submit(() -> setSpeedSync(speed));
}
@ -559,6 +573,7 @@ public class PlaybackServiceMediaPlayer {
/**
* Returns the current playback speed. If the playback speed could not be retrieved, 1 is returned.
*/
@Override
public float getPlaybackSpeed() {
if (!playerLock.tryLock()) {
return 1;
@ -578,6 +593,7 @@ public class PlaybackServiceMediaPlayer {
* Sets the playback volume.
* This method is executed on an internal executor service.
*/
@Override
public void setVolume(final float volumeLeft, float volumeRight) {
executor.submit(() -> setVolumeSync(volumeLeft, volumeRight));
}
@ -598,6 +614,7 @@ public class PlaybackServiceMediaPlayer {
/**
* Returns true if the mediaplayer can mix stereo down to mono
*/
@Override
public boolean canDownmix() {
boolean retVal = false;
if (mediaPlayer != null && media != null && media.getMediaType() == MediaType.AUDIO) {
@ -606,6 +623,7 @@ public class PlaybackServiceMediaPlayer {
return retVal;
}
@Override
public void setDownmix(boolean enable) {
playerLock.lock();
if (media != null && media.getMediaType() == MediaType.AUDIO) {
@ -615,10 +633,12 @@ public class PlaybackServiceMediaPlayer {
playerLock.unlock();
}
@Override
public MediaType getCurrentMediaType() {
return mediaType;
}
@Override
public boolean isStreaming() {
return stream;
}
@ -627,6 +647,7 @@ public class PlaybackServiceMediaPlayer {
/**
* Releases internally used resources. This method should only be called when the object is not used anymore.
*/
@Override
public void shutdown() {
executor.shutdown();
if (mediaPlayer != null) {
@ -635,6 +656,7 @@ public class PlaybackServiceMediaPlayer {
releaseWifiLockIfNecessary();
}
@Override
public void setVideoSurface(final SurfaceHolder surface) {
executor.submit(() -> {
playerLock.lock();
@ -645,6 +667,7 @@ public class PlaybackServiceMediaPlayer {
});
}
@Override
public void resetVideoSurface() {
executor.submit(() -> {
playerLock.lock();
@ -662,6 +685,7 @@ public class PlaybackServiceMediaPlayer {
* return an invalid non-null value if the getVideoWidth() and getVideoHeight() methods of the media player return
* invalid values.
*/
@Override
public Pair<Integer, Integer> getVideoSize() {
if (!playerLock.tryLock()) {
// use cached value if lock can't be aquired
@ -684,6 +708,7 @@ public class PlaybackServiceMediaPlayer {
*
* @return The PSMPInfo object.
*/
@Override
public synchronized PSMPInfo getPSMPInfo() {
return new PSMPInfo(playerStatus, media);
}
@ -694,6 +719,7 @@ public class PlaybackServiceMediaPlayer {
* could result in nonsensical results (like a status of PLAYING, but a null playable)
* @return the current player status
*/
@Override
public PlayerStatus getPlayerStatus() {
return playerStatus;
}
@ -704,6 +730,7 @@ public class PlaybackServiceMediaPlayer {
* could result in nonsensical results (like a status of PLAYING, but a null playable)
* @return the current media. May be null
*/
@Override
public Playable getPlayable() {
return media;
}
@ -799,6 +826,7 @@ public class PlaybackServiceMediaPlayer {
};
@Override
public void endPlayback(final boolean wasSkipped) {
executor.submit(() -> {
playerLock.lock();
@ -821,11 +849,12 @@ public class PlaybackServiceMediaPlayer {
}
/**
* Moves the PlaybackServiceMediaPlayer into STOPPED state. This call is only valid if the player is currently in
* Moves the LocalPSMP into STOPPED state. This call is only valid if the player is currently in
* INDETERMINATE state, for example after a call to endPlayback.
* This method will only take care of changing the PlayerStatus of this object! Other tasks like
* abandoning audio focus have to be done with other methods.
*/
@Override
public void stop() {
executor.submit(() -> {
playerLock.lock();
@ -858,39 +887,6 @@ public class PlaybackServiceMediaPlayer {
}
}
/**
* Holds information about a PSMP object.
*/
public class PSMPInfo {
public PlayerStatus playerStatus;
public Playable playable;
public PSMPInfo(PlayerStatus playerStatus, Playable playable) {
this.playerStatus = playerStatus;
this.playable = playable;
}
}
public interface PSMPCallback {
void statusChanged(PSMPInfo newInfo);
void shouldStop();
void playbackSpeedChanged(float s);
void setSpeedAbilityChanged();
void onBufferingUpdate(int percent);
void updateMediaSessionMetadata(Playable p);
boolean onMediaPlayerInfo(int code);
boolean onMediaPlayerError(Object inObj, int what, int extra);
boolean endPlayback(boolean playNextEpisode, boolean wasSkipped);
}
private IPlayer setMediaPlayerListeners(IPlayer mp) {
if (mp != null && media != null) {
if (media.getMediaType() == MediaType.AUDIO) {

View File

@ -174,7 +174,7 @@ public class PlaybackService extends Service implements SharedPreferences.OnShar
private static final int NOTIFICATION_ID = 1;
private PlaybackServiceMediaPlayer mediaPlayer;
private IPlaybackServiceMediaPlayer mediaPlayer;
private PlaybackServiceTaskManager taskManager;
/**
* Only used for Lollipop notifications.
@ -248,7 +248,7 @@ public class PlaybackService extends Service implements SharedPreferences.OnShar
registerReceiver(pauseResumeCurrentEpisodeReceiver, new IntentFilter(
ACTION_RESUME_PLAY_CURRENT_EPISODE));
taskManager = new PlaybackServiceTaskManager(this, taskManagerCallback);
mediaPlayer = new PlaybackServiceMediaPlayer(this, mediaPlayerCallback);
mediaPlayer = new LocalPSMP(this, mediaPlayerCallback);
ComponentName eventReceiver = new ComponentName(getApplicationContext(),
MediaButtonReceiver.class);
@ -353,7 +353,7 @@ public class PlaybackService extends Service implements SharedPreferences.OnShar
*/
private void handleKeycode(int keycode, int source) {
Log.d(TAG, "Handling keycode: " + keycode);
final PlaybackServiceMediaPlayer.PSMPInfo info = mediaPlayer.getPSMPInfo();
final IPlaybackServiceMediaPlayer.PSMPInfo info = mediaPlayer.getPSMPInfo();
final PlayerStatus status = info.playerStatus;
switch (keycode) {
case KeyEvent.KEYCODE_HEADSETHOOK:
@ -491,9 +491,9 @@ public class PlaybackService extends Service implements SharedPreferences.OnShar
}
};
private final PlaybackServiceMediaPlayer.PSMPCallback mediaPlayerCallback = new PlaybackServiceMediaPlayer.PSMPCallback() {
private final IPlaybackServiceMediaPlayer.PSMPCallback mediaPlayerCallback = new IPlaybackServiceMediaPlayer.PSMPCallback() {
@Override
public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
public void statusChanged(IPlaybackServiceMediaPlayer.PSMPInfo newInfo) {
currentMediaType = mediaPlayer.getCurrentMediaType();
updateMediaSession(newInfo.playerStatus);
switch (newInfo.playerStatus) {
@ -779,7 +779,7 @@ public class PlaybackService extends Service implements SharedPreferences.OnShar
SharedPreferences.Editor editor = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext()).edit();
PlaybackServiceMediaPlayer.PSMPInfo info = mediaPlayer.getPSMPInfo();
IPlaybackServiceMediaPlayer.PSMPInfo info = mediaPlayer.getPSMPInfo();
MediaType mediaType = mediaPlayer.getCurrentMediaType();
boolean stream = mediaPlayer.isStreaming();
int playerStatus = getCurrentPlayerStatusAsInt(info.playerStatus);
@ -940,7 +940,7 @@ public class PlaybackService extends Service implements SharedPreferences.OnShar
/**
* Prepares notification and starts the service in the foreground.
*/
private void setupNotification(final PlaybackServiceMediaPlayer.PSMPInfo info) {
private void setupNotification(final IPlaybackServiceMediaPlayer.PSMPInfo info) {
final PendingIntent pIntent = PendingIntent.getActivity(this, 0,
PlaybackService.getPlayerActivityIntent(this),
PendingIntent.FLAG_UPDATE_CURRENT);
@ -1144,7 +1144,7 @@ public class PlaybackService extends Service implements SharedPreferences.OnShar
return taskManager.getSleepTimerTimeLeft();
}
private void bluetoothNotifyChange(PlaybackServiceMediaPlayer.PSMPInfo info, String whatChanged) {
private void bluetoothNotifyChange(IPlaybackServiceMediaPlayer.PSMPInfo info, String whatChanged) {
boolean isPlaying = false;
if (info.playerStatus == PlayerStatus.PLAYING) {
@ -1319,7 +1319,7 @@ public class PlaybackService extends Service implements SharedPreferences.OnShar
mediaPlayer.reinit();
}
public PlaybackServiceMediaPlayer.PSMPInfo getPSMPInfo() {
public IPlaybackServiceMediaPlayer.PSMPInfo getPSMPInfo() {
return mediaPlayer.getPSMPInfo();
}
@ -1391,7 +1391,7 @@ public class PlaybackService extends Service implements SharedPreferences.OnShar
}
/**
* @see de.danoeh.antennapod.core.service.playback.PlaybackServiceMediaPlayer#seekToChapter(de.danoeh.antennapod.core.feed.Chapter)
* @see LocalPSMP#seekToChapter(de.danoeh.antennapod.core.feed.Chapter)
*/
public void seekToChapter(Chapter c) {
mediaPlayer.seekToChapter(c);

View File

@ -34,8 +34,8 @@ import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.playback.LocalPSMP;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.service.playback.PlaybackServiceMediaPlayer;
import de.danoeh.antennapod.core.service.playback.PlayerStatus;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.util.Converter;
@ -281,7 +281,7 @@ public abstract class PlaybackController {
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Received statusUpdate Intent.");
if (isConnectedToPlaybackService()) {
PlaybackServiceMediaPlayer.PSMPInfo info = playbackService.getPSMPInfo();
LocalPSMP.PSMPInfo info = playbackService.getPSMPInfo();
status = info.playerStatus;
media = info.playable;
handleStatus();