Methods Summary |
---|
private void | check(boolean condition, java.lang.String exception)
if (!condition) {
throw new IllegalStateException(exception);
}
|
private void | checkNotNull(java.lang.Object argument, java.lang.String argumentName)
if (argument == null) {
throw new IllegalArgumentException(argumentName + " must not be null");
}
|
public static MediaPlayerProxy | createVariableSpeed(java.util.concurrent.Executor executor)
return new SingleThreadedMediaPlayerProxy(new VariableSpeed(executor));
|
public int | getCurrentPosition()
synchronized (lock) {
check(!mHasBeenReleased, "has been released, reset before use");
if (!mHasStartedPlayback) {
return 0;
}
if (!hasEngineBeenInitialized()) {
return 0;
}
if (!hasPlaybackFinished()) {
return VariableSpeedNative.getCurrentPosition();
}
return mDuration;
}
|
public int | getDuration()
synchronized (lock) {
check(!mHasBeenReleased, "has been released, reset before use");
check(mHasDuration, "you haven't called prepare, can't get the duration");
return mDuration;
}
|
private boolean | hasEngineBeenInitialized()
return mEngineInitializedLatch.getCount() <= 0;
|
private boolean | hasPlaybackFinished()
return mPlaybackFinishedLatch.getCount() <= 0;
|
private void | innerSetDataSource(MediaPlayerDataSource source)
checkNotNull(source, "source");
synchronized (lock) {
check(!mHasBeenReleased, "has been released, reset before use");
check(mDataSource == null, "cannot setDataSource more than once");
mDataSource = source;
}
|
public boolean | isPlaying()
synchronized (lock) {
return isReadyToPlay() && mHasStartedPlayback && !hasPlaybackFinished();
}
|
public boolean | isReadyToPlay()
synchronized (lock) {
return !mHasBeenReleased && mHasDuration;
}
|
public void | pause()
synchronized (lock) {
check(!mHasBeenReleased, "has been released, reset before use");
}
stopCurrentPlayback();
|
public void | prepare()
MediaPlayerDataSource dataSource;
int audioStreamType;
synchronized (lock) {
check(!mHasBeenReleased, "has been released, reset before use");
check(mDataSource != null, "must setDataSource before you prepare");
check(!mIsPrepared, "cannot prepare more than once");
mIsPrepared = true;
dataSource = mDataSource;
audioStreamType = mAudioStreamType;
}
// NYI This should become another executable that we can wait on.
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(audioStreamType);
dataSource.setAsSourceFor(mediaPlayer);
mediaPlayer.prepare();
synchronized (lock) {
check(!mHasDuration, "can't have duration, this is impossible");
mHasDuration = true;
mDuration = mediaPlayer.getDuration();
}
mediaPlayer.release();
|
public void | release()
synchronized (lock) {
if (mHasBeenReleased) {
return;
}
mHasBeenReleased = true;
}
stopCurrentPlayback();
boolean requiresShutdown = false;
synchronized (lock) {
requiresShutdown = hasEngineBeenInitialized();
}
if (requiresShutdown) {
VariableSpeedNative.shutdownEngine();
}
synchronized (lock) {
mIsReadyToReUse = true;
}
|
private void | reportException(java.lang.Exception e)
Log.e(TAG, "playback error:", e);
|
public void | reset()
boolean requiresRelease;
synchronized (lock) {
requiresRelease = !mHasBeenReleased;
}
if (requiresRelease) {
release();
}
synchronized (lock) {
check(mHasBeenReleased && mIsReadyToReUse, "to re-use, must call reset after release");
mDataSource = null;
mIsPrepared = false;
mHasDuration = false;
mHasStartedPlayback = false;
mEngineInitializedLatch = new CountDownLatch(1);
mPlaybackFinishedLatch = new CountDownLatch(1);
mHasBeenReleased = false;
mIsReadyToReUse = false;
mSkipCompletionReport = false;
mStartPosition = 0;
mDuration = 0;
}
|
public void | seekTo(int startPosition)
boolean currentlyPlaying;
MediaPlayerDataSource dataSource;
synchronized (lock) {
check(!mHasBeenReleased, "has been released, reset before use");
check(mHasDuration, "you can't seek until you have prepared");
currentlyPlaying = mHasStartedPlayback && !hasPlaybackFinished();
mStartPosition = Math.min(startPosition, mDuration);
dataSource = mDataSource;
}
if (currentlyPlaying) {
stopAndStartPlayingAgain(dataSource);
}
|
public void | setAudioStreamType(int audioStreamType)
synchronized (lock) {
mAudioStreamType = audioStreamType;
}
|
public void | setDataSource(android.content.Context context, android.net.Uri intentUri)
checkNotNull(context, "context");
checkNotNull(intentUri, "intentUri");
innerSetDataSource(new MediaPlayerDataSource(context, intentUri));
|
public void | setDataSource(java.lang.String path)
checkNotNull(path, "path");
innerSetDataSource(new MediaPlayerDataSource(path));
|
public void | setOnCompletionListener(MediaPlayer.OnCompletionListener listener)
synchronized (lock) {
check(!mHasBeenReleased, "has been released, reset before use");
mCompletionListener = listener;
}
|
public void | setOnErrorListener(MediaPlayer.OnErrorListener listener)
synchronized (lock) {
check(!mHasBeenReleased, "has been released, reset before use");
// TODO: I haven't actually added any error listener code.
}
|
public void | setVariableSpeed(float rate)
// TODO: are there situations in which the engine has been destroyed, so
// that this will segfault?
synchronized (lock) {
check(!mHasBeenReleased, "has been released, reset before use");
// TODO: This too is wrong, once we've started preparing the variable speed set
// will not be enough.
if (mHasStartedPlayback) {
VariableSpeedNative.setVariableSpeed(rate);
}
mCurrentPlaybackRate = rate;
}
|
public void | start()
MediaPlayerDataSource restartWithThisDataSource = null;
synchronized (lock) {
check(!mHasBeenReleased, "has been released, reset before use");
check(mIsPrepared, "must have prepared before you can start");
if (!mHasStartedPlayback) {
// Playback has not started. Start it.
mHasStartedPlayback = true;
EngineParameters engineParameters = new EngineParameters.Builder()
.initialRate(mCurrentPlaybackRate)
.startPositionMillis(mStartPosition)
.audioStreamType(mAudioStreamType)
.build();
VariableSpeedNative.initializeEngine(engineParameters);
VariableSpeedNative.startPlayback();
mEngineInitializedLatch.countDown();
mExecutor.execute(new PlaybackRunnable(mDataSource));
} else {
// Playback has already started. Restart it, without holding the
// lock.
restartWithThisDataSource = mDataSource;
}
}
if (restartWithThisDataSource != null) {
stopAndStartPlayingAgain(restartWithThisDataSource);
}
|
private void | stopAndStartPlayingAgain(MediaPlayerDataSource source)
stopCurrentPlayback();
reset();
innerSetDataSource(source);
try {
prepare();
} catch (IOException e) {
reportException(e);
return;
}
start();
return;
|
private void | stopCurrentPlayback()Stops the current playback, returns once it has stopped.
boolean isPlaying;
CountDownLatch engineInitializedLatch;
CountDownLatch playbackFinishedLatch;
synchronized (lock) {
isPlaying = mHasStartedPlayback && !hasPlaybackFinished();
engineInitializedLatch = mEngineInitializedLatch;
playbackFinishedLatch = mPlaybackFinishedLatch;
if (isPlaying) {
mSkipCompletionReport = true;
}
}
if (isPlaying) {
waitForLatch(engineInitializedLatch);
VariableSpeedNative.stopPlayback();
waitForLatch(playbackFinishedLatch);
}
|
private void | waitForLatch(java.util.concurrent.CountDownLatch latch)
try {
boolean success = latch.await(1, TimeUnit.SECONDS);
if (!success) {
reportException(new TimeoutException("waited too long"));
}
} catch (InterruptedException e) {
// Preserve the interrupt status, though this is unexpected.
Thread.currentThread().interrupt();
reportException(e);
}
|