diff options
Diffstat (limited to 'core/java/android/webkit/HTML5Audio.java')
-rw-r--r-- | core/java/android/webkit/HTML5Audio.java | 358 |
1 files changed, 0 insertions, 358 deletions
diff --git a/core/java/android/webkit/HTML5Audio.java b/core/java/android/webkit/HTML5Audio.java deleted file mode 100644 index 17eb2df..0000000 --- a/core/java/android/webkit/HTML5Audio.java +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * 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 android.webkit; - -import android.content.Context; -import android.media.AudioManager; -import android.media.MediaPlayer; -import android.net.Uri; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.util.Log; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; - -/** - * HTML5 support class for Audio. - * - * This class runs almost entirely on the WebCore thread. The exception is when - * accessing the WebView object to determine whether private browsing is - * enabled. - */ -class HTML5Audio extends Handler - implements MediaPlayer.OnBufferingUpdateListener, - MediaPlayer.OnCompletionListener, - MediaPlayer.OnErrorListener, - MediaPlayer.OnPreparedListener, - MediaPlayer.OnSeekCompleteListener, - AudioManager.OnAudioFocusChangeListener { - // Logging tag. - private static final String LOGTAG = "HTML5Audio"; - - private MediaPlayer mMediaPlayer; - - // The C++ MediaPlayerPrivateAndroid object. - private int mNativePointer; - // The private status of the view that created this player - private IsPrivateBrowsingEnabledGetter mIsPrivateBrowsingEnabledGetter; - - private static int IDLE = 0; - private static int INITIALIZED = 1; - private static int PREPARED = 2; - private static int STARTED = 4; - private static int COMPLETE = 5; - private static int PAUSED = 6; - private static int PAUSED_TRANSITORILY = 7; - private static int STOPPED = -2; - private static int ERROR = -1; - - private int mState = IDLE; - - private String mUrl; - private boolean mAskToPlay = false; - private boolean mLoopEnabled = false; - private boolean mProcessingOnEnd = false; - private Context mContext; - - // Timer thread -> UI thread - private static final int TIMEUPDATE = 100; - - private static final String COOKIE = "Cookie"; - private static final String HIDE_URL_LOGS = "x-hide-urls-from-log"; - - // The spec says the timer should fire every 250 ms or less. - private static final int TIMEUPDATE_PERIOD = 250; // ms - // The timer for timeupate events. - // See http://www.whatwg.org/specs/web-apps/current-work/#event-media-timeupdate - private Timer mTimer; - private final class TimeupdateTask extends TimerTask { - @Override - public void run() { - HTML5Audio.this.obtainMessage(TIMEUPDATE).sendToTarget(); - } - } - - // Helper class to determine whether private browsing is enabled in the - // given WebView. Queries the WebView on the UI thread. Calls to get() - // block until the data is available. - private class IsPrivateBrowsingEnabledGetter { - private boolean mIsReady; - private boolean mIsPrivateBrowsingEnabled; - IsPrivateBrowsingEnabledGetter(Looper uiThreadLooper, final WebViewClassic webView) { - new Handler(uiThreadLooper).post(new Runnable() { - @Override - public void run() { - synchronized(IsPrivateBrowsingEnabledGetter.this) { - mIsPrivateBrowsingEnabled = webView.isPrivateBrowsingEnabled(); - mIsReady = true; - IsPrivateBrowsingEnabledGetter.this.notify(); - } - } - }); - } - synchronized boolean get() { - while (!mIsReady) { - try { - wait(); - } catch (InterruptedException e) { - } - } - return mIsPrivateBrowsingEnabled; - } - }; - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case TIMEUPDATE: { - try { - if (mState != ERROR && mMediaPlayer.isPlaying()) { - int position = mMediaPlayer.getCurrentPosition(); - nativeOnTimeupdate(position, mNativePointer); - } - } catch (IllegalStateException e) { - mState = ERROR; - } - } - } - } - - // event listeners for MediaPlayer - // Those are called from the same thread we created the MediaPlayer - // (i.e. the webviewcore thread here) - - // MediaPlayer.OnBufferingUpdateListener - @Override - public void onBufferingUpdate(MediaPlayer mp, int percent) { - nativeOnBuffering(percent, mNativePointer); - } - - // MediaPlayer.OnCompletionListener; - @Override - public void onCompletion(MediaPlayer mp) { - mState = COMPLETE; - mProcessingOnEnd = true; - nativeOnEnded(mNativePointer); - mProcessingOnEnd = false; - if (mLoopEnabled == true) { - nativeOnRequestPlay(mNativePointer); - mLoopEnabled = false; - } - } - - // MediaPlayer.OnErrorListener - @Override - public boolean onError(MediaPlayer mp, int what, int extra) { - mState = ERROR; - resetMediaPlayer(); - mState = IDLE; - return false; - } - - // MediaPlayer.OnPreparedListener - @Override - public void onPrepared(MediaPlayer mp) { - mState = PREPARED; - if (mTimer != null) { - mTimer.schedule(new TimeupdateTask(), - TIMEUPDATE_PERIOD, TIMEUPDATE_PERIOD); - } - nativeOnPrepared(mp.getDuration(), 0, 0, mNativePointer); - if (mAskToPlay) { - mAskToPlay = false; - play(); - } - } - - // MediaPlayer.OnSeekCompleteListener - @Override - public void onSeekComplete(MediaPlayer mp) { - nativeOnTimeupdate(mp.getCurrentPosition(), mNativePointer); - } - - - /** - * @param nativePtr is the C++ pointer to the MediaPlayerPrivate object. - */ - public HTML5Audio(WebViewCore webViewCore, int nativePtr) { - // Save the native ptr - mNativePointer = nativePtr; - resetMediaPlayer(); - mContext = webViewCore.getContext(); - mIsPrivateBrowsingEnabledGetter = new IsPrivateBrowsingEnabledGetter( - webViewCore.getContext().getMainLooper(), webViewCore.getWebViewClassic()); - } - - private void resetMediaPlayer() { - if (mMediaPlayer == null) { - mMediaPlayer = new MediaPlayer(); - } else { - mMediaPlayer.reset(); - } - mMediaPlayer.setOnBufferingUpdateListener(this); - mMediaPlayer.setOnCompletionListener(this); - mMediaPlayer.setOnErrorListener(this); - mMediaPlayer.setOnPreparedListener(this); - mMediaPlayer.setOnSeekCompleteListener(this); - - if (mTimer != null) { - mTimer.cancel(); - } - mTimer = new Timer(); - mState = IDLE; - } - - private void setDataSource(String url) { - mUrl = url; - try { - if (mState != IDLE) { - resetMediaPlayer(); - } - String cookieValue = CookieManager.getInstance().getCookie( - url, mIsPrivateBrowsingEnabledGetter.get()); - Map<String, String> headers = new HashMap<String, String>(); - - if (cookieValue != null) { - headers.put(COOKIE, cookieValue); - } - if (mIsPrivateBrowsingEnabledGetter.get()) { - headers.put(HIDE_URL_LOGS, "true"); - } - - mMediaPlayer.setDataSource(mContext, Uri.parse(url), headers); - mState = INITIALIZED; - mMediaPlayer.prepareAsync(); - } catch (IOException e) { - String debugUrl = url.length() > 128 ? url.substring(0, 128) + "..." : url; - Log.e(LOGTAG, "couldn't load the resource: "+ debugUrl +" exc: " + e); - resetMediaPlayer(); - } - } - - @Override - public void onAudioFocusChange(int focusChange) { - switch (focusChange) { - case AudioManager.AUDIOFOCUS_GAIN: - // resume playback - if (mMediaPlayer == null) { - resetMediaPlayer(); - } else if (mState == PAUSED_TRANSITORILY && !mMediaPlayer.isPlaying()) { - mMediaPlayer.start(); - mState = STARTED; - } - break; - - case AudioManager.AUDIOFOCUS_LOSS: - // Lost focus for an unbounded amount of time: stop playback. - if (mState != ERROR && mMediaPlayer.isPlaying()) { - mMediaPlayer.stop(); - mState = STOPPED; - } - break; - - case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: - case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: - // Lost focus for a short time, but we have to stop - // playback. - if (mState != ERROR && mMediaPlayer.isPlaying()) { - pause(PAUSED_TRANSITORILY); - } - break; - } - } - - - private void play() { - if (mState == COMPLETE && mLoopEnabled == true) { - // Play it again, Sam - mMediaPlayer.start(); - mState = STARTED; - return; - } - - if (((mState >= ERROR && mState < PREPARED)) && mUrl != null) { - resetMediaPlayer(); - setDataSource(mUrl); - mAskToPlay = true; - } - - if (mState >= PREPARED) { - AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); - int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, - AudioManager.AUDIOFOCUS_GAIN); - - if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { - mMediaPlayer.start(); - mState = STARTED; - } - } - } - - private void pause() { - pause(PAUSED); - } - - private void pause(int state) { - if (mState == STARTED) { - if (mTimer != null) { - mTimer.purge(); - } - mMediaPlayer.pause(); - mState = state; - } - } - - private void seek(int msec) { - if (mProcessingOnEnd == true && mState == COMPLETE && msec == 0) { - mLoopEnabled = true; - } - if (mState >= PREPARED) { - mMediaPlayer.seekTo(msec); - } - } - - /** - * Called only over JNI when WebKit is happy to - * destroy the media player. - */ - private void teardown() { - mMediaPlayer.release(); - mMediaPlayer = null; - mState = ERROR; - mNativePointer = 0; - } - - private float getMaxTimeSeekable() { - if (mState >= PREPARED) { - return mMediaPlayer.getDuration() / 1000.0f; - } else { - return 0; - } - } - - private native void nativeOnBuffering(int percent, int nativePointer); - private native void nativeOnEnded(int nativePointer); - private native void nativeOnRequestPlay(int nativePointer); - private native void nativeOnPrepared(int duration, int width, int height, int nativePointer); - private native void nativeOnTimeupdate(int position, int nativePointer); - -} |