107c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik/* 207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * Copyright (C) 2014 The Android Open Source Project 307c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * 407c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * Licensed under the Apache License, Version 2.0 (the "License"); 507c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * you may not use this file except in compliance with the License. 607c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * You may obtain a copy of the License at 707c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * 807c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * http://www.apache.org/licenses/LICENSE-2.0 907c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * 1007c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * Unless required by applicable law or agreed to in writing, software 1107c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * distributed under the License is distributed on an "AS IS" BASIS, 1207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1307c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * See the License for the specific language governing permissions and 1407c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * limitations under the License. 1507c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik */ 16bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikpackage com.android.onemedia.playback; 17bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 18bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport org.apache.http.Header; 19bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport org.apache.http.HttpResponse; 20bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport org.apache.http.client.methods.HttpGet; 21bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 22bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.content.Context; 23bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.media.AudioManager; 24bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.media.AudioManager.OnAudioFocusChangeListener; 25bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.media.MediaPlayer; 26bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.media.MediaPlayer.OnBufferingUpdateListener; 27bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.media.MediaPlayer.OnCompletionListener; 28bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.media.MediaPlayer.OnErrorListener; 29bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.media.MediaPlayer.OnPreparedListener; 30bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.net.Uri; 31bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.net.http.AndroidHttpClient; 32bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.os.AsyncTask; 33bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.os.Bundle; 34bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.os.Handler; 35bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.util.Log; 36bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport android.view.SurfaceHolder; 37bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 38bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport java.io.IOException; 39bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikimport java.util.Map; 40bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 41bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik/** 42bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * Helper class for wrapping a MediaPlayer and doing a lot of the default work 43bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * to play audio. This class is not currently thread safe and all calls to it 44bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * should be made on the same thread. 45bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik */ 46bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErikpublic class LocalRenderer extends Renderer implements OnPreparedListener, 47bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik OnBufferingUpdateListener, OnCompletionListener, OnErrorListener, 48bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik OnAudioFocusChangeListener { 49bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private static final String TAG = "MediaPlayerManager"; 501e55375c96cadb8ef7aa12008e2be754969e1294Joe Onorato private static final boolean DEBUG = false; 51bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private static long sDebugInstanceId = 0; 52bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 53bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private static final String[] SUPPORTED_FEATURES = { 54bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik FEATURE_SET_CONTENT, 55bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik FEATURE_SET_NEXT_CONTENT, 56bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik FEATURE_PLAY, 57bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik FEATURE_PAUSE, 58bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik FEATURE_NEXT, 59bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik FEATURE_PREVIOUS, 60bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik FEATURE_SEEK_TO, 61bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik FEATURE_STOP 62bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik }; 63bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 64bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik /** 65bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * These are the states where it is valid to call play directly on the 66bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * MediaPlayer. 67bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik */ 68bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private static final int CAN_PLAY = STATE_READY | STATE_PAUSED | STATE_ENDED; 69bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik /** 70bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * These are the states where we expect the MediaPlayer to be ready in the 71bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * future, so we can set a flag to start playing when it is. 72bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik */ 73bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private static final int CAN_READY_PLAY = STATE_INIT | STATE_PREPARING; 74bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik /** 75bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * The states when it is valid to call pause on the MediaPlayer. 76bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik */ 77bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private static final int CAN_PAUSE = STATE_PLAYING; 78bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik /** 79bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * The states where it is valid to call seek on the MediaPlayer. 80bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik */ 81bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private static final int CAN_SEEK = STATE_READY | STATE_PLAYING | STATE_PAUSED | STATE_ENDED; 82bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik /** 83bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * The states where we expect the MediaPlayer to be ready in the future and 84bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * can store a seek position to set later. 85bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik */ 86bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private static final int CAN_READY_SEEK = STATE_INIT | STATE_PREPARING; 87bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik /** 88bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * The states where it is valid to call stop on the MediaPlayer. 89bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik */ 90bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private static final int CAN_STOP = STATE_READY | STATE_PLAYING | STATE_PAUSED | STATE_ENDED; 91bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik /** 92bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * The states where it is valid to get the current play position and the 93bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * duration from the MediaPlayer. 94bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik */ 95bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private static final int CAN_GET_POSITION = STATE_READY | STATE_PLAYING | STATE_PAUSED; 96bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 97bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 98bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 99bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private class PlayerContent { 100bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public final String source; 101bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public final Map<String, String> headers; 102bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 103bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public PlayerContent(String source, Map<String, String> headers) { 104bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik this.source = source; 105bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik this.headers = headers; 106bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 107bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 108bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 109bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private class AsyncErrorRetriever extends AsyncTask<HttpGet, Void, Void> { 110bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private final long errorId; 111bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private boolean closeHttpClient; 112bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 113bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public AsyncErrorRetriever(long errorId) { 114bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik this.errorId = errorId; 115bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik closeHttpClient = false; 116bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 117bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 118bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public boolean cancelRequestLocked(boolean closeHttp) { 119bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik closeHttpClient = closeHttp; 120bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return this.cancel(false); 121bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 122bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 123bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 124bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik protected Void doInBackground(HttpGet[] params) { 125bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik synchronized (mErrorLock) { 126bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (isCancelled() || mHttpClient == null) { 127bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mErrorRetriever == this) { 128bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mErrorRetriever = null; 129bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 130bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return null; 131bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 132bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mSafeToCloseClient = false; 133bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 134bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik final PlaybackError error = new PlaybackError(); 135bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik try { 136bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik HttpResponse response = mHttpClient.execute(params[0]); 137bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik synchronized (mErrorLock) { 138bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mErrorId != errorId || mError == null) { 139bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // A new error has occurred, abort 140bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return null; 141bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 142bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik error.type = mError.type; 143bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik error.extra = mError.extra; 144bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik error.errorMessage = mError.errorMessage; 145bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 146bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik final int code = response.getStatusLine().getStatusCode(); 147bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (code >= 300) { 148bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik error.extra = code; 149bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 150bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik final Bundle errorExtras = new Bundle(); 151bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik Header[] headers = response.getAllHeaders(); 152bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (headers != null && headers.length > 0) { 153bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik for (Header header : headers) { 154bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik errorExtras.putString(header.getName(), header.getValue()); 155bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 156bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik error.errorExtras = errorExtras; 157bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 158bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } catch (IOException e) { 159bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik Log.e(TAG, "IOException requesting from server, unable to get more exact error"); 160bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } finally { 161bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik synchronized (mErrorLock) { 162bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mSafeToCloseClient = true; 163bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mErrorRetriever == this) { 164bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mErrorRetriever = null; 165bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 166bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (isCancelled()) { 167bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (closeHttpClient) { 168bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mHttpClient.close(); 169bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mHttpClient = null; 170bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 171bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return null; 172bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 173bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 174bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 175bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mHandler.post(new Runnable() { 176bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 177bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public void run() { 178bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik synchronized (mErrorLock) { 179bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mErrorId == errorId) { 180bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik setError(error.type, error.extra, error.errorExtras, null); 181bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 182bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 183bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 184bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik }); 185bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return null; 186bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 187bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 188bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 189bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private int mState = STATE_INIT; 190bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 191bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private AudioManager mAudioManager; 192bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private MediaPlayer mPlayer; 193bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private PlayerContent mContent; 194bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private MediaPlayer mNextPlayer; 195bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private PlayerContent mNextContent; 196bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private SurfaceHolder mHolder; 197bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private SurfaceHolder.Callback mHolderCB; 198bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private Context mContext; 199bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 200bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private Handler mHandler = new Handler(); 201bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 202bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private AndroidHttpClient mHttpClient = AndroidHttpClient.newInstance("TUQ"); 203bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // The ongoing error request thread if there is one. This should only be 204bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // modified while mErrorLock is held. 205bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private AsyncErrorRetriever mErrorRetriever; 206bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // This is set to false while a server request is being made to retrieve 207bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // the current error. It should only be set while mErrorLock is held. 208bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private boolean mSafeToCloseClient = true; 209bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private final Object mErrorLock = new Object(); 210bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // A tracking id for the current error. This should only be modified while 211bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // mErrorLock is held. 212bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private long mErrorId = 0; 213bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // The current error state of this player. This is cleared when the state 214bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // leaves an error state and set when it enters one. This should only be 215bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // modified when mErrorLock is held. 216bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private PlaybackError mError; 217bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 218bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private boolean mPlayOnReady; 219bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private int mSeekOnReady; 220bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private boolean mHasAudioFocus; 221bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private long mDebugId = sDebugInstanceId++; 222bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 223bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public LocalRenderer(Context context, Bundle params) { 224bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik super(context, params); 225bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mContext = context; 226bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 227bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 228bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 229bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 230bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik protected void initFeatures(Bundle params) { 231bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik for (String feature : SUPPORTED_FEATURES) { 232bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mFeatures.add(feature); 233bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 234bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 235bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 236bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik /** 237bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * Call this when completely finished with the MediaPlayerManager to have it 238bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * clean up. The instance may not be used again after this is called. 239bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik */ 240bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 241bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public void onDestroy() { 242bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik synchronized (mErrorLock) { 243bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (DEBUG) { 244bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik Log.d(TAG, "onDestroy, error retriever? " + mErrorRetriever + " safe to close? " 245bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik + mSafeToCloseClient + " client? " + mHttpClient); 246bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 247bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mErrorRetriever != null) { 248bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mErrorRetriever.cancelRequestLocked(true); 249bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mErrorRetriever = null; 250bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 251bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // Increment the error id to ensure no errors are sent after this 252bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // point. 253bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mErrorId++; 254bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mSafeToCloseClient) { 255bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mHttpClient.close(); 256bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mHttpClient = null; 257bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 258bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 259bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 260bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 261bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 262bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public void onPrepared(MediaPlayer player) { 263bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (!isCurrentPlayer(player)) { 264bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return; 265bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 266bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik setState(STATE_READY); 267bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (DEBUG) { 268bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik Log.d(TAG, mDebugId + ": Finished preparing, seekOnReady is " + mSeekOnReady); 269bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 270bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mSeekOnReady >= 0) { 271bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik onSeekTo(mSeekOnReady); 272bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mSeekOnReady = -1; 273bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 274bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mPlayOnReady) { 275bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik player.start(); 276bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik setState(STATE_PLAYING); 277bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 278bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 279bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 280bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 281bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public void onBufferingUpdate(MediaPlayer player, int percent) { 282bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (!isCurrentPlayer(player)) { 283bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return; 284bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 285bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik pushOnBufferingUpdate(percent); 286bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 287bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 288bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 289bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public void onCompletion(MediaPlayer player) { 290bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (!isCurrentPlayer(player)) { 291bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return; 292bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 293bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (DEBUG) { 294bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik Log.d(TAG, mDebugId + ": Completed item. Have next item? " + (mNextPlayer != null)); 295bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 296bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mNextPlayer != null) { 297bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mPlayer != null) { 298bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mPlayer.release(); 299bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 300bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mPlayer = mNextPlayer; 301bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mContent = mNextContent; 302bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mNextPlayer = null; 303bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mNextContent = null; 304bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik pushOnNextStarted(); 305bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return; 306bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 307bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik setState(STATE_ENDED); 308bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 309bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 310bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 311bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public boolean onError(MediaPlayer player, int what, int extra) { 312bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (!isCurrentPlayer(player)) { 313bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return false; 314bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 315bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (DEBUG) { 316bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik Log.d(TAG, mDebugId + ": Entered error state, what: " + what + " extra: " + extra); 317bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 318bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik synchronized (mErrorLock) { 319bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik ++mErrorId; 320bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mError = new PlaybackError(); 321bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mError.type = what; 322bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mError.extra = extra; 323bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 324bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 325bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (what == MediaPlayer.MEDIA_ERROR_UNKNOWN && extra == MediaPlayer.MEDIA_ERROR_IO 326bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik && mContent != null && mContent.source.startsWith("http")) { 327bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik HttpGet request = new HttpGet(mContent.source); 328bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mContent.headers != null) { 329bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik for (String key : mContent.headers.keySet()) { 330bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik request.addHeader(key, mContent.headers.get(key)); 331bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 332bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 333bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik synchronized (mErrorLock) { 334bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mErrorRetriever != null) { 335bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mErrorRetriever.cancelRequestLocked(false); 336bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 337bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mErrorRetriever = new AsyncErrorRetriever(mErrorId); 338bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mErrorRetriever.execute(request); 339bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 340bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } else { 341bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik setError(what, extra, null, null); 342bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 343bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return true; 344bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 345bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 346bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 347bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public void onAudioFocusChange(int focusChange) { 348bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // TODO figure out appropriate logic for handling focus loss at the TUQ 349bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // level. 350bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik switch (focusChange) { 351bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: 352bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: 353bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mState == STATE_PLAYING) { 354bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik onPause(); 355bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mPlayOnReady = true; 356bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 357bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mHasAudioFocus = false; 358bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik break; 359bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik case AudioManager.AUDIOFOCUS_LOSS: 360bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mState == STATE_PLAYING) { 361bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik onPause(); 362bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mPlayOnReady = false; 363bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 364bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik pushOnFocusLost(); 365bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mHasAudioFocus = false; 366bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik break; 367bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik case AudioManager.AUDIOFOCUS_GAIN: 368bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mHasAudioFocus = true; 369bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mPlayOnReady) { 370bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik onPlay(); 371bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 372bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik break; 373bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik default: 374bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik Log.d(TAG, "Unknown focus change event " + focusChange); 375bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik break; 376bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 377bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 378bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 379bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 380bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public void setContent(Bundle request) { 381bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik setContent(request, null); 382bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 383bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 384bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik /** 385bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * Prepares the player for the given playback request. If the holder is null 386bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * it is assumed this is an audio only source. If playOnReady is set to true 387bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * the media will begin playing as soon as it can. 38807c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * 38907c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * @see RequestUtils for the set of valid keys. 390bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik */ 391bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public void setContent(Bundle request, SurfaceHolder holder) { 392bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik String source = request.getString(RequestUtils.EXTRA_KEY_SOURCE); 393bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik Map<String, String> headers = null; // request.mHeaders; 394bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik boolean playOnReady = true; // request.mPlayOnReady; 395bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (DEBUG) { 396bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik Log.d(TAG, mDebugId + ": Settings new content. Have a player? " + (mPlayer != null) 397bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik + " have a next player? " + (mNextPlayer != null)); 398bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 399bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik cleanUpPlayer(); 400bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik setState(STATE_PREPARING); 401bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mPlayOnReady = playOnReady; 402bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mSeekOnReady = -1; 403bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik final MediaPlayer newPlayer = new MediaPlayer(); 404bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 405bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik requestAudioFocus(); 406bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 407bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mPlayer = newPlayer; 408bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mContent = new PlayerContent(source, headers); 409bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik try { 410bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (headers != null) { 411bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik Uri sourceUri = Uri.parse(source); 412bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik newPlayer.setDataSource(mContext, sourceUri, headers); 413bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } else { 414bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik newPlayer.setDataSource(source); 415bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 416bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } catch (Exception e) { 417bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik setError(Listener.ERROR_LOAD_FAILED, 0, null, e); 418bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return; 419bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 420bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (isHolderReady(holder, newPlayer)) { 421bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik preparePlayer(newPlayer, true); 422bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 423bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 424bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 425bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 426bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public void setNextContent(Bundle request) { 427bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik String source = request.getString(RequestUtils.EXTRA_KEY_SOURCE); 428bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik Map<String, String> headers = null; // request.mHeaders; 429bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 430bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // TODO support video 431bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 432bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (DEBUG) { 433bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik Log.d(TAG, mDebugId + ": Setting next content. Have player? " + (mPlayer != null) 434bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik + " have next player? " + (mNextPlayer != null)); 435bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 436bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 437bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mPlayer == null) { 438bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // The manager isn't being used to play anything, don't try to 439bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // set a next. 440bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return; 441bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 442bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mNextPlayer != null) { 443bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // Before setting up the new one clear out the old one and release 444bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // it to ensure it doesn't play. 445bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mPlayer.setNextMediaPlayer(null); 446bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mNextPlayer.release(); 447bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mNextPlayer = null; 448bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mNextContent = null; 449bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 450bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (source == null) { 451bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // If there's no new content we're done 452bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return; 453bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 454bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik final MediaPlayer newPlayer = new MediaPlayer(); 455bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 456bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik try { 457bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (headers != null) { 458bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik Uri sourceUri = Uri.parse(source); 459bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik newPlayer.setDataSource(mContext, sourceUri, headers); 460bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } else { 461bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik newPlayer.setDataSource(source); 462bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 463bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } catch (Exception e) { 464bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik newPlayer.release(); 465bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // Don't return an error until we get to this item in playback 466bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return; 467bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 468bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 469bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (preparePlayer(newPlayer, false)) { 470bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mPlayer.setNextMediaPlayer(newPlayer); 471bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mNextPlayer = newPlayer; 472bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mNextContent = new PlayerContent(source, headers); 473bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 474bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 475bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 476bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private void requestAudioFocus() { 477bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik int result = mAudioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, 478bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik AudioManager.AUDIOFOCUS_GAIN); 479bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mHasAudioFocus = result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED; 480bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 481bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 482bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik /** 483bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * Start the player if possible or queue it to play when ready. If the 484bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * player is in a state where it will never be ready returns false. 485bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * 486bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * @return true if the content was started or will be started later 487bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik */ 488bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 489bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public boolean onPlay() { 490bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik MediaPlayer player = mPlayer; 491bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (player != null && mState == STATE_PLAYING) { 492bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // already playing, just return 493bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return true; 494bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 495bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (!mHasAudioFocus) { 496bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik requestAudioFocus(); 497bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 498bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (player != null && canPlay()) { 499bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik player.start(); 500bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik setState(STATE_PLAYING); 501bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } else if (canReadyPlay()) { 502bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mPlayOnReady = true; 503bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } else if (!isPlaying()) { 504bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return false; 505bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 506bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return true; 507bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 508bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 509bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik /** 510bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * Pause the player if possible or set it to not play when ready. If the 511bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * player is in a state where it will never be ready returns false. 512bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * 513bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * @return true if the content was paused or will wait to play when ready 514bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * later 515bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik */ 516bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 517bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public boolean onPause() { 518bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik MediaPlayer player = mPlayer; 5198ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik // If the user paused us make sure we won't start playing again until 5208ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik // asked to 5218ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mPlayOnReady = false; 522bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (player != null && (mState & CAN_PAUSE) != 0) { 523bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik player.pause(); 524bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik setState(STATE_PAUSED); 525bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } else if (!isPaused()) { 526bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return false; 527bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 528bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return true; 529bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 530bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 531bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik /** 532bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * Seek to a given position in the media. If the seek succeeded or will be 533bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * performed when loading is complete returns true. If the position is not 534bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * in range or the player will never be ready returns false. 535bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * 536bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * @param position The position to seek to in milliseconds 537bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * @return true if playback was moved or will be moved when ready 538bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik */ 539bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 540bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public boolean onSeekTo(int position) { 541bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik MediaPlayer player = mPlayer; 542bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (player != null && (mState & CAN_SEEK) != 0) { 543bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (position < 0 || position >= getDuration()) { 544bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return false; 545bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } else { 546bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mState == STATE_ENDED) { 547bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik player.start(); 548bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik player.pause(); 549bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik setState(STATE_PAUSED); 550bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 551bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik player.seekTo(position); 552bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 553bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } else if ((mState & CAN_READY_SEEK) != 0) { 554bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mSeekOnReady = position; 555bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } else { 556bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return false; 557bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 558bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return true; 559bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 560bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 561bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik /** 562bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * Stop the player. It cannot be used again until 563bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * {@link #setContent(String, boolean)} is called. 564bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * 565bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * @return true if stopping the player succeeded 566bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik */ 567bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 568bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public boolean onStop() { 569bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik cleanUpPlayer(); 570bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik setState(STATE_STOPPED); 571bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return true; 572bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 573bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 574bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public boolean isPlaying() { 575bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return mState == STATE_PLAYING; 576bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 577bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 578bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public boolean isPaused() { 579bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return mState == STATE_PAUSED; 580bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 581bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 582bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 583bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public long getSeekPosition() { 584bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return ((mState & CAN_GET_POSITION) == 0) ? -1 : mPlayer.getCurrentPosition(); 585bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 586bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 587bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 588bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public long getDuration() { 589bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return ((mState & CAN_GET_POSITION) == 0) ? -1 : mPlayer.getDuration(); 590bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 591bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 592bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private boolean canPlay() { 593bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return ((mState & CAN_PLAY) != 0) && mHasAudioFocus; 594bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 595bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 596bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private boolean canReadyPlay() { 597bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return (mState & CAN_PLAY) != 0 || (mState & CAN_READY_PLAY) != 0; 598bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 599bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 600bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik /** 601bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * Sends a state update if the listener exists 602bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik */ 603bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private void setState(int state) { 604bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (state == mState) { 605bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return; 606bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 607bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik Log.d(TAG, "Entering state " + state + " from state " + mState); 608bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mState = state; 609bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (state != STATE_ERROR) { 610bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // Don't notify error here, it'll get sent via onError 611bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik pushOnStateChanged(state); 612bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 613bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 614bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 615bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private boolean preparePlayer(final MediaPlayer player, boolean current) { 616bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik player.setOnPreparedListener(this); 617bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik player.setOnBufferingUpdateListener(this); 618bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik player.setOnCompletionListener(this); 619bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik player.setOnErrorListener(this); 620bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik try { 621bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik player.prepareAsync(); 622bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (current) { 623bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik setState(STATE_PREPARING); 624bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 625bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } catch (IllegalStateException e) { 626bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (current) { 627bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik setError(Listener.ERROR_PREPARE_ERROR, 0, null, e); 628bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 629bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return false; 630bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 631bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return true; 632bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 633bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 634bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik /** 635bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * @param extra 636bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * @param e 637bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik */ 638bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private void setError(int type, int extra, Bundle extras, Exception e) { 639bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik setState(STATE_ERROR); 640bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik pushOnError(type, extra, extras, e); 641bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik cleanUpPlayer(); 642bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return; 643bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 644bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 645bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik /** 646bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * Checks if the holder is ready and either sets up a callback to wait for 647bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * it or sets it directly. If 648bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * 649bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * @param holder 650bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * @param player 651bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik * @return 652bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik */ 653bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private boolean isHolderReady(final SurfaceHolder holder, final MediaPlayer player) { 654bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mHolder = holder; 655bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (holder != null) { 656bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (holder.getSurface() != null && holder.getSurface().isValid()) { 657bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik player.setDisplay(holder); 658bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return true; 659bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } else { 660bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik Log.w(TAG, "Holder not null, waiting for it to be ready"); 661bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // If the holder isn't ready yet add a callback to set the 662bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // holder when it's ready. 663bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik SurfaceHolder.Callback cb = new SurfaceHolder.Callback() { 664bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 665bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public void surfaceDestroyed(SurfaceHolder arg0) { 666bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 667bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 668bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 669bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public void surfaceCreated(SurfaceHolder arg0) { 670bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (player.equals(mPlayer)) { 671bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik player.setDisplay(arg0); 672bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik preparePlayer(player, true); 673bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 674bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 675bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 676bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik @Override 677bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { 678bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 679bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik }; 680bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mHolderCB = cb; 681bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik holder.addCallback(cb); 682bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return false; 683bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 684bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 685bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return true; 686bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 687bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 688bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private void cleanUpPlayer() { 689bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (DEBUG) { 690bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik Log.d(TAG, mDebugId + ": Cleaning up current player"); 691bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 692bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik synchronized (mErrorLock) { 693bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mError = null; 694bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (mErrorRetriever != null) { 695bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mErrorRetriever.cancelRequestLocked(false); 696bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // Don't set to null as we may need to cancel again with true if 697bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik // the object gets destroyed. 698bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 699bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 700bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mAudioManager.abandonAudioFocus(this); 701bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 702bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik SurfaceHolder.Callback cb = mHolderCB; 703bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mHolderCB = null; 704bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik SurfaceHolder holder = mHolder; 705bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mHolder = null; 706bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (holder != null && cb != null) { 707bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik holder.removeCallback(cb); 708bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 709bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 710bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik MediaPlayer player = mPlayer; 711bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik mPlayer = null; 712bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik if (player != null) { 713bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik player.reset(); 714bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik player.release(); 715bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 716bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 717bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik 718bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik private boolean isCurrentPlayer(MediaPlayer player) { 719bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik return player.equals(mPlayer); 720bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik } 721bfa153b64b4e8c2faa39a15e87fc9f0300335f20RoboErik} 722