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;
15285d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        p.gravity = Gravity.TOP;
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
17085d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        WindowManager.LayoutParams p = mDecorLayoutParams;
17185d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        p.width = mAnchor.getWidth();
17285d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        p.y = anchorPos[1] + mAnchor.getHeight();
17385d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang    }
17485d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang
17585d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang    // This is called whenever mAnchor's layout bound changes
17685d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang    private OnLayoutChangeListener mLayoutChangeListener =
17785d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang            new OnLayoutChangeListener() {
17885d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        public void onLayoutChange(View v, int left, int top, int right,
17985d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang                int bottom, int oldLeft, int oldTop, int oldRight,
18085d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang                int oldBottom) {
18185d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang            updateFloatingWindowLayout();
18285d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang            if (mShowing) {
18385d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang                mWindowManager.updateViewLayout(mDecor, mDecorLayoutParams);
18485d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang            }
18585d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        }
18685d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang    };
18785d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private OnTouchListener mTouchListener = new OnTouchListener() {
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean onTouch(View v, MotionEvent event) {
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (event.getAction() == MotionEvent.ACTION_DOWN) {
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mShowing) {
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    hide();
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setMediaPlayer(MediaPlayerControl player) {
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPlayer = player;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updatePausePlay();
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the view that acts as the anchor for the control view.
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This can for example be a VideoView, or your Activity's main view.
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param view The view to which to anchor the controller when it is visible.
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAnchorView(View view) {
21085d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        if (mAnchor != null) {
21185d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang            mAnchor.removeOnLayoutChangeListener(mLayoutChangeListener);
21285d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        }
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnchor = view;
21485d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        if (mAnchor != null) {
21585d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang            mAnchor.addOnLayoutChangeListener(mLayoutChangeListener);
21685d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang        }
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams(
219980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy                ViewGroup.LayoutParams.MATCH_PARENT,
220980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy                ViewGroup.LayoutParams.MATCH_PARENT
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        );
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        removeAllViews();
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View v = makeControllerView();
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        addView(v, frameParams);
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create the view that holds the widgets that control playback.
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Derived classes can override this to create their own.
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The controller view.
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide This doesn't work as advertised
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected View makeControllerView() {
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LayoutInflater inflate = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRoot = inflate.inflate(com.android.internal.R.layout.media_controller, null);
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initControllerView(mRoot);
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mRoot;
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void initControllerView(View v) {
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPauseButton = (ImageButton) v.findViewById(com.android.internal.R.id.pause);
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPauseButton != null) {
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPauseButton.requestFocus();
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPauseButton.setOnClickListener(mPauseListener);
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFfwdButton = (ImageButton) v.findViewById(com.android.internal.R.id.ffwd);
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFfwdButton != null) {
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFfwdButton.setOnClickListener(mFfwdListener);
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mFromXml) {
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mFfwdButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRewButton = (ImageButton) v.findViewById(com.android.internal.R.id.rew);
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRewButton != null) {
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRewButton.setOnClickListener(mRewListener);
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mFromXml) {
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRewButton.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        // By default these are hidden. They will be enabled when setPrevNextListeners() is called
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNextButton = (ImageButton) v.findViewById(com.android.internal.R.id.next);
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNextButton != null && !mFromXml && !mListenersSet) {
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNextButton.setVisibility(View.GONE);
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPrevButton = (ImageButton) v.findViewById(com.android.internal.R.id.prev);
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPrevButton != null && !mFromXml && !mListenersSet) {
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPrevButton.setVisibility(View.GONE);
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProgress = (ProgressBar) v.findViewById(com.android.internal.R.id.mediacontroller_progress);
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mProgress != null) {
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mProgress instanceof SeekBar) {
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                SeekBar seeker = (SeekBar) mProgress;
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                seeker.setOnSeekBarChangeListener(mSeekListener);
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProgress.setMax(1000);
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEndTime = (TextView) v.findViewById(com.android.internal.R.id.time);
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurrentTime = (TextView) v.findViewById(com.android.internal.R.id.time_current);
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFormatBuilder = new StringBuilder();
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        installPrevNextListeners();
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Show the controller on screen. It will go away
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * automatically after 3 seconds of inactivity.
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void show() {
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        show(sDefaultTimeout);
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
302c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen     * Disable pause or seek buttons if the stream cannot be paused or seeked.
303c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen     * This requires the control interface to be a MediaPlayerControlExt
304c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen     */
305c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen    private void disableUnsupportedButtons() {
306c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen        try {
307c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            if (mPauseButton != null && !mPlayer.canPause()) {
308c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen                mPauseButton.setEnabled(false);
309c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            }
310c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            if (mRewButton != null && !mPlayer.canSeekBackward()) {
311c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen                mRewButton.setEnabled(false);
312c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            }
313c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            if (mFfwdButton != null && !mPlayer.canSeekForward()) {
314c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen                mFfwdButton.setEnabled(false);
315c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            }
316c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen        } catch (IncompatibleClassChangeError ex) {
317c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            // We were given an old version of the interface, that doesn't have
318c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            // the canPause/canSeekXYZ methods. This is OK, it just means we
319c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            // assume the media can be paused and seeked, and so we don't disable
320c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            // the buttons.
321c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen        }
322c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen    }
323c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen
324c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen    /**
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Show the controller on screen. It will go away
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * automatically after 'timeout' milliseconds of inactivity.
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param timeout The timeout in milliseconds. Use 0 to show
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the controller until hide() is called.
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void show(int timeout) {
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mShowing && mAnchor != null) {
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setProgress();
333d701e020769b7cc6dd492eadcb09083578074ee0Marco Nelissen            if (mPauseButton != null) {
334d701e020769b7cc6dd492eadcb09083578074ee0Marco Nelissen                mPauseButton.requestFocus();
335d701e020769b7cc6dd492eadcb09083578074ee0Marco Nelissen            }
336c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            disableUnsupportedButtons();
33785d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang            updateFloatingWindowLayout();
33885d4ea6fe49e97c8b569768ba63a849653adb5b1Chih-Chung Chang            mWindowManager.addView(mDecor, mDecorLayoutParams);
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowing = true;
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updatePausePlay();
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // cause the progress bar to be updated even if mShowing
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // was already true.  This happens, for example, if we're
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // paused with the progress bar showing the user hits play.
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler.sendEmptyMessage(SHOW_PROGRESS);
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Message msg = mHandler.obtainMessage(FADE_OUT);
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (timeout != 0) {
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHandler.removeMessages(FADE_OUT);
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHandler.sendMessageDelayed(msg, timeout);
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isShowing() {
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mShowing;
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove the controller from the screen.
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void hide() {
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mAnchor == null)
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowing) {
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHandler.removeMessages(SHOW_PROGRESS);
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mWindowManager.removeView(mDecor);
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IllegalArgumentException ex) {
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.w("MediaController", "already removed");
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowing = false;
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Handler mHandler = new Handler() {
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void handleMessage(Message msg) {
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int pos;
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (msg.what) {
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case FADE_OUT:
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    hide();
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case SHOW_PROGRESS:
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pos = setProgress();
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!mDragging && mShowing && mPlayer.isPlaying()) {
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        msg = obtainMessage(SHOW_PROGRESS);
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sendMessageDelayed(msg, 1000 - (pos % 1000));
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String stringForTime(int timeMs) {
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int totalSeconds = timeMs / 1000;
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int seconds = totalSeconds % 60;
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int minutes = (totalSeconds / 60) % 60;
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int hours   = totalSeconds / 3600;
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFormatBuilder.setLength(0);
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (hours > 0) {
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mFormatter.format("%02d:%02d", minutes, seconds).toString();
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int setProgress() {
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPlayer == null || mDragging) {
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int position = mPlayer.getCurrentPosition();
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int duration = mPlayer.getDuration();
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mProgress != null) {
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (duration > 0) {
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // use long to avoid overflow
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long pos = 1000L * position / duration;
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mProgress.setProgress( (int) pos);
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int percent = mPlayer.getBufferPercentage();
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProgress.setSecondaryProgress(percent * 10);
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEndTime != null)
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEndTime.setText(stringForTime(duration));
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrentTime != null)
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurrentTime.setText(stringForTime(position));
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return position;
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onTouchEvent(MotionEvent event) {
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        show(sDefaultTimeout);
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onTrackballEvent(MotionEvent ev) {
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        show(sDefaultTimeout);
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean dispatchKeyEvent(KeyEvent event) {
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int keyCode = event.getKeyCode();
4504d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown        final boolean uniqueDown = event.getRepeatCount() == 0
4514d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                && event.getAction() == KeyEvent.ACTION_DOWN;
4524d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown        if (keyCode ==  KeyEvent.KEYCODE_HEADSETHOOK
4534d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
4544d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                || keyCode == KeyEvent.KEYCODE_SPACE) {
4554d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown            if (uniqueDown) {
4564d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                doPauseResume();
4574d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                show(sDefaultTimeout);
4584d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                if (mPauseButton != null) {
4594d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                    mPauseButton.requestFocus();
4604d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                }
4614d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown            }
4624d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown            return true;
4634d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown        } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
4644d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown            if (uniqueDown && !mPlayer.isPlaying()) {
4654d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                mPlayer.start();
4664d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                updatePausePlay();
4674d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                show(sDefaultTimeout);
468d701e020769b7cc6dd492eadcb09083578074ee0Marco Nelissen            }
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
4704d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown        } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
4714d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
4724d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown            if (uniqueDown && mPlayer.isPlaying()) {
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mPlayer.pause();
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                updatePausePlay();
4754d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                show(sDefaultTimeout);
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
4784d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
479b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown                || keyCode == KeyEvent.KEYCODE_VOLUME_UP
48096ac720117979ab0507d8760f49076a0a1e3bfb8bxu                || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE
48196ac720117979ab0507d8760f49076a0a1e3bfb8bxu                || keyCode == KeyEvent.KEYCODE_CAMERA) {
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // don't show the controls for volume adjustment
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return super.dispatchKeyEvent(event);
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU) {
4854d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown            if (uniqueDown) {
4864d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown                hide();
4874d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown            }
488105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return true;
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4904d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown
4914d396052deb54399cbadbeb8abd873df6f3af342Jeff Brown        show(sDefaultTimeout);
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return super.dispatchKeyEvent(event);
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View.OnClickListener mPauseListener = new View.OnClickListener() {
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onClick(View v) {
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            doPauseResume();
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            show(sDefaultTimeout);
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updatePausePlay() {
503c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen        if (mRoot == null || mPauseButton == null)
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPlayer.isPlaying()) {
507c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            mPauseButton.setImageResource(com.android.internal.R.drawable.ic_media_pause);
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
509c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen            mPauseButton.setImageResource(com.android.internal.R.drawable.ic_media_play);
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void doPauseResume() {
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPlayer.isPlaying()) {
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPlayer.pause();
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPlayer.start();
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updatePausePlay();
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5220de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    // There are two scenarios that can trigger the seekbar listener to trigger:
5230de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    //
5240de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    // The first is the user using the touchpad to adjust the posititon of the
5250de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    // seekbar's thumb. In this case onStartTrackingTouch is called followed by
5260de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    // a number of onProgressChanged notifications, concluded by onStopTrackingTouch.
5270de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    // We're setting the field "mDragging" to true for the duration of the dragging
5280de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    // session to avoid jumps in the position in case of ongoing playback.
5290de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    //
5300de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    // The second scenario involves the user operating the scroll ball, in this
5310de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    // case there WON'T BE onStartTrackingTouch/onStopTrackingTouch notifications,
5320de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber    // we will simply apply the updated position without suspending regular updates.
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onStartTrackingTouch(SeekBar bar) {
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            show(3600000);
5360de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber
5370de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            mDragging = true;
5380de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber
5390de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            // By removing these pending progress messages we make sure
5400de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            // that a) we won't update the progress while the user adjusts
5410de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            // the seekbar and b) once the user is done dragging the thumb
5420de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            // we will post one of these messages to the queue again and
5430de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            // this ensures that there will be exactly one message queued up.
5440de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            mHandler.removeMessages(SHOW_PROGRESS);
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5460de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber
5470de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber        public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
5480de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            if (!fromuser) {
5490de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber                // We're not interested in programmatically generated changes to
5500de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber                // the progress bar's position.
5510de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber                return;
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5530de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber
5540de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            long duration = mPlayer.getDuration();
5550de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            long newposition = (duration * progress) / 1000L;
5560de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            mPlayer.seekTo( (int) newposition);
5570de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            if (mCurrentTime != null)
5580de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber                mCurrentTime.setText(stringForTime( (int) newposition));
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5600de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onStopTrackingTouch(SeekBar bar) {
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDragging = false;
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setProgress();
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updatePausePlay();
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            show(sDefaultTimeout);
5660de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber
5670de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            // Ensure that progress is properly updated in the future,
5680de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            // the call to show() does not guarantee this because it is a
5690de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            // no-op if we are already showing.
5700de7dcd126175a1bef77f2039b39df1eed4b4164Andreas Huber            mHandler.sendEmptyMessage(SHOW_PROGRESS);
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setEnabled(boolean enabled) {
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPauseButton != null) {
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPauseButton.setEnabled(enabled);
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFfwdButton != null) {
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFfwdButton.setEnabled(enabled);
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRewButton != null) {
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRewButton.setEnabled(enabled);
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNextButton != null) {
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNextButton.setEnabled(enabled && mNextListener != null);
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPrevButton != null) {
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPrevButton.setEnabled(enabled && mPrevListener != null);
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mProgress != null) {
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProgress.setEnabled(enabled);
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
594c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen        disableUnsupportedButtons();
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.setEnabled(enabled);
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5988a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    @Override
5998a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6008a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        super.onInitializeAccessibilityEvent(event);
6018a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        event.setClassName(MediaController.class.getName());
6028a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    }
6038a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov
6048a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    @Override
6058a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6068a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        super.onInitializeAccessibilityNodeInfo(info);
6078a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        info.setClassName(MediaController.class.getName());
6088a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    }
6098a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View.OnClickListener mRewListener = new View.OnClickListener() {
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onClick(View v) {
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int pos = mPlayer.getCurrentPosition();
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pos -= 5000; // milliseconds
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPlayer.seekTo(pos);
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setProgress();
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            show(sDefaultTimeout);
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View.OnClickListener mFfwdListener = new View.OnClickListener() {
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onClick(View v) {
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int pos = mPlayer.getCurrentPosition();
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pos += 15000; // milliseconds
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPlayer.seekTo(pos);
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setProgress();
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            show(sDefaultTimeout);
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void installPrevNextListeners() {
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNextButton != null) {
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNextButton.setOnClickListener(mNextListener);
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNextButton.setEnabled(mNextListener != null);
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPrevButton != null) {
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPrevButton.setOnClickListener(mPrevListener);
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPrevButton.setEnabled(mPrevListener != null);
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setPrevNextListeners(View.OnClickListener next, View.OnClickListener prev) {
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNextListener = next;
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPrevListener = prev;
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mListenersSet = true;
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRoot != null) {
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            installPrevNextListeners();
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mNextButton != null && !mFromXml) {
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mNextButton.setVisibility(View.VISIBLE);
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mPrevButton != null && !mFromXml) {
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mPrevButton.setVisibility(View.VISIBLE);
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface MediaPlayerControl {
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void    start();
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void    pause();
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int     getDuration();
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int     getCurrentPosition();
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void    seekTo(int pos);
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean isPlaying();
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int     getBufferPercentage();
669c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen        boolean canPause();
670c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen        boolean canSeekBackward();
671c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen        boolean canSeekForward();
672c818b141ee97a7a26fe069456d4b662d06c9eaeaMarco Nelissen    }
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
674