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.content.Context;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.PixelFormat;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.media.AudioManager;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Gravity;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.LayoutInflater;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.MotionEvent;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewGroup;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Window;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManager;
348a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityEvent;
358a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.SeekBar.OnSeekBarChangeListener;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.policy.PolicyManager;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Formatter;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Locale;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A view containing controls for a MediaPlayer. Typically contains the
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * buttons like "Play/Pause", "Rewind", "Fast Forward" and a progress
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * slider. It takes care of synchronizing the controls with the state
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of the MediaPlayer.
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The way to use this class is to instantiate it programatically.
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The MediaController will create a default set of controls
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and put them in a window floating above your application. Specifically,
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the controls will float above the view specified with setAnchorView().
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The window will disappear if left idle for three seconds and reappear
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * when the user touches the anchor view.
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Functions like show() and hide() have no effect when MediaController
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is created in an xml layout.
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * MediaController will hide and
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * show the buttons according to these rules:
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> The "previous" and "next" buttons are hidden until setPrevNextListeners()
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   has been called
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> The "previous" and "next" buttons are visible but disabled if
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   setPrevNextListeners() was called with null listeners
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li> The "rewind" and "fastforward" buttons are shown unless requested
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   otherwise by using the MediaController(Context, boolean) constructor
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   with the boolean set to false
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class MediaController extends FrameLayout {
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private MediaPlayerControl  mPlayer;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Context             mContext;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View                mAnchor;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View                mRoot;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private WindowManager       mWindowManager;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Window              mWindow;
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View                mDecor;
8085d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang    private WindowManager.LayoutParams mDecorLayoutParams;
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ProgressBar         mProgress;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private TextView            mEndTime, mCurrentTime;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean             mShowing;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean             mDragging;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int    sDefaultTimeout = 3000;
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int    FADE_OUT = 1;
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int    SHOW_PROGRESS = 2;
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean             mUseFastForward;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean             mFromXml;
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean             mListenersSet;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View.OnClickListener mNextListener, mPrevListener;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    StringBuilder               mFormatBuilder;
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Formatter                   mFormatter;
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ImageButton         mPauseButton;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ImageButton         mFfwdButton;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ImageButton         mRewButton;
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ImageButton         mNextButton;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ImageButton         mPrevButton;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MediaController(Context context, AttributeSet attrs) {
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(context, attrs);
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRoot = this;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mUseFastForward = true;
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFromXml = true;
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onFinishInflate() {
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRoot != null)
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            initControllerView(mRoot);
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MediaController(Context context, boolean useFastForward) {
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(context);
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mUseFastForward = useFastForward;
11802dd17da3685652b5235ca48bd6882e65997434aChih-Chung Chang        initFloatingWindowLayout();
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initFloatingWindow();
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MediaController(Context context) {
12302dd17da3685652b5235ca48bd6882e65997434aChih-Chung Chang        this(context, true);
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void initFloatingWindow() {
127ef367529f9c7a538d74599b37b49ac309d0a8d8cChristian Mehlmauer        mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWindow = PolicyManager.makeNewWindow(mContext);
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWindow.setWindowManager(mWindowManager, null, null);
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWindow.requestFeature(Window.FEATURE_NO_TITLE);
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDecor = mWindow.getDecorView();
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDecor.setOnTouchListener(mTouchListener);
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWindow.setContentView(this);
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWindow.setBackgroundDrawableResource(android.R.color.transparent);
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // While the media controller is up, the volume control keys should
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // affect the media stream type
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWindow.setVolumeControlStream(AudioManager.STREAM_MUSIC);
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setFocusable(true);
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setFocusableInTouchMode(true);
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        requestFocus();
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14685d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang    // Allocate and initialize the static parts of mDecorLayoutParams. Must
14785d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang    // also call updateFloatingWindowLayout() to fill in the dynamic parts
14885d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang    // (y and width) before mDecorLayoutParams can be used.
14985d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang    private void initFloatingWindowLayout() {
15085d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        mDecorLayoutParams = new WindowManager.LayoutParams();
15185d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        WindowManager.LayoutParams p = mDecorLayoutParams;
1520b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen        p.gravity = Gravity.TOP | Gravity.LEFT;
15385d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        p.height = LayoutParams.WRAP_CONTENT;
15485d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        p.x = 0;
15585d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        p.format = PixelFormat.TRANSLUCENT;
15685d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
15785d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        p.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
15885d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
15985d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang                | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
16085d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        p.token = null;
16185d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        p.windowAnimations = 0; // android.R.style.DropDownAnimationDown;
16285d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang    }
16385d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang
16485d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang    // Update the dynamic parts of mDecorLayoutParams
16585d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang    // Must be called with mAnchor != NULL.
16685d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang    private void updateFloatingWindowLayout() {
16785d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        int [] anchorPos = new int[2];
16885d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        mAnchor.getLocationOnScreen(anchorPos);
16985d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang
1700b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen        // we need to know the size of the controller so we can properly position it
1710b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen        // within its space
1720b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen        mDecor.measure(MeasureSpec.makeMeasureSpec(mAnchor.getWidth(), MeasureSpec.AT_MOST),
1730b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen                MeasureSpec.makeMeasureSpec(mAnchor.getHeight(), MeasureSpec.AT_MOST));
1740b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen
17585d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        WindowManager.LayoutParams p = mDecorLayoutParams;
17685d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        p.width = mAnchor.getWidth();
1770b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen        p.x = anchorPos[0] + (mAnchor.getWidth() - p.width) / 2;
1780b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen        p.y = anchorPos[1] + mAnchor.getHeight() - mDecor.getMeasuredHeight();
17985d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang    }
18085d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang
18185d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang    // This is called whenever mAnchor's layout bound changes
18285d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang    private OnLayoutChangeListener mLayoutChangeListener =
18385d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang            new OnLayoutChangeListener() {
18485d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        public void onLayoutChange(View v, int left, int top, int right,
18585d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang                int bottom, int oldLeft, int oldTop, int oldRight,
18685d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang                int oldBottom) {
18785d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang            updateFloatingWindowLayout();
18885d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang            if (mShowing) {
18985d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang                mWindowManager.updateViewLayout(mDecor, mDecorLayoutParams);
19085d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang            }
19185d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        }
19285d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang    };
19385d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private OnTouchListener mTouchListener = new OnTouchListener() {
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean onTouch(View v, MotionEvent event) {
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (event.getAction() == MotionEvent.ACTION_DOWN) {
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mShowing) {
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    hide();
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setMediaPlayer(MediaPlayerControl player) {
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPlayer = player;
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updatePausePlay();
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the view that acts as the anchor for the control view.
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This can for example be a VideoView, or your Activity's main view.
2130b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen     * When VideoView calls this method, it will use the VideoView's parent
2140b2d87237ed53b94dc2216a42942d35788d3307bMarco Nelissen     * as the anchor.
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param view The view to which to anchor the controller when it is visible.
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAnchorView(View view) {
21885d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        if (mAnchor != null) {
21985d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang            mAnchor.removeOnLayoutChangeListener(mLayoutChangeListener);
22085d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        }
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnchor = view;
22285d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        if (mAnchor != null) {
22385d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang            mAnchor.addOnLayoutChangeListener(mLayoutChangeListener);
22485d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        }
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams(
227980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy                ViewGroup.LayoutParams.MATCH_PARENT,
228980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy                ViewGroup.LayoutParams.MATCH_PARENT
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        );
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        removeAllViews();
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View v = makeControllerView();
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        addView(v, frameParams);
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create the view that holds the widgets that control playback.
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Derived classes can override this to create their own.
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The controller view.
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide This doesn't work as advertised
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected View makeControllerView() {
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LayoutInflater inflate = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRoot = inflate.inflate(com.android.internal.R.layout.media_controller, null);
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initControllerView(mRoot);
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mRoot;
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void initControllerView(View v) {
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPauseButton = (ImageButton) v.findViewById(com.android.internal.R.id.pause);
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPauseButton != null) {
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPauseButton.requestFocus();
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPauseButton.setOnClickListener(mPauseListener);
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFfwdButton = (ImageButton) v.findViewById(com.android.internal.R.id.ffwd);
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFfwdButton != null) {
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFfwdButton.setOnClickListener(mFfwdListener);
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mFromXml) {
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mFfwdButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRewButton = (ImageButton) v.findViewById(com.android.internal.R.id.rew);
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRewButton != null) {
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRewButton.setOnClickListener(mRewListener);
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mFromXml) {
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRewButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // By default these are hidden. They will be enabled when setPrevNextListeners() is called
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNextButton = (ImageButton) v.findViewById(com.android.internal.R.id.next);
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNextButton != null && !mFromXml && !mListenersSet) {
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNextButton.setVisibility(View.GONE);
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPrevButton = (ImageButton) v.findViewById(com.android.internal.R.id.prev);
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPrevButton != null && !mFromXml && !mListenersSet) {
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPrevButton.setVisibility(View.GONE);
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProgress = (ProgressBar) v.findViewById(com.android.internal.R.id.mediacontroller_progress);
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mProgress != null) {
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mProgress instanceof SeekBar) {
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                SeekBar seeker = (SeekBar) mProgress;
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                seeker.setOnSeekBarChangeListener(mSeekListener);
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProgress.setMax(1000);
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEndTime = (TextView) v.findViewById(com.android.internal.R.id.time);
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurrentTime = (TextView) v.findViewById(com.android.internal.R.id.time_current);
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFormatBuilder = new StringBuilder();
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        installPrevNextListeners();
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Show the controller on screen. It will go away
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * automatically after 3 seconds of inactivity.
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void show() {
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        show(sDefaultTimeout);
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
310c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen     * Disable pause or seek buttons if the stream cannot be paused or seeked.
311c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen     * This requires the control interface to be a MediaPlayerControlExt
312c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen     */
313c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen    private void disableUnsupportedButtons() {
314c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen        try {
315c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            if (mPauseButton != null && !mPlayer.canPause()) {
316c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen                mPauseButton.setEnabled(false);
317c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            }
318c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            if (mRewButton != null && !mPlayer.canSeekBackward()) {
319c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen                mRewButton.setEnabled(false);
320c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            }
321c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            if (mFfwdButton != null && !mPlayer.canSeekForward()) {
322c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen                mFfwdButton.setEnabled(false);
323c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            }
324c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen        } catch (IncompatibleClassChangeError ex) {
325c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            // We were given an old version of the interface, that doesn't have
326c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            // the canPause/canSeekXYZ methods. This is OK, it just means we
327c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            // assume the media can be paused and seeked, and so we don't disable
328c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            // the buttons.
329c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen        }
330c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen    }
331c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen
332c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen    /**
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Show the controller on screen. It will go away
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * automatically after 'timeout' milliseconds of inactivity.
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param timeout The timeout in milliseconds. Use 0 to show
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the controller until hide() is called.
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void show(int timeout) {
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mShowing && mAnchor != null) {
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setProgress();
341d701e020769b7cc6dd492eadcb09083578074ee0Marco Nelissen            if (mPauseButton != null) {
342d701e020769b7cc6dd492eadcb09083578074ee0Marco Nelissen                mPauseButton.requestFocus();
343d701e020769b7cc6dd492eadcb09083578074ee0Marco Nelissen            }
344c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            disableUnsupportedButtons();
34585d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang            updateFloatingWindowLayout();
34685d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang            mWindowManager.addView(mDecor, mDecorLayoutParams);
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowing = true;
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updatePausePlay();
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // cause the progress bar to be updated even if mShowing
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // was already true.  This happens, for example, if we're
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // paused with the progress bar showing the user hits play.
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler.sendEmptyMessage(SHOW_PROGRESS);
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Message msg = mHandler.obtainMessage(FADE_OUT);
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (timeout != 0) {
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHandler.removeMessages(FADE_OUT);
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHandler.sendMessageDelayed(msg, timeout);
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isShowing() {
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mShowing;
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove the controller from the screen.
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void hide() {
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mAnchor == null)
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowing) {
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHandler.removeMessages(SHOW_PROGRESS);
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mWindowManager.removeView(mDecor);
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IllegalArgumentException ex) {
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.w("MediaController", "already removed");
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowing = false;
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Handler mHandler = new Handler() {
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void handleMessage(Message msg) {
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int pos;
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (msg.what) {
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case FADE_OUT:
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    hide();
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SHOW_PROGRESS:
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pos = setProgress();
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!mDragging && mShowing && mPlayer.isPlaying()) {
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        msg = obtainMessage(SHOW_PROGRESS);
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sendMessageDelayed(msg, 1000 - (pos % 1000));
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String stringForTime(int timeMs) {
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int totalSeconds = timeMs / 1000;
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int seconds = totalSeconds % 60;
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int minutes = (totalSeconds / 60) % 60;
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int hours   = totalSeconds / 3600;
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFormatBuilder.setLength(0);
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (hours > 0) {
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mFormatter.format("%02d:%02d", minutes, seconds).toString();
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int setProgress() {
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPlayer == null || mDragging) {
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int position = mPlayer.getCurrentPosition();
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int duration = mPlayer.getDuration();
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mProgress != null) {
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (duration > 0) {
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // use long to avoid overflow
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long pos = 1000L * position / duration;
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mProgress.setProgress( (int) pos);
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int percent = mPlayer.getBufferPercentage();
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProgress.setSecondaryProgress(percent * 10);
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEndTime != null)
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEndTime.setText(stringForTime(duration));
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrentTime != null)
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurrentTime.setText(stringForTime(position));
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return position;
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onTouchEvent(MotionEvent event) {
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        show(sDefaultTimeout);
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onTrackballEvent(MotionEvent ev) {
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        show(sDefaultTimeout);
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean dispatchKeyEvent(KeyEvent event) {
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int keyCode = event.getKeyCode();
4584d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown        final boolean uniqueDown = event.getRepeatCount() == 0
4594d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                && event.getAction() == KeyEvent.ACTION_DOWN;
4604d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown        if (keyCode ==  KeyEvent.KEYCODE_HEADSETHOOK
4614d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
4624d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                || keyCode == KeyEvent.KEYCODE_SPACE) {
4634d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown            if (uniqueDown) {
4644d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                doPauseResume();
4654d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                show(sDefaultTimeout);
4664d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                if (mPauseButton != null) {
4674d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                    mPauseButton.requestFocus();
4684d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                }
4694d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown            }
4704d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown            return true;
4714d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown        } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
4724d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown            if (uniqueDown && !mPlayer.isPlaying()) {
4734d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                mPlayer.start();
4744d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                updatePausePlay();
4754d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                show(sDefaultTimeout);
476d701e020769b7cc6dd492eadcb09083578074ee0Marco Nelissen            }
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
4784d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown        } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
4794d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
4804d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown            if (uniqueDown && mPlayer.isPlaying()) {
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mPlayer.pause();
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                updatePausePlay();
4834d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                show(sDefaultTimeout);
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
4864d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
487b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown                || keyCode == KeyEvent.KEYCODE_VOLUME_UP
48896ac720117979ab0507d8760f49076a0a1e3bfb8bxu                || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE
48996ac720117979ab0507d8760f49076a0a1e3bfb8bxu                || keyCode == KeyEvent.KEYCODE_CAMERA) {
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // don't show the controls for volume adjustment
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return super.dispatchKeyEvent(event);
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU) {
4934d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown            if (uniqueDown) {
4944d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                hide();
4954d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown            }
496105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return true;
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4984d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown
4994d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown        show(sDefaultTimeout);
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return super.dispatchKeyEvent(event);
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View.OnClickListener mPauseListener = new View.OnClickListener() {
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onClick(View v) {
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            doPauseResume();
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            show(sDefaultTimeout);
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updatePausePlay() {
511c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen        if (mRoot == null || mPauseButton == null)
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPlayer.isPlaying()) {
515c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            mPauseButton.setImageResource(com.android.internal.R.drawable.ic_media_pause);
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
517c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            mPauseButton.setImageResource(com.android.internal.R.drawable.ic_media_play);
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void doPauseResume() {
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPlayer.isPlaying()) {
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPlayer.pause();
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPlayer.start();
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updatePausePlay();
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5300de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    // There are two scenarios that can trigger the seekbar listener to trigger:
5310de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    //
5320de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    // The first is the user using the touchpad to adjust the posititon of the
5330de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    // seekbar's thumb. In this case onStartTrackingTouch is called followed by
5340de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    // a number of onProgressChanged notifications, concluded by onStopTrackingTouch.
5350de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    // We're setting the field "mDragging" to true for the duration of the dragging
5360de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    // session to avoid jumps in the position in case of ongoing playback.
5370de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    //
5380de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    // The second scenario involves the user operating the scroll ball, in this
5390de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    // case there WON'T BE onStartTrackingTouch/onStopTrackingTouch notifications,
5400de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    // we will simply apply the updated position without suspending regular updates.
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onStartTrackingTouch(SeekBar bar) {
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            show(3600000);
5440de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber
5450de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            mDragging = true;
5460de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber
5470de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            // By removing these pending progress messages we make sure
5480de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            // that a) we won't update the progress while the user adjusts
5490de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            // the seekbar and b) once the user is done dragging the thumb
5500de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            // we will post one of these messages to the queue again and
5510de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            // this ensures that there will be exactly one message queued up.
5520de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            mHandler.removeMessages(SHOW_PROGRESS);
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5540de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber
5550de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber        public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
5560de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            if (!fromuser) {
5570de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber                // We're not interested in programmatically generated changes to
5580de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber                // the progress bar's position.
5590de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber                return;
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5610de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber
5620de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            long duration = mPlayer.getDuration();
5630de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            long newposition = (duration * progress) / 1000L;
5640de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            mPlayer.seekTo( (int) newposition);
5650de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            if (mCurrentTime != null)
5660de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber                mCurrentTime.setText(stringForTime( (int) newposition));
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5680de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onStopTrackingTouch(SeekBar bar) {
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDragging = false;
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setProgress();
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updatePausePlay();
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            show(sDefaultTimeout);
5740de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber
5750de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            // Ensure that progress is properly updated in the future,
5760de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            // the call to show() does not guarantee this because it is a
5770de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            // no-op if we are already showing.
5780de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            mHandler.sendEmptyMessage(SHOW_PROGRESS);
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setEnabled(boolean enabled) {
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPauseButton != null) {
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPauseButton.setEnabled(enabled);
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFfwdButton != null) {
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFfwdButton.setEnabled(enabled);
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRewButton != null) {
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRewButton.setEnabled(enabled);
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNextButton != null) {
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNextButton.setEnabled(enabled && mNextListener != null);
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPrevButton != null) {
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPrevButton.setEnabled(enabled && mPrevListener != null);
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mProgress != null) {
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProgress.setEnabled(enabled);
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
602c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen        disableUnsupportedButtons();
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.setEnabled(enabled);
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6068a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    @Override
6078a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6088a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        super.onInitializeAccessibilityEvent(event);
6098a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        event.setClassName(MediaController.class.getName());
6108a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    }
6118a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov
6128a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    @Override
6138a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6148a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        super.onInitializeAccessibilityNodeInfo(info);
6158a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        info.setClassName(MediaController.class.getName());
6168a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    }
6178a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View.OnClickListener mRewListener = new View.OnClickListener() {
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onClick(View v) {
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int pos = mPlayer.getCurrentPosition();
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pos -= 5000; // milliseconds
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPlayer.seekTo(pos);
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setProgress();
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            show(sDefaultTimeout);
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View.OnClickListener mFfwdListener = new View.OnClickListener() {
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onClick(View v) {
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int pos = mPlayer.getCurrentPosition();
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pos += 15000; // milliseconds
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPlayer.seekTo(pos);
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setProgress();
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            show(sDefaultTimeout);
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void installPrevNextListeners() {
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNextButton != null) {
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNextButton.setOnClickListener(mNextListener);
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNextButton.setEnabled(mNextListener != null);
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPrevButton != null) {
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPrevButton.setOnClickListener(mPrevListener);
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPrevButton.setEnabled(mPrevListener != null);
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setPrevNextListeners(View.OnClickListener next, View.OnClickListener prev) {
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNextListener = next;
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPrevListener = prev;
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mListenersSet = true;
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRoot != null) {
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            installPrevNextListeners();
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mNextButton != null && !mFromXml) {
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mNextButton.setVisibility(View.VISIBLE);
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mPrevButton != null && !mFromXml) {
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mPrevButton.setVisibility(View.VISIBLE);
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface MediaPlayerControl {
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void    start();
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void    pause();
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int     getDuration();
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int     getCurrentPosition();
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void    seekTo(int pos);
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean isPlaying();
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int     getBufferPercentage();
677c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen        boolean canPause();
678c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen        boolean canSeekBackward();
679c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen        boolean canSeekForward();
68013bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen
68113bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen        /**
68213bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen         * Get the audio session id for the player used by this VideoView. This can be used to
68313bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen         * apply audio effects to the audio track of a video.
68413bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen         * @return The audio session, or 0 if there was an error.
68513bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen         */
68613bfebd6b70ebfd8ad0d1aa24a92178ebff3565bMarco Nelissen        int     getAudioSessionId();
687c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen    }
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
689