VideoView.java revision 29f5183794efd58a3442aedcf829e3dbcd3fd867
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.widget; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.AlertDialog; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.DialogInterface; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources; 24de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viveretteimport android.graphics.Canvas; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.media.AudioManager; 26af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnarimport android.media.MediaFormat; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.media.MediaPlayer; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.media.MediaPlayer.OnCompletionListener; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.media.MediaPlayer.OnErrorListener; 30a0ba79473b9067e315155718545103bb4f361873James Dongimport android.media.MediaPlayer.OnInfoListener; 31af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnarimport android.media.Metadata; 32484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnarimport android.media.SubtitleController; 33d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viveretteimport android.media.SubtitleTrack.RenderingWidget; 34484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnarimport android.media.WebVttRenderer; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri; 3629f5183794efd58a3442aedcf829e3dbcd3fd867Lajos Molnarimport android.os.Looper; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 39484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnarimport android.util.Pair; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.MotionEvent; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SurfaceHolder; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SurfaceView; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 458a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityEvent; 468a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo; 47a8381dfc5ee60dcf99dfd16a840f746cd7cb42abOwen Linimport android.widget.MediaController.MediaPlayerControl; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 50af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnarimport java.io.InputStream; 51256430093679e1d62b54fb0c852126e54d162f6fAndreas Huberimport java.util.Map; 52af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnarimport java.util.Vector; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Displays a video file. The VideoView class 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * can load images from various sources (such as resources or content 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * providers), takes care of computing its measurement from the video so that 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it can be used in any layout manager, and provides various display options 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * such as scaling and tinting. 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 61484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnarpublic class VideoView extends SurfaceView 62484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar implements MediaPlayerControl, SubtitleController.Anchor { 63b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project private String TAG = "VideoView"; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // settable by the client 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Uri mUri; 66256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber private Map<String, String> mHeaders; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 68fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong // all possible internal states 69fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong private static final int STATE_ERROR = -1; 70fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong private static final int STATE_IDLE = 0; 71fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong private static final int STATE_PREPARING = 1; 72fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong private static final int STATE_PREPARED = 2; 73fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong private static final int STATE_PLAYING = 3; 74fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong private static final int STATE_PAUSED = 4; 75fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong private static final int STATE_PLAYBACK_COMPLETED = 5; 76fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong 77fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong // mCurrentState is a VideoView object's current state. 78fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong // mTargetState is the state that a method caller intends to reach. 79fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong // For instance, regardless the VideoView object's current state, 80fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong // calling pause() intends to bring the object to a target state 81fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong // of STATE_PAUSED. 82fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong private int mCurrentState = STATE_IDLE; 83fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong private int mTargetState = STATE_IDLE; 84fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // All the stuff we need for playing and showing a video 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SurfaceHolder mSurfaceHolder = null; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private MediaPlayer mMediaPlayer = null; 8813bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen private int mAudioSession; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mVideoWidth; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mVideoHeight; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mSurfaceWidth; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mSurfaceHeight; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private MediaController mMediaController; 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private OnCompletionListener mOnCompletionListener; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private MediaPlayer.OnPreparedListener mOnPreparedListener; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mCurrentBufferPercentage; 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private OnErrorListener mOnErrorListener; 98a0ba79473b9067e315155718545103bb4f361873James Dong private OnInfoListener mOnInfoListener; 99fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong private int mSeekWhenPrepared; // recording the seek position while preparing 100c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen private boolean mCanPause; 101c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen private boolean mCanSeekBack; 102c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen private boolean mCanSeekForward; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 104d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette /** Subtitle rendering widget overlaid on top of the video. */ 105d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette private RenderingWidget mSubtitleWidget; 106de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette 107d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette /** Listener for changes to subtitle data, used to redraw when needed. */ 108d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette private RenderingWidget.OnChangedListener mSubtitlesChangedListener; 109de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public VideoView(Context context) { 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(context); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project initVideoView(); 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 114256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public VideoView(Context context, AttributeSet attrs) { 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, attrs, 0); 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project initVideoView(); 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 119256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public VideoView(Context context, AttributeSet attrs, int defStyle) { 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(context, attrs, defStyle); 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project initVideoView(); 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 1270b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen //Log.i("@@@@", "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", " 1280b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen // + MeasureSpec.toString(heightMeasureSpec) + ")"); 1290b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int width = getDefaultSize(mVideoWidth, widthMeasureSpec); 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int height = getDefaultSize(mVideoHeight, heightMeasureSpec); 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mVideoWidth > 0 && mVideoHeight > 0) { 1330b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen 1340b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); 1350b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); 1360b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); 1370b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); 1380b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen 1390b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen if (widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.EXACTLY) { 1400b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen // the size is fixed 1410b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen width = widthSpecSize; 1420b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen height = heightSpecSize; 1430b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen 1440b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen // for compatibility, we adjust size based on aspect ratio 1450b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen if ( mVideoWidth * height < width * mVideoHeight ) { 1460b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen //Log.i("@@@", "image too wide, correcting"); 1470b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen width = height * mVideoWidth / mVideoHeight; 1480b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen } else if ( mVideoWidth * height > width * mVideoHeight ) { 1490b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen //Log.i("@@@", "image too tall, correcting"); 1500b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen height = width * mVideoHeight / mVideoWidth; 1510b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen } 1520b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen } else if (widthSpecMode == MeasureSpec.EXACTLY) { 1530b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen // only the width is fixed, adjust the height to match aspect ratio if possible 1540b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen width = widthSpecSize; 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project height = width * mVideoHeight / mVideoWidth; 1560b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) { 1570b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen // couldn't match aspect ratio within the constraints 1580b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen height = heightSpecSize; 1590b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen } 1600b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen } else if (heightSpecMode == MeasureSpec.EXACTLY) { 1610b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen // only the height is fixed, adjust the width to match aspect ratio if possible 1620b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen height = heightSpecSize; 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project width = height * mVideoWidth / mVideoHeight; 1640b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) { 1650b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen // couldn't match aspect ratio within the constraints 1660b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen width = widthSpecSize; 1670b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen } 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1690b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen // neither the width nor the height are fixed, try to use actual video size 1700b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen width = mVideoWidth; 1710b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen height = mVideoHeight; 1720b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) { 1730b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen // too tall, decrease both width and height 1740b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen height = heightSpecSize; 1750b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen width = height * mVideoWidth / mVideoHeight; 1760b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen } 1770b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) { 1780b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen // too wide, decrease both width and height 1790b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen width = widthSpecSize; 1800b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen height = width * mVideoHeight / mVideoWidth; 1810b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen } 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1830b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen } else { 1840b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen // no size yet, just adopt the given spec sizes 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setMeasuredDimension(width, height); 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 188256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber 1898a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 1908a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 1918a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov super.onInitializeAccessibilityEvent(event); 1928a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov event.setClassName(VideoView.class.getName()); 1938a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 1948a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 1958a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 1968a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 1978a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov super.onInitializeAccessibilityNodeInfo(info); 1988a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov info.setClassName(VideoView.class.getName()); 1998a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 2008a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 201c1374e8e1ae6669ffda874445ebf6b14c49d3a9cMarco Nelissen public int resolveAdjustedSize(int desiredSize, int measureSpec) { 202c1374e8e1ae6669ffda874445ebf6b14c49d3a9cMarco Nelissen return getDefaultSize(desiredSize, measureSpec); 203c1374e8e1ae6669ffda874445ebf6b14c49d3a9cMarco Nelissen } 204c1374e8e1ae6669ffda874445ebf6b14c49d3a9cMarco Nelissen 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void initVideoView() { 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVideoWidth = 0; 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVideoHeight = 0; 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getHolder().addCallback(mSHCallback); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setFocusable(true); 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setFocusableInTouchMode(true); 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestFocus(); 213484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar mPendingSubtitleTracks = new Vector<Pair<InputStream, MediaFormat>>(); 214fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mCurrentState = STATE_IDLE; 215fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mTargetState = STATE_IDLE; 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setVideoPath(String path) { 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setVideoURI(Uri.parse(path)); 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setVideoURI(Uri uri) { 223256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber setVideoURI(uri, null); 224256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber } 225256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber 226256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber /** 227256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber * @hide 228256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber */ 229256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber public void setVideoURI(Uri uri, Map<String, String> headers) { 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUri = uri; 231256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber mHeaders = headers; 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSeekWhenPrepared = 0; 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project openVideo(); 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayout(); 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidate(); 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 237256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber 238af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar /** 239af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * Adds an external subtitle source file (from the provided input stream.) 240af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * 241af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * Note that a single external subtitle source may contain multiple or no 242af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * supported tracks in it. If the source contained at least one track in 243af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * it, one will receive an {@link MediaPlayer#MEDIA_INFO_METADATA_UPDATE} 244af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * info message. Otherwise, if reading the source takes excessive time, 245af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * one will receive a {@link MediaPlayer#MEDIA_INFO_SUBTITLE_TIMED_OUT} 246af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * message. If the source contained no supported track (including an empty 247af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * source file or null input stream), one will receive a {@link 248af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * MediaPlayer#MEDIA_INFO_UNSUPPORTED_SUBTITLE} message. One can find the 249af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * total number of available tracks using {@link MediaPlayer#getTrackInfo()} 250af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * to see what additional tracks become available after this method call. 251af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * 252af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * @param is input stream containing the subtitle data. It will be 253af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * closed by the media framework. 254af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * @param format the format of the subtitle track(s). Must contain at least 255af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * the mime type ({@link MediaFormat#KEY_MIME}) and the 256af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * language ({@link MediaFormat#KEY_LANGUAGE}) of the file. 257af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * If the file itself contains the language information, 258af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar * specify "und" for the language. 259af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar */ 260af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar public void addSubtitleSource(InputStream is, MediaFormat format) { 261af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar if (mMediaPlayer == null) { 262484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar mPendingSubtitleTracks.add(Pair.create(is, format)); 263af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar } else { 264484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar try { 265484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar mMediaPlayer.addSubtitleSource(is, format); 266484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar } catch (IllegalStateException e) { 267484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar mInfoListener.onInfo( 268484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar mMediaPlayer, MediaPlayer.MEDIA_INFO_UNSUPPORTED_SUBTITLE, 0); 269484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar } 270af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar } 271af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar } 272af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar 273484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar private Vector<Pair<InputStream, MediaFormat>> mPendingSubtitleTracks; 274af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void stopPlayback() { 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMediaPlayer != null) { 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaPlayer.stop(); 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaPlayer.release(); 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaPlayer = null; 280fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mCurrentState = STATE_IDLE; 281fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mTargetState = STATE_IDLE; 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void openVideo() { 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mUri == null || mSurfaceHolder == null) { 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // not ready for playback just yet, will try again later 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 290256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber // Tell the music playback service to pause 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: these constants need to be published somewhere in the framework. 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent i = new Intent("com.android.music.musicservicecommand"); 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i.putExtra("command", "pause"); 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(i); 295fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong 296dddeee6f350673b691b1b9001545a27f9c3d19f0Marco Nelissen // we shouldn't clear the target state, because somebody might have 297dddeee6f350673b691b1b9001545a27f9c3d19f0Marco Nelissen // called start() previously 298dddeee6f350673b691b1b9001545a27f9c3d19f0Marco Nelissen release(false); 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaPlayer = new MediaPlayer(); 301484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar // TODO: create SubtitleController in MediaPlayer, but we need 302484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar // a context for the subtitle renderers 303d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette final Context context = getContext(); 304d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette final SubtitleController controller = new SubtitleController( 305d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette context, mMediaPlayer.getMediaTimeProvider(), mMediaPlayer); 306d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette controller.registerRenderer(new WebVttRenderer(context)); 307484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar mMediaPlayer.setSubtitleAnchor(controller, this); 308484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar 30913bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen if (mAudioSession != 0) { 31013bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen mMediaPlayer.setAudioSessionId(mAudioSession); 31113bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen } else { 31213bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen mAudioSession = mMediaPlayer.getAudioSessionId(); 31313bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen } 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaPlayer.setOnPreparedListener(mPreparedListener); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener); 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaPlayer.setOnCompletionListener(mCompletionListener); 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaPlayer.setOnErrorListener(mErrorListener); 318af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar mMediaPlayer.setOnInfoListener(mInfoListener); 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener); 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCurrentBufferPercentage = 0; 321256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber mMediaPlayer.setDataSource(mContext, mUri, mHeaders); 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaPlayer.setDisplay(mSurfaceHolder); 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaPlayer.setScreenOnWhilePlaying(true); 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaPlayer.prepareAsync(); 326af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar 327484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar for (Pair<InputStream, MediaFormat> pending: mPendingSubtitleTracks) { 328484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar try { 329484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar mMediaPlayer.addSubtitleSource(pending.first, pending.second); 330484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar } catch (IllegalStateException e) { 331484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar mInfoListener.onInfo( 332484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar mMediaPlayer, MediaPlayer.MEDIA_INFO_UNSUPPORTED_SUBTITLE, 0); 333484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar } 334af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar } 335af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar 336dddeee6f350673b691b1b9001545a27f9c3d19f0Marco Nelissen // we don't set the target state here either, but preserve the 337dddeee6f350673b691b1b9001545a27f9c3d19f0Marco Nelissen // target state that was there before. 338fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mCurrentState = STATE_PREPARING; 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project attachMediaController(); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException ex) { 341b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project Log.w(TAG, "Unable to open content: " + mUri, ex); 342fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mCurrentState = STATE_ERROR; 343fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mTargetState = STATE_ERROR; 344020d2e3453b98ae435c4c21b849a2fe0a8842be7Andrei Popescu mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalArgumentException ex) { 347b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project Log.w(TAG, "Unable to open content: " + mUri, ex); 348fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mCurrentState = STATE_ERROR; 349fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mTargetState = STATE_ERROR; 350020d2e3453b98ae435c4c21b849a2fe0a8842be7Andrei Popescu mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 352af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar } finally { 353484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar mPendingSubtitleTracks.clear(); 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 356256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setMediaController(MediaController controller) { 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMediaController != null) { 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaController.hide(); 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaController = controller; 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project attachMediaController(); 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void attachMediaController() { 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMediaPlayer != null && mMediaController != null) { 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaController.setMediaPlayer(this); 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View anchorView = this.getParent() instanceof View ? 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (View)this.getParent() : this; 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaController.setAnchorView(anchorView); 371fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mMediaController.setEnabled(isInPlaybackState()); 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 374256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaPlayer.OnVideoSizeChangedListener mSizeChangedListener = 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new MediaPlayer.OnVideoSizeChangedListener() { 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVideoWidth = mp.getVideoWidth(); 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVideoHeight = mp.getVideoHeight(); 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mVideoWidth != 0 && mVideoHeight != 0) { 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getHolder().setFixedSize(mVideoWidth, mVideoHeight); 382f5d102ed769ba33cbd48e58c209ece3f1014fe61Teng-Hui Zhu requestLayout(); 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 386256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() { 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onPrepared(MediaPlayer mp) { 389fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mCurrentState = STATE_PREPARED; 390c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen 391c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen // Get the capabilities of the player for this stream 392c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen Metadata data = mp.getMetadata(MediaPlayer.METADATA_ALL, 393c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen MediaPlayer.BYPASS_METADATA_FILTER); 394d44d33b01a2125cfa40153e8399dd39908005004Andreas Huber 395d44d33b01a2125cfa40153e8399dd39908005004Andreas Huber if (data != null) { 396d44d33b01a2125cfa40153e8399dd39908005004Andreas Huber mCanPause = !data.has(Metadata.PAUSE_AVAILABLE) 397d44d33b01a2125cfa40153e8399dd39908005004Andreas Huber || data.getBoolean(Metadata.PAUSE_AVAILABLE); 398d44d33b01a2125cfa40153e8399dd39908005004Andreas Huber mCanSeekBack = !data.has(Metadata.SEEK_BACKWARD_AVAILABLE) 399d44d33b01a2125cfa40153e8399dd39908005004Andreas Huber || data.getBoolean(Metadata.SEEK_BACKWARD_AVAILABLE); 400d44d33b01a2125cfa40153e8399dd39908005004Andreas Huber mCanSeekForward = !data.has(Metadata.SEEK_FORWARD_AVAILABLE) 401d44d33b01a2125cfa40153e8399dd39908005004Andreas Huber || data.getBoolean(Metadata.SEEK_FORWARD_AVAILABLE); 402d44d33b01a2125cfa40153e8399dd39908005004Andreas Huber } else { 4032869e952c65548555a9fc197c1f8ceb5b7470462Andreas Huber mCanPause = mCanSeekBack = mCanSeekForward = true; 404d44d33b01a2125cfa40153e8399dd39908005004Andreas Huber } 405c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOnPreparedListener != null) { 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnPreparedListener.onPrepared(mMediaPlayer); 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMediaController != null) { 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaController.setEnabled(true); 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVideoWidth = mp.getVideoWidth(); 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVideoHeight = mp.getVideoHeight(); 414c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen 415fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong int seekToPosition = mSeekWhenPrepared; // mSeekWhenPrepared may be changed after seekTo() call 416fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong if (seekToPosition != 0) { 417fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong seekTo(seekToPosition); 418fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong } 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mVideoWidth != 0 && mVideoHeight != 0) { 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //Log.i("@@@@", "video size: " + mVideoWidth +"/"+ mVideoHeight); 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getHolder().setFixedSize(mVideoWidth, mVideoHeight); 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSurfaceWidth == mVideoWidth && mSurfaceHeight == mVideoHeight) { 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We didn't actually change the size (it was already at the size 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we need), so we won't get a "surface changed" callback, so 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // start the video here instead of in the callback. 426fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong if (mTargetState == STATE_PLAYING) { 427aa00e390c191f9b4eaee8ecade88c74571b2b3f3James Dong start(); 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMediaController != null) { 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaController.show(); 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!isPlaying() && 432fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong (seekToPosition != 0 || getCurrentPosition() > 0)) { 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMediaController != null) { 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Show the media controls when we're paused into a video and make 'em stick. 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaController.show(0); 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We don't know the video size yet, but should start anyway. 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The video size might be reported to us later. 442fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong if (mTargetState == STATE_PLAYING) { 443aa00e390c191f9b4eaee8ecade88c74571b2b3f3James Dong start(); 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private MediaPlayer.OnCompletionListener mCompletionListener = 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new MediaPlayer.OnCompletionListener() { 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onCompletion(MediaPlayer mp) { 452fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mCurrentState = STATE_PLAYBACK_COMPLETED; 453fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mTargetState = STATE_PLAYBACK_COMPLETED; 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMediaController != null) { 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaController.hide(); 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOnCompletionListener != null) { 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnCompletionListener.onCompletion(mMediaPlayer); 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 463af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar private MediaPlayer.OnInfoListener mInfoListener = 464af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar new MediaPlayer.OnInfoListener() { 465af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar public boolean onInfo(MediaPlayer mp, int arg1, int arg2) { 466af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar if (mOnInfoListener != null) { 467af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar mOnInfoListener.onInfo(mp, arg1, arg2); 468af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar } 469af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar return true; 470af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar } 471af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar }; 472af309824350d6b2fd38e19ef9104211e5ba132e8Lajos Molnar 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private MediaPlayer.OnErrorListener mErrorListener = 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new MediaPlayer.OnErrorListener() { 475c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public boolean onError(MediaPlayer mp, int framework_err, int impl_err) { 476c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project Log.d(TAG, "Error: " + framework_err + "," + impl_err); 477fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mCurrentState = STATE_ERROR; 478fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mTargetState = STATE_ERROR; 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMediaController != null) { 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaController.hide(); 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* If an error handler has been supplied, use it and finish. */ 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOnErrorListener != null) { 485c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (mOnErrorListener.onError(mMediaPlayer, framework_err, impl_err)) { 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Otherwise, pop up an error dialog so the user knows that 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * something bad has happened. Only try and pop up the dialog 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if we're attached to a window. When we're going away and no 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * longer have a window, don't bother showing the user an error. 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getWindowToken() != null) { 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Resources r = mContext.getResources(); 497c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project int messageId; 498c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 499c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (framework_err == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) { 500c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project messageId = com.android.internal.R.string.VideoView_error_text_invalid_progressive_playback; 501c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else { 502c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project messageId = com.android.internal.R.string.VideoView_error_text_unknown; 503c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 504c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new AlertDialog.Builder(mContext) 506c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project .setMessage(messageId) 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .setPositiveButton(com.android.internal.R.string.VideoView_error_button, 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new DialogInterface.OnClickListener() { 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onClick(DialogInterface dialog, int whichButton) { 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* If we get here, there is no onError listener, so 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * at least inform them that the video is over. 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOnCompletionListener != null) { 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnCompletionListener.onCompletion(mMediaPlayer); 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }) 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .setCancelable(false) 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .show(); 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener = 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new MediaPlayer.OnBufferingUpdateListener() { 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onBufferingUpdate(MediaPlayer mp, int percent) { 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCurrentBufferPercentage = percent; 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Register a callback to be invoked when the media file 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is loaded and ready to go. 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param l The callback that will be run 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setOnPreparedListener(MediaPlayer.OnPreparedListener l) 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnPreparedListener = l; 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Register a callback to be invoked when the end of a media file 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * has been reached during playback. 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param l The callback that will be run 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setOnCompletionListener(OnCompletionListener l) 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnCompletionListener = l; 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Register a callback to be invoked when an error occurs 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * during playback or setup. If no listener is specified, 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or if the listener returned false, VideoView will inform 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the user of any errors. 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param l The callback that will be run 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setOnErrorListener(OnErrorListener l) 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnErrorListener = l; 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 567a0ba79473b9067e315155718545103bb4f361873James Dong /** 568a0ba79473b9067e315155718545103bb4f361873James Dong * Register a callback to be invoked when an informational event 569a0ba79473b9067e315155718545103bb4f361873James Dong * occurs during playback or setup. 570a0ba79473b9067e315155718545103bb4f361873James Dong * 571a0ba79473b9067e315155718545103bb4f361873James Dong * @param l The callback that will be run 572a0ba79473b9067e315155718545103bb4f361873James Dong */ 573a0ba79473b9067e315155718545103bb4f361873James Dong public void setOnInfoListener(OnInfoListener l) { 574a0ba79473b9067e315155718545103bb4f361873James Dong mOnInfoListener = l; 575a0ba79473b9067e315155718545103bb4f361873James Dong } 576a0ba79473b9067e315155718545103bb4f361873James Dong 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback() 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceChanged(SurfaceHolder holder, int format, 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int w, int h) 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSurfaceWidth = w; 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSurfaceHeight = h; 584fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong boolean isValidState = (mTargetState == STATE_PLAYING); 585fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong boolean hasValidSize = (mVideoWidth == w && mVideoHeight == h); 586fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong if (mMediaPlayer != null && isValidState && hasValidSize) { 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSeekWhenPrepared != 0) { 588fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong seekTo(mSeekWhenPrepared); 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 590fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong start(); 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceCreated(SurfaceHolder holder) 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSurfaceHolder = holder; 59769b8d69aadbf0e795f1a1e1adc82c78cf0b9959fAndreas Huber openVideo(); 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void surfaceDestroyed(SurfaceHolder holder) 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // after we return from this we can't use the surface any more 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSurfaceHolder = null; 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMediaController != null) mMediaController.hide(); 60569b8d69aadbf0e795f1a1e1adc82c78cf0b9959fAndreas Huber release(true); 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 609fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong /* 610fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong * release the media player in any state 611fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong */ 612dddeee6f350673b691b1b9001545a27f9c3d19f0Marco Nelissen private void release(boolean cleartargetstate) { 613fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong if (mMediaPlayer != null) { 614fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mMediaPlayer.reset(); 615fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mMediaPlayer.release(); 616fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mMediaPlayer = null; 617484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar mPendingSubtitleTracks.clear(); 618fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mCurrentState = STATE_IDLE; 619dddeee6f350673b691b1b9001545a27f9c3d19f0Marco Nelissen if (cleartargetstate) { 620dddeee6f350673b691b1b9001545a27f9c3d19f0Marco Nelissen mTargetState = STATE_IDLE; 621dddeee6f350673b691b1b9001545a27f9c3d19f0Marco Nelissen } 622fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong } 623fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong } 624fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onTouchEvent(MotionEvent ev) { 627fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong if (isInPlaybackState() && mMediaController != null) { 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toggleMediaControlsVisiblity(); 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 632256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onTrackballEvent(MotionEvent ev) { 635fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong if (isInPlaybackState() && mMediaController != null) { 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toggleMediaControlsVisiblity(); 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 640256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 644fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK && 645fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong keyCode != KeyEvent.KEYCODE_VOLUME_UP && 646fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong keyCode != KeyEvent.KEYCODE_VOLUME_DOWN && 647b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown keyCode != KeyEvent.KEYCODE_VOLUME_MUTE && 648fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong keyCode != KeyEvent.KEYCODE_MENU && 649fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong keyCode != KeyEvent.KEYCODE_CALL && 650fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong keyCode != KeyEvent.KEYCODE_ENDCALL; 651fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong if (isInPlaybackState() && isKeyCodeSupported && mMediaController != null) { 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK || 653f8a7ceaef2e7d5cd530c9426bde91b6fa9a40b75Andy Stadler keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) { 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMediaPlayer.isPlaying()) { 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pause(); 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaController.show(); 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start(); 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaController.hide(); 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 6624d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) { 663d7db70123fe177e149ae50283e31508f79452f8cChih-Chung Chang if (!mMediaPlayer.isPlaying()) { 6644d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown start(); 6654d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown mMediaController.hide(); 6664d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown } 6674d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown return true; 668256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP 6694d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) { 670d7db70123fe177e149ae50283e31508f79452f8cChih-Chung Chang if (mMediaPlayer.isPlaying()) { 6714d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown pause(); 6724d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown mMediaController.show(); 6734d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown } 6744d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown return true; 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toggleMediaControlsVisiblity(); 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.onKeyDown(keyCode, event); 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void toggleMediaControlsVisiblity() { 684256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber if (mMediaController.isShowing()) { 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaController.hide(); 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaController.show(); 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 690256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber 69113bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen @Override 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void start() { 693fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong if (isInPlaybackState()) { 694fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mMediaPlayer.start(); 695fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mCurrentState = STATE_PLAYING; 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 697fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mTargetState = STATE_PLAYING; 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 699256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber 70013bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen @Override 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void pause() { 702fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong if (isInPlaybackState()) { 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMediaPlayer.isPlaying()) { 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaPlayer.pause(); 705fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mCurrentState = STATE_PAUSED; 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 708fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mTargetState = STATE_PAUSED; 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 710256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber 7112e1818a4d16c3309660f27286c77d8d1eee95a25Gloria Wang public void suspend() { 71269b8d69aadbf0e795f1a1e1adc82c78cf0b9959fAndreas Huber release(false); 7132e1818a4d16c3309660f27286c77d8d1eee95a25Gloria Wang } 7142e1818a4d16c3309660f27286c77d8d1eee95a25Gloria Wang 7152e1818a4d16c3309660f27286c77d8d1eee95a25Gloria Wang public void resume() { 71669b8d69aadbf0e795f1a1e1adc82c78cf0b9959fAndreas Huber openVideo(); 7172e1818a4d16c3309660f27286c77d8d1eee95a25Gloria Wang } 7182e1818a4d16c3309660f27286c77d8d1eee95a25Gloria Wang 71913bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen @Override 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getDuration() { 721fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong if (isInPlaybackState()) { 722585c07e9ac19060bb242067a72a570cd42c75deaAndreas Huber return mMediaPlayer.getDuration(); 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 724585c07e9ac19060bb242067a72a570cd42c75deaAndreas Huber 725585c07e9ac19060bb242067a72a570cd42c75deaAndreas Huber return -1; 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 727256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber 72813bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen @Override 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getCurrentPosition() { 730fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong if (isInPlaybackState()) { 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mMediaPlayer.getCurrentPosition(); 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 735256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber 73613bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen @Override 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void seekTo(int msec) { 738fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong if (isInPlaybackState()) { 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaPlayer.seekTo(msec); 740fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mSeekWhenPrepared = 0; 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSeekWhenPrepared = msec; 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 744256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber } 745256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber 74613bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen @Override 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isPlaying() { 748fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong return isInPlaybackState() && mMediaPlayer.isPlaying(); 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 750256430093679e1d62b54fb0c852126e54d162f6fAndreas Huber 75113bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen @Override 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getBufferPercentage() { 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMediaPlayer != null) { 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mCurrentBufferPercentage; 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 758fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong 759fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong private boolean isInPlaybackState() { 760fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong return (mMediaPlayer != null && 761fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mCurrentState != STATE_ERROR && 762fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mCurrentState != STATE_IDLE && 763fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong mCurrentState != STATE_PREPARING); 764fdf3ac6cdc370d7dedca463dddd697a1bed79a9cJames Dong } 765c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen 76613bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen @Override 767c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen public boolean canPause() { 768c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen return mCanPause; 769c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen } 770c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen 77113bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen @Override 772c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen public boolean canSeekBackward() { 773c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen return mCanSeekBack; 774c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen } 775c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen 77613bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen @Override 777c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen public boolean canSeekForward() { 778c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen return mCanSeekForward; 779c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen } 78013bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen 78113bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen @Override 78213bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen public int getAudioSessionId() { 78313bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen if (mAudioSession == 0) { 78413bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen MediaPlayer foo = new MediaPlayer(); 78513bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen mAudioSession = foo.getAudioSessionId(); 78613bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen foo.release(); 78713bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen } 78813bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen return mAudioSession; 78913bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen } 790de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette 791de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette @Override 792d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette protected void onAttachedToWindow() { 793d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette super.onAttachedToWindow(); 794de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette 795d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette if (mSubtitleWidget != null) { 796d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette mSubtitleWidget.onAttachedToWindow(); 797de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette } 798de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette } 799de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette 800de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette @Override 801d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette protected void onDetachedFromWindow() { 802d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette super.onDetachedFromWindow(); 803de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette 804d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette if (mSubtitleWidget != null) { 805d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette mSubtitleWidget.onDetachedFromWindow(); 806de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette } 807de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette } 808de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette 809d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette @Override 810d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 811d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette super.onLayout(changed, left, top, right, bottom); 812de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette 813d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette if (mSubtitleWidget != null) { 814d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette measureAndLayoutSubtitleWidget(); 815de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette } 816de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette } 817de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette 818d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette @Override 819d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette public void draw(Canvas canvas) { 820d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette super.draw(canvas); 821de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette 822d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette if (mSubtitleWidget != null) { 823d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette final int saveCount = canvas.save(); 824d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette canvas.translate(getPaddingLeft(), getPaddingTop()); 825d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette mSubtitleWidget.draw(canvas); 826d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette canvas.restoreToCount(saveCount); 827de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette } 828de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette } 829de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette 830de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette /** 831de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette * Forces a measurement and layout pass for all overlaid views. 832de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette * 833d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette * @see #setSubtitleWidget(RenderingWidget) 834de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette */ 835d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette private void measureAndLayoutSubtitleWidget() { 836d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette final int width = getWidth() - getPaddingLeft() - getPaddingRight(); 837d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette final int height = getHeight() - getPaddingTop() - getPaddingBottom(); 838de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette 839d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette mSubtitleWidget.setSize(width, height); 840de213f708fc715c85f806fe5f4a7552e8b363bf9Alan Viverette } 841484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar 842484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar /** @hide */ 843484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar @Override 844d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette public void setSubtitleWidget(RenderingWidget subtitleWidget) { 845d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette if (mSubtitleWidget == subtitleWidget) { 846484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar return; 847484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar } 848484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar 849d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette final boolean attachedToWindow = isAttachedToWindow(); 850d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette if (mSubtitleWidget != null) { 851d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette if (attachedToWindow) { 852d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette mSubtitleWidget.onDetachedFromWindow(); 853d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette } 854d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette 855d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette mSubtitleWidget.setOnChangedListener(null); 856484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar } 857d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette 858d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette mSubtitleWidget = subtitleWidget; 859d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette 860d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette if (subtitleWidget != null) { 861d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette if (mSubtitlesChangedListener == null) { 862d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette mSubtitlesChangedListener = new RenderingWidget.OnChangedListener() { 863d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette @Override 864d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette public void onChanged(RenderingWidget renderingWidget) { 865d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette invalidate(); 866d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette } 867d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette }; 868d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette } 869d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette 870d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette setWillNotDraw(false); 871d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette subtitleWidget.setOnChangedListener(mSubtitlesChangedListener); 872d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette 873d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette if (attachedToWindow) { 874d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette subtitleWidget.onAttachedToWindow(); 875d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette requestLayout(); 876d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette } 877d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette } else { 878d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette setWillNotDraw(true); 879484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar } 880484ff7a92298eaeb5e7edc39895b3a26bed704b3Lajos Molnar 881d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette invalidate(); 882d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette } 88329f5183794efd58a3442aedcf829e3dbcd3fd867Lajos Molnar 88429f5183794efd58a3442aedcf829e3dbcd3fd867Lajos Molnar /** @hide */ 88529f5183794efd58a3442aedcf829e3dbcd3fd867Lajos Molnar @Override 88629f5183794efd58a3442aedcf829e3dbcd3fd867Lajos Molnar public Looper getSubtitleLooper() { 88729f5183794efd58a3442aedcf829e3dbcd3fd867Lajos Molnar return Looper.getMainLooper(); 88829f5183794efd58a3442aedcf829e3dbcd3fd867Lajos Molnar } 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 890