// Copyright 2011, Aocate, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.aocate.media;
import java.io.IOException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.media.AudioManager;
import android.net.Uri;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.PowerManager.WakeLock;
import android.util.Log;
import com.aocate.media.MediaPlayer.State;
import com.aocate.presto.service.IDeathCallback_0_8;
import com.aocate.presto.service.IOnBufferingUpdateListenerCallback_0_8;
import com.aocate.presto.service.IOnCompletionListenerCallback_0_8;
import com.aocate.presto.service.IOnErrorListenerCallback_0_8;
import com.aocate.presto.service.IOnInfoListenerCallback_0_8;
import com.aocate.presto.service.IOnPitchAdjustmentAvailableChangedListenerCallback_0_8;
import com.aocate.presto.service.IOnPreparedListenerCallback_0_8;
import com.aocate.presto.service.IOnSeekCompleteListenerCallback_0_8;
import com.aocate.presto.service.IOnSpeedAdjustmentAvailableChangedListenerCallback_0_8;
import com.aocate.presto.service.IPlayMedia_0_8;
/**
* Class for connecting to remote speed-altering, media playing Service
* Note that there is unusually high coupling between MediaPlayer and this
* class. This is an unfortunate compromise, since the alternative was to
* track state in two different places in this code (plus the internal state
* of the remote media player).
* @author aocate
*
*/
public class ServiceBackedMediaPlayer extends MediaPlayerImpl {
static final String INTENT_NAME = "com.aocate.intent.PLAY_AUDIO_ADJUST_SPEED_0_8";
private static final String SBMP_TAG = "AocateServiceBackedMediaPlayer";
private ServiceConnection mPlayMediaServiceConnection = null;
protected IPlayMedia_0_8 pmInterface = null;
private Intent playMediaServiceIntent = null;
// In some cases, we're going to have to replace the
// android.media.MediaPlayer on the fly, and we don't want to touch the
// wrong media player.
private long sessionId = 0;
private boolean isErroring = false;
private int mAudioStreamType = AudioManager.STREAM_MUSIC;
private WakeLock mWakeLock = null;
// So here's the major problem
// Sometimes the service won't exist or won't be connected,
// so start with an android.media.MediaPlayer, and when
// the service is connected, use that from then on
public ServiceBackedMediaPlayer(MediaPlayer owningMediaPlayer, final Context context, final ServiceConnection serviceConnection) {
super(owningMediaPlayer, context);
Log.d(SBMP_TAG, "Instantiating ServiceBackedMediaPlayer 87");
this.playMediaServiceIntent =
new Intent(INTENT_NAME);
this.mPlayMediaServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
IPlayMedia_0_8 tmpPlayMediaInterface = IPlayMedia_0_8.Stub.asInterface((IBinder) service);
Log.d(SBMP_TAG, "Setting up pmInterface 94");
if (ServiceBackedMediaPlayer.this.sessionId == 0) {
try {
// The IDeathCallback isn't a conventional callback.
// It exists so that if the client ceases to exist,
// the Service becomes aware of that and can shut
// down whatever it needs to shut down
ServiceBackedMediaPlayer.this.sessionId = tmpPlayMediaInterface.startSession(new IDeathCallback_0_8.Stub() {
});
// This is really bad if this fails
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
Log.d(SBMP_TAG, "Assigning pmInterface");
ServiceBackedMediaPlayer.this.setOnBufferingUpdateCallback(tmpPlayMediaInterface);
ServiceBackedMediaPlayer.this.setOnCompletionCallback(tmpPlayMediaInterface);
ServiceBackedMediaPlayer.this.setOnErrorCallback(tmpPlayMediaInterface);
ServiceBackedMediaPlayer.this.setOnInfoCallback(tmpPlayMediaInterface);
ServiceBackedMediaPlayer.this.setOnPitchAdjustmentAvailableChangedListener(tmpPlayMediaInterface);
ServiceBackedMediaPlayer.this.setOnPreparedCallback(tmpPlayMediaInterface);
ServiceBackedMediaPlayer.this.setOnSeekCompleteCallback(tmpPlayMediaInterface);
ServiceBackedMediaPlayer.this.setOnSpeedAdjustmentAvailableChangedCallback(tmpPlayMediaInterface);
// In order to avoid race conditions from the sessionId or listener not being assigned
pmInterface = tmpPlayMediaInterface;
Log.d(SBMP_TAG, "Invoking onServiceConnected");
serviceConnection.onServiceConnected(name, service);
}
public void onServiceDisconnected(ComponentName name) {
Log.d(SBMP_TAG, "onServiceDisconnected 114");
pmInterface = null;
sessionId = 0;
serviceConnection.onServiceDisconnected(name);
}
};
Log.d(SBMP_TAG, "Connecting PlayMediaService 124");
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
private boolean ConnectPlayMediaService() {
Log.d(SBMP_TAG, "ConnectPlayMediaService()");
if (MediaPlayer.isIntentAvailable(mContext, INTENT_NAME)) {
Log.d(SBMP_TAG, INTENT_NAME + " is available");
if (pmInterface == null) {
try {
Log.d(SBMP_TAG, "Binding service");
return mContext.bindService(playMediaServiceIntent, mPlayMediaServiceConnection, Context.BIND_AUTO_CREATE);
} catch (Exception e) {
return false;
}
} else {
Log.d(SBMP_TAG, "Service already bound");
return true;
}
}
else {
Log.d(SBMP_TAG, INTENT_NAME + " is not available");
return false;
}
}
/**
* Returns true if pitch can be changed at this moment
* @return True if pitch can be changed
*/
@Override
public boolean canSetPitch() {
Log.d(SBMP_TAG, "canSetPitch() 155");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
if (pmInterface != null) {
// Can't set pitch if the service isn't connected
try {
return pmInterface.canSetPitch(ServiceBackedMediaPlayer.this.sessionId);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
return false;
}
/**
* Returns true if speed can be changed at this moment
* @return True if speed can be changed
*/
@Override
public boolean canSetSpeed() {
Log.d(SBMP_TAG, "canSetSpeed() 180");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
if (pmInterface != null) {
// Can't set speed if the service isn't connected
try {
return pmInterface.canSetSpeed(ServiceBackedMediaPlayer.this.sessionId);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
return false;
}
void error(int what, int extra) {
owningMediaPlayer.lock.lock();
Log.e(SBMP_TAG, "error(" + what + ", " + extra + ")");
try {
if (!this.isErroring) {
this.isErroring = true;
owningMediaPlayer.state = State.ERROR;
if (owningMediaPlayer.onErrorListener != null) {
if (owningMediaPlayer.onErrorListener.onError(owningMediaPlayer, what, extra)) {
return;
}
}
if (owningMediaPlayer.onCompletionListener != null) {
owningMediaPlayer.onCompletionListener.onCompletion(owningMediaPlayer);
}
}
}
finally {
this.isErroring = false;
owningMediaPlayer.lock.unlock();
}
}
protected void finalize() throws Throwable {
owningMediaPlayer.lock.lock();
try {
Log.d(SBMP_TAG, "finalize() 224");
this.release();
}
finally {
owningMediaPlayer.lock.unlock();
}
}
/**
* Returns the number of steps (in a musical scale) by which playback is
* currently shifted. When greater than zero, pitch is shifted up.
* When less than zero, pitch is shifted down.
* @return The number of steps pitch is currently shifted by
*/
@Override
public float getCurrentPitchStepsAdjustment() {
Log.d(SBMP_TAG, "getCurrentPitchStepsAdjustment() 240");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
if (pmInterface != null) {
// Can't set pitch if the service isn't connected
try {
return pmInterface.getCurrentPitchStepsAdjustment(
ServiceBackedMediaPlayer.this.sessionId);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
return 0f;
}
/**
* Functions identically to android.media.MediaPlayer.getCurrentPosition()
* @return Current position (in milliseconds)
*/
@Override
public int getCurrentPosition() {
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
try {
return pmInterface.getCurrentPosition(
ServiceBackedMediaPlayer.this.sessionId);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
return 0;
}
/**
* Returns the current speed multiplier. Defaults to 1.0 (normal speed)
* @return The current speed multiplier
*/
@Override
public float getCurrentSpeedMultiplier() {
Log.d(SBMP_TAG, "getCurrentSpeedMultiplier() 286");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
if (pmInterface != null) {
// Can't set speed if the service isn't connected
try {
return pmInterface.getCurrentSpeedMultiplier(
ServiceBackedMediaPlayer.this.sessionId);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
return 1;
}
/**
* Functions identically to android.media.MediaPlayer.getDuration()
* @return Length of the track (in milliseconds)
*/
@Override
public int getDuration() {
Log.d(SBMP_TAG, "getDuration() 311");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
try {
return pmInterface.getDuration(ServiceBackedMediaPlayer.this.sessionId);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
return 0;
}
/**
* Get the maximum value that can be passed to setPlaybackSpeed
* @return The maximum speed multiplier
*/
@Override
public float getMaxSpeedMultiplier() {
Log.d(SBMP_TAG, "getMaxSpeedMultiplier() 332");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
if (pmInterface != null) {
// Can't set speed if the Service isn't connected
try {
return pmInterface.getMaxSpeedMultiplier(
ServiceBackedMediaPlayer.this.sessionId);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
return 1f;
}
/**
* Get the minimum value that can be passed to setPlaybackSpeed
* @return The minimum speed multiplier
*/
@Override
public float getMinSpeedMultiplier() {
Log.d(SBMP_TAG, "getMinSpeedMultiplier() 357");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
if (pmInterface != null) {
// Can't set speed if the Service isn't connected
try {
return pmInterface.getMinSpeedMultiplier(
ServiceBackedMediaPlayer.this.sessionId);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
return 1f;
}
public int getServiceVersionCode() {
Log.d(SBMP_TAG, "getVersionCode");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
try {
return pmInterface.getVersionCode();
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
return 0;
}
public String getServiceVersionName() {
Log.d(SBMP_TAG, "getVersionName");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
try {
return pmInterface.getVersionName();
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
return "";
}
public boolean isConnected() {
return (pmInterface != null);
}
/**
* Functions identically to android.media.MediaPlayer.isLooping()
* @return True if the track is looping
*/
@Override
public boolean isLooping() {
Log.d(SBMP_TAG, "isLooping() 382");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
try {
return pmInterface.isLooping(ServiceBackedMediaPlayer.this.sessionId);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
return false;
}
/**
* Functions identically to android.media.MediaPlayer.isPlaying()
* @return True if the track is playing
*/
@Override
public boolean isPlaying() {
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
if (pmInterface != null) {
try {
return pmInterface.isPlaying(ServiceBackedMediaPlayer.this.sessionId);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
return false;
}
/**
* Functions identically to android.media.MediaPlayer.pause()
* Pauses the track
*/
@Override
public void pause() {
Log.d(SBMP_TAG, "pause() 424");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
try {
pmInterface.pause(ServiceBackedMediaPlayer.this.sessionId);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
/**
* Functions identically to android.media.MediaPlayer.prepare()
* Prepares the track. This or prepareAsync must be called before start()
*/
@Override
public void prepare() throws IllegalStateException, IOException {
Log.d(SBMP_TAG, "prepare() 444");
Log.d(SBMP_TAG, "onPreparedCallback is: " + ((this.mOnPreparedCallback == null) ? "null" : "non-null"));
if (pmInterface == null) {
Log.d(SBMP_TAG, "prepare: pmInterface is null");
if (!ConnectPlayMediaService()) {
Log.d(SBMP_TAG, "prepare: Failed to connect play media service");
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
if (pmInterface != null) {
Log.d(SBMP_TAG, "prepare: pmInterface isn't null");
try {
Log.d(SBMP_TAG, "prepare: Remote invoke pmInterface.prepare(" + ServiceBackedMediaPlayer.this.sessionId + ")");
pmInterface.prepare(ServiceBackedMediaPlayer.this.sessionId);
Log.d(SBMP_TAG, "prepare: prepared");
} catch (RemoteException e) {
Log.d(SBMP_TAG, "prepare: RemoteException");
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
Log.d(SBMP_TAG, "Done with prepare()");
}
/**
* Functions identically to android.media.MediaPlayer.prepareAsync()
* Prepares the track. This or prepare must be called before start()
*/
@Override
public void prepareAsync() {
Log.d(SBMP_TAG, "prepareAsync() 469");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
try {
pmInterface.prepareAsync(ServiceBackedMediaPlayer.this.sessionId);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
/**
* Functions identically to android.media.MediaPlayer.release()
* Releases the underlying resources used by the media player.
*/
@Override
public void release() {
Log.d(SBMP_TAG, "release() 492");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
if (pmInterface != null) {
Log.d(SBMP_TAG, "release() 500");
try {
pmInterface.release(ServiceBackedMediaPlayer.this.sessionId);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
mContext.unbindService(this.mPlayMediaServiceConnection);
// Don't try to keep awake (if we were)
this.setWakeMode(mContext, 0);
pmInterface = null;
this.sessionId = 0;
}
if ((this.mWakeLock != null) && this.mWakeLock.isHeld()) {
Log.d(SBMP_TAG, "Releasing wakelock");
this.mWakeLock.release();
}
}
/**
* Functions identically to android.media.MediaPlayer.reset()
* Resets the track to idle state
*/
@Override
public void reset() {
Log.d(SBMP_TAG, "reset() 523");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
try {
pmInterface.reset(ServiceBackedMediaPlayer.this.sessionId);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
/**
* Functions identically to android.media.MediaPlayer.seekTo(int msec)
* Seeks to msec in the track
*/
@Override
public void seekTo(int msec) throws IllegalStateException {
Log.d(SBMP_TAG, "seekTo(" + msec + ")");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
try {
pmInterface.seekTo(ServiceBackedMediaPlayer.this.sessionId, msec);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
/**
* Functions identically to android.media.MediaPlayer.setAudioStreamType(int streamtype)
* Sets the audio stream type.
*/
@Override
public void setAudioStreamType(int streamtype) {
Log.d(SBMP_TAG, "setAudioStreamType(" + streamtype + ")");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
try {
pmInterface.setAudioStreamType(
ServiceBackedMediaPlayer.this.sessionId,
this.mAudioStreamType);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
/**
* Functions identically to android.media.MediaPlayer.setDataSource(Context context, Uri uri)
* Sets uri as data source in the context given
*/
@Override
public void setDataSource(Context context, Uri uri) throws IllegalArgumentException, IllegalStateException, IOException {
Log.d(SBMP_TAG, "setDataSource(context, uri)");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
try {
pmInterface.setDataSourceUri(
ServiceBackedMediaPlayer.this.sessionId,
uri);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
/**
* Functions identically to android.media.MediaPlayer.setDataSource(String path)
* Sets the data source of the track to a file given.
*/
@Override
public void setDataSource(String path) throws IllegalArgumentException, IllegalStateException, IOException {
Log.d(SBMP_TAG, "setDataSource(path)");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
if (pmInterface == null) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
else {
try {
pmInterface.setDataSourceString(
ServiceBackedMediaPlayer.this.sessionId,
path);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
}
/**
* Sets whether to use speed adjustment or not. Speed adjustment on is
* more computation-intensive than with it off.
* @param enableSpeedAdjustment Whether speed adjustment should be supported.
*/
@Override
public void setEnableSpeedAdjustment(boolean enableSpeedAdjustment) {
// TODO: This has no business being here, I think
owningMediaPlayer.lock.lock();
Log.d(SBMP_TAG, "setEnableSpeedAdjustment(enableSpeedAdjustment)");
try {
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
if (pmInterface != null) {
// Can't set speed if the Service isn't connected
try {
pmInterface.setEnableSpeedAdjustment(
ServiceBackedMediaPlayer.this.sessionId,
enableSpeedAdjustment);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
}
finally {
owningMediaPlayer.lock.unlock();
}
}
/**
* Functions identically to android.media.MediaPlayer.setLooping(boolean loop)
* Sets the track to loop infinitely if loop is true, play once if loop is false
*/
@Override
public void setLooping(boolean loop) {
Log.d(SBMP_TAG, "setLooping(" + loop + ")");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
try {
pmInterface.setLooping(ServiceBackedMediaPlayer.this.sessionId, loop);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
/**
* Sets the number of steps (in a musical scale) by which playback is
* currently shifted. When greater than zero, pitch is shifted up.
* When less than zero, pitch is shifted down.
*
* @param pitchSteps The number of steps by which to shift playback
*/
@Override
public void setPitchStepsAdjustment(float pitchSteps) {
Log.d(SBMP_TAG, "setPitchStepsAdjustment(" + pitchSteps + ")");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
if (pmInterface != null) {
// Can't set speed if the Service isn't connected
try {
pmInterface.setPitchStepsAdjustment(
ServiceBackedMediaPlayer.this.sessionId,
pitchSteps);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
}
/**
* Sets the percentage by which pitch is currently shifted. When
* greater than zero, pitch is shifted up. When less than zero, pitch
* is shifted down
* @param f The percentage to shift pitch
*/
@Override
public void setPlaybackPitch(float f) {
Log.d(SBMP_TAG, "setPlaybackPitch(" + f + ")");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
if (pmInterface != null) {
// Can't set speed if the Service isn't connected
try {
pmInterface.setPlaybackPitch(
ServiceBackedMediaPlayer.this.sessionId,
f);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
}
/**
* Set playback speed. 1.0 is normal speed, 2.0 is double speed, and so
* on. Speed should never be set to 0 or below.
* @param f The speed multiplier to use for further playback
*/
@Override
public void setPlaybackSpeed(float f) {
Log.d(SBMP_TAG, "setPlaybackSpeed(" + f + ")");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
if (pmInterface != null) {
// Can't set speed if the Service isn't connected
try {
pmInterface.setPlaybackSpeed(
ServiceBackedMediaPlayer.this.sessionId,
f);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
}
@Override
public void setSpeedAdjustmentAlgorithm(int algorithm) {
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
try {
pmInterface.setSpeedAdjustmentAlgorithm(
ServiceBackedMediaPlayer.this.sessionId,
algorithm);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
/**
* Functions identically to android.media.MediaPlayer.setVolume(float leftVolume, float rightVolume)
* Sets the stereo volume
*/
@Override
public void setVolume(float leftVolume, float rightVolume) {
Log.d(SBMP_TAG, "setVolume(" + leftVolume + ", " + rightVolume + ")");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
try {
pmInterface.setVolume(
ServiceBackedMediaPlayer.this.sessionId,
leftVolume,
rightVolume);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
/**
* Functions identically to android.media.MediaPlayer.setWakeMode(Context context, int mode)
* Acquires a wake lock in the context given. You must request the appropriate permissions
* in your AndroidManifest.xml file.
*/
@Override
// This does not just call .setWakeMode() in the Service because doing so
// would add a permission requirement to the Service. Do it here, and it's
// the client app's responsibility to request that permission
public void setWakeMode(Context context, int mode) {
Log.d(SBMP_TAG, "setWakeMode(context, " + mode + ")");
if ((this.mWakeLock != null)
&& (this.mWakeLock.isHeld())) {
this.mWakeLock.release();
}
if (mode != 0) {
if (this.mWakeLock == null) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
// Since mode can't be changed on the fly, we have to allocate a new one
this.mWakeLock = pm.newWakeLock(mode, this.getClass().getName());
}
this.mWakeLock.acquire();
}
}
private IOnBufferingUpdateListenerCallback_0_8.Stub mOnBufferingUpdateCallback = null;
private void setOnBufferingUpdateCallback(IPlayMedia_0_8 iface) {
try {
if (this.mOnBufferingUpdateCallback == null) {
mOnBufferingUpdateCallback = new IOnBufferingUpdateListenerCallback_0_8.Stub() {
public void onBufferingUpdate(int percent)
throws RemoteException {
owningMediaPlayer.lock.lock();
try {
if ((owningMediaPlayer.onBufferingUpdateListener != null)
&& (owningMediaPlayer.mpi == ServiceBackedMediaPlayer.this)) {
owningMediaPlayer.onBufferingUpdateListener.onBufferingUpdate(owningMediaPlayer, percent);
}
}
finally {
owningMediaPlayer.lock.unlock();
}
}
};
}
iface.registerOnBufferingUpdateCallback(
ServiceBackedMediaPlayer.this.sessionId,
mOnBufferingUpdateCallback);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
private IOnCompletionListenerCallback_0_8.Stub mOnCompletionCallback = null;
private void setOnCompletionCallback(IPlayMedia_0_8 iface) {
try {
if (this.mOnCompletionCallback == null) {
this.mOnCompletionCallback = new IOnCompletionListenerCallback_0_8.Stub() {
public void onCompletion() throws RemoteException {
owningMediaPlayer.lock.lock();
Log.d(SBMP_TAG, "onCompletionListener being called");
try {
if (owningMediaPlayer.onCompletionListener != null) {
owningMediaPlayer.onCompletionListener.onCompletion(owningMediaPlayer);
}
}
finally {
owningMediaPlayer.lock.unlock();
}
}
};
}
iface.registerOnCompletionCallback(
ServiceBackedMediaPlayer.this.sessionId,
this.mOnCompletionCallback);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
private IOnErrorListenerCallback_0_8.Stub mOnErrorCallback = null;
private void setOnErrorCallback(IPlayMedia_0_8 iface) {
try {
if (this.mOnErrorCallback == null) {
this.mOnErrorCallback = new IOnErrorListenerCallback_0_8.Stub() {
public boolean onError(int what, int extra) throws RemoteException {
owningMediaPlayer.lock.lock();
try {
if (owningMediaPlayer.onErrorListener != null) {
return owningMediaPlayer.onErrorListener.onError(owningMediaPlayer, what, extra);
}
return false;
}
finally {
owningMediaPlayer.lock.unlock();
}
}
};
}
iface.registerOnErrorCallback(
ServiceBackedMediaPlayer.this.sessionId,
this.mOnErrorCallback);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
private IOnInfoListenerCallback_0_8.Stub mOnInfoCallback = null;
private void setOnInfoCallback(IPlayMedia_0_8 iface) {
try {
if (this.mOnInfoCallback == null) {
this.mOnInfoCallback = new IOnInfoListenerCallback_0_8.Stub() {
public boolean onInfo(int what, int extra) throws RemoteException {
owningMediaPlayer.lock.lock();
try {
if ((owningMediaPlayer.onInfoListener != null)
&& (owningMediaPlayer.mpi == ServiceBackedMediaPlayer.this)) {
return owningMediaPlayer.onInfoListener.onInfo(owningMediaPlayer, what, extra);
}
}
finally {
owningMediaPlayer.lock.unlock();
}
return false;
}
};
}
iface.registerOnInfoCallback(
ServiceBackedMediaPlayer.this.sessionId,
this.mOnInfoCallback);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
private IOnPitchAdjustmentAvailableChangedListenerCallback_0_8.Stub mOnPitchAdjustmentAvailableChangedCallback = null;
private void setOnPitchAdjustmentAvailableChangedListener(IPlayMedia_0_8 iface) {
try {
if (this.mOnPitchAdjustmentAvailableChangedCallback == null) {
this.mOnPitchAdjustmentAvailableChangedCallback = new IOnPitchAdjustmentAvailableChangedListenerCallback_0_8.Stub() {
public void onPitchAdjustmentAvailableChanged(
boolean pitchAdjustmentAvailable)
throws RemoteException {
owningMediaPlayer.lock.lock();
try {
if (owningMediaPlayer.onPitchAdjustmentAvailableChangedListener != null) {
owningMediaPlayer.onPitchAdjustmentAvailableChangedListener.onPitchAdjustmentAvailableChanged(owningMediaPlayer, pitchAdjustmentAvailable);
}
}
finally {
owningMediaPlayer.lock.unlock();
}
}
};
}
iface.registerOnPitchAdjustmentAvailableChangedCallback(
ServiceBackedMediaPlayer.this.sessionId,
this.mOnPitchAdjustmentAvailableChangedCallback);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
private IOnPreparedListenerCallback_0_8.Stub mOnPreparedCallback = null;
private void setOnPreparedCallback(IPlayMedia_0_8 iface) {
try {
if (this.mOnPreparedCallback == null) {
this.mOnPreparedCallback = new IOnPreparedListenerCallback_0_8.Stub() {
public void onPrepared() throws RemoteException {
owningMediaPlayer.lock.lock();
Log.d(SBMP_TAG, "setOnPreparedCallback.mOnPreparedCallback.onPrepared 1050");
try {
Log.d(SBMP_TAG, "owningMediaPlayer.onPreparedListener is " + ((owningMediaPlayer.onPreparedListener == null) ? "null" : "non-null"));
Log.d(SBMP_TAG, "owningMediaPlayer.mpi is " + ((owningMediaPlayer.mpi == ServiceBackedMediaPlayer.this) ? "this" : "not this"));
ServiceBackedMediaPlayer.this.lockMuteOnPreparedCount.lock();
try {
if (ServiceBackedMediaPlayer.this.muteOnPreparedCount > 0) {
ServiceBackedMediaPlayer.this.muteOnPreparedCount--;
}
else {
ServiceBackedMediaPlayer.this.muteOnPreparedCount = 0;
if (ServiceBackedMediaPlayer.this.owningMediaPlayer.onPreparedListener != null) {
owningMediaPlayer.onPreparedListener.onPrepared(owningMediaPlayer);
}
}
}
finally {
ServiceBackedMediaPlayer.this.lockMuteOnPreparedCount.unlock();
}
}
finally {
owningMediaPlayer.lock.unlock();
}
}
};
}
iface.registerOnPreparedCallback(
ServiceBackedMediaPlayer.this.sessionId,
this.mOnPreparedCallback);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
private IOnSeekCompleteListenerCallback_0_8.Stub mOnSeekCompleteCallback = null;
private void setOnSeekCompleteCallback(IPlayMedia_0_8 iface) {
try {
if (this.mOnSeekCompleteCallback == null) {
this.mOnSeekCompleteCallback = new IOnSeekCompleteListenerCallback_0_8.Stub() {
public void onSeekComplete() throws RemoteException {
Log.d(SBMP_TAG, "onSeekComplete() 941");
owningMediaPlayer.lock.lock();
try {
if (ServiceBackedMediaPlayer.this.muteOnSeekCount > 0) {
Log.d(SBMP_TAG, "The next " + ServiceBackedMediaPlayer.this.muteOnSeekCount + " seek events are muted (counting this one)");
ServiceBackedMediaPlayer.this.muteOnSeekCount--;
}
else {
ServiceBackedMediaPlayer.this.muteOnSeekCount = 0;
Log.d(SBMP_TAG, "Attempting to invoke next seek event");
if (ServiceBackedMediaPlayer.this.owningMediaPlayer.onSeekCompleteListener != null) {
Log.d(SBMP_TAG, "Invoking onSeekComplete");
owningMediaPlayer.onSeekCompleteListener.onSeekComplete(owningMediaPlayer);
}
}
}
finally {
owningMediaPlayer.lock.unlock();
}
}
};
}
iface.registerOnSeekCompleteCallback(
ServiceBackedMediaPlayer.this.sessionId,
this.mOnSeekCompleteCallback);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
private IOnSpeedAdjustmentAvailableChangedListenerCallback_0_8.Stub mOnSpeedAdjustmentAvailableChangedCallback = null;
private void setOnSpeedAdjustmentAvailableChangedCallback(IPlayMedia_0_8 iface) {
try {
Log.d(SBMP_TAG, "Setting the service of on speed adjustment available changed");
if (this.mOnSpeedAdjustmentAvailableChangedCallback == null) {
this.mOnSpeedAdjustmentAvailableChangedCallback = new IOnSpeedAdjustmentAvailableChangedListenerCallback_0_8.Stub() {
public void onSpeedAdjustmentAvailableChanged(
boolean speedAdjustmentAvailable)
throws RemoteException {
owningMediaPlayer.lock.lock();
try {
if (owningMediaPlayer.onSpeedAdjustmentAvailableChangedListener != null) {
owningMediaPlayer.onSpeedAdjustmentAvailableChangedListener.onSpeedAdjustmentAvailableChanged(owningMediaPlayer, speedAdjustmentAvailable);
}
}
finally {
owningMediaPlayer.lock.unlock();
}
}
};
}
iface.registerOnSpeedAdjustmentAvailableChangedCallback(
ServiceBackedMediaPlayer.this.sessionId,
this.mOnSpeedAdjustmentAvailableChangedCallback);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
/**
* Functions identically to android.media.MediaPlayer.start()
* Starts a track playing
*/
@Override
public void start() {
Log.d(SBMP_TAG, "start()");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
try {
pmInterface.start(ServiceBackedMediaPlayer.this.sessionId);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
/**
* Functions identically to android.media.MediaPlayer.stop()
* Stops a track playing and resets its position to the start.
*/
@Override
public void stop() {
Log.d(SBMP_TAG, "stop()");
if (pmInterface == null) {
if (!ConnectPlayMediaService()) {
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
try {
pmInterface.stop(ServiceBackedMediaPlayer.this.sessionId);
} catch (RemoteException e) {
e.printStackTrace();
ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
}
}