1dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli/*
2dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * Copyright (C) 2017 The Android Open Source Project
3dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli *
4dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * Licensed under the Apache License, Version 2.0 (the "License");
5dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * you may not use this file except in compliance with the License.
6dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * You may obtain a copy of the License at
7dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli *
8dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli *      http://www.apache.org/licenses/LICENSE-2.0
9dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli *
10dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * Unless required by applicable law or agreed to in writing, software
11dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * distributed under the License is distributed on an "AS IS" BASIS,
12dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * See the License for the specific language governing permissions and
14dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * limitations under the License.
15dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli */
16dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.leanback.media;
18dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
19ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_FAST_FORWARD;
20ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_PLAY_PAUSE;
21ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_REPEAT;
22ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_REWIND;
23ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_SHUFFLE;
24ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_SKIP_TO_NEXT;
25ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.leanback.media.PlaybackBaseControlGlue.ACTION_SKIP_TO_PREVIOUS;
26dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
27dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangliimport android.content.Context;
28dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangliimport android.graphics.Bitmap;
29dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangliimport android.graphics.drawable.BitmapDrawable;
30dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangliimport android.graphics.drawable.Drawable;
31dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangliimport android.os.Handler;
32dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangliimport android.support.v4.media.MediaMetadataCompat;
3324919ee8c30d91ec056cae6c4f578d7007cbe968Aurimas Liutikasimport android.support.v4.media.session.MediaControllerCompat;
34dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangliimport android.support.v4.media.session.PlaybackStateCompat;
35dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangliimport android.util.Log;
36dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
378619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.leanback.widget.PlaybackControlsRow;
388619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikas
39dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli/**
40dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli * A helper class for implementing a adapter layer for {@link MediaControllerCompat}.
41dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli */
42dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjianglipublic class MediaControllerAdapter extends PlayerAdapter {
43dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
44dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    private static final String TAG = "MediaControllerAdapter";
45dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    private static final boolean DEBUG = false;
46dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
47dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    private MediaControllerCompat mController;
48dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    private Handler mHandler = new Handler();
49dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
50dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    // Runnable object to update current media's playing position.
51dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    private final Runnable mPositionUpdaterRunnable = new Runnable() {
52dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        @Override
53dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        public void run() {
54dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            getCallback().onCurrentPositionChanged(MediaControllerAdapter.this);
55dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            mHandler.postDelayed(this, getUpdatePeriod());
56dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
57dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    };
58dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
59dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    // Update period to post runnable.
60dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    private int getUpdatePeriod() {
61dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        return 16;
62dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
63dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
64dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    private boolean mIsBuffering = false;
65dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
66dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    MediaControllerCompat.Callback mMediaControllerCallback =
67dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            new MediaControllerCompat.Callback() {
68dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                @Override
69dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                public void onPlaybackStateChanged(PlaybackStateCompat state) {
70dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                    if (mIsBuffering && state.getState() != PlaybackStateCompat.STATE_BUFFERING) {
71dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        getCallback().onBufferingStateChanged(MediaControllerAdapter.this, false);
72dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        getCallback().onBufferedPositionChanged(MediaControllerAdapter.this);
73dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        mIsBuffering = false;
74dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                    }
75dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                    if (state.getState() == PlaybackStateCompat.STATE_NONE) {
76dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        // The STATE_NONE playback state will only occurs when initialize the player
77dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        // at first time.
78dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        if (DEBUG) {
79dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                            Log.d(TAG, "Playback state is none");
80dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        }
81dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                    } else if (state.getState() == PlaybackStateCompat.STATE_STOPPED) {
82dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        // STATE_STOPPED is associated with onPlayCompleted() callback.
83dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        // STATE_STOPPED playback state will only occurs when the last item in
84dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        // play list is finished. And repeat mode is not enabled.
85dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        getCallback().onPlayCompleted(MediaControllerAdapter.this);
86dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                    } else if (state.getState() == PlaybackStateCompat.STATE_PAUSED) {
87dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        getCallback().onPlayStateChanged(MediaControllerAdapter.this);
88dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        getCallback().onCurrentPositionChanged(MediaControllerAdapter.this);
89dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                    } else if (state.getState() == PlaybackStateCompat.STATE_PLAYING) {
90dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        getCallback().onPlayStateChanged(MediaControllerAdapter.this);
91dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        getCallback().onCurrentPositionChanged(MediaControllerAdapter.this);
92dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                    } else if (state.getState() == PlaybackStateCompat.STATE_BUFFERING) {
93dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        mIsBuffering = true;
94dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        getCallback().onBufferingStateChanged(MediaControllerAdapter.this, true);
95dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        getCallback().onBufferedPositionChanged(MediaControllerAdapter.this);
96dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                    } else if (state.getState() == PlaybackStateCompat.STATE_ERROR) {
97dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        CharSequence errorMessage = state.getErrorMessage();
98dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        if (errorMessage == null) {
99dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                            getCallback().onError(MediaControllerAdapter.this, state.getErrorCode(),
100dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                                    "");
101dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        } else {
102dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                            getCallback().onError(MediaControllerAdapter.this, state.getErrorCode(),
103dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                                    state.getErrorMessage().toString());
104dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        }
105dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                    } else if (state.getState() == PlaybackStateCompat.STATE_FAST_FORWARDING) {
106dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        getCallback().onPlayStateChanged(MediaControllerAdapter.this);
107dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        getCallback().onCurrentPositionChanged(MediaControllerAdapter.this);
108dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                    } else if (state.getState() == PlaybackStateCompat.STATE_REWINDING) {
109dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        getCallback().onPlayStateChanged(MediaControllerAdapter.this);
110dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                        getCallback().onCurrentPositionChanged(MediaControllerAdapter.this);
111dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                    }
112dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                }
113dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
114dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                @Override
115dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                public void onMetadataChanged(MediaMetadataCompat metadata) {
116dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                    getCallback().onMetadataChanged(MediaControllerAdapter.this);
117dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                }
118dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            };
119dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
120dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    /**
121dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     * Constructor for the adapter using {@link MediaControllerCompat}.
122dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     *
123dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     * @param controller Object of MediaControllerCompat..
124dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     */
125dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public MediaControllerAdapter(MediaControllerCompat controller) {
126dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        if (controller == null) {
127dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            throw new NullPointerException("Object of MediaControllerCompat is null");
128dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
129dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        mController = controller;
130dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
131dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
132dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    /**
133dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     * Return the object of {@link MediaControllerCompat} from this class.
134dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     *
135dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     * @return Media Controller Compat object owned by this class.
136dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     */
137dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public MediaControllerCompat getMediaController() {
138dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        return mController;
139dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
140dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
141dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    @Override
142dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public void play() {
143dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        mController.getTransportControls().play();
144dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
145dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
146dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    @Override
147dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public void pause() {
148dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        mController.getTransportControls().pause();
149dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
150dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
151dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    @Override
152dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public void seekTo(long positionInMs) {
153dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        mController.getTransportControls().seekTo(positionInMs);
154dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
155dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
156dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    @Override
157dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public void next() {
158dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        mController.getTransportControls().skipToNext();
159dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
160dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
161dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    @Override
162dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public void previous() {
163dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        mController.getTransportControls().skipToPrevious();
164dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
165dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
166dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    @Override
167dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public void fastForward() {
168dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        mController.getTransportControls().fastForward();
169dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
170dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
171dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    @Override
172dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public void rewind() {
173dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        mController.getTransportControls().rewind();
174dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
175dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
176dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    @Override
177dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public void setRepeatAction(int repeatActionIndex) {
178dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        int repeatMode = mapRepeatActionToRepeatMode(repeatActionIndex);
179dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        mController.getTransportControls().setRepeatMode(repeatMode);
180dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
181dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
182dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    @Override
183dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public void setShuffleAction(int shuffleActionIndex) {
184dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        int shuffleMode = mapShuffleActionToShuffleMode(shuffleActionIndex);
185dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        mController.getTransportControls().setShuffleMode(shuffleMode);
186dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
187dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
188dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    @Override
189dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public boolean isPlaying() {
190dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        if (mController.getPlaybackState() == null) {
191dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            return false;
192dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
193dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        return mController.getPlaybackState().getState()
194dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                == PlaybackStateCompat.STATE_PLAYING
195dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                || mController.getPlaybackState().getState()
196dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                == PlaybackStateCompat.STATE_FAST_FORWARDING
197dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                || mController.getPlaybackState().getState() == PlaybackStateCompat.STATE_REWINDING;
198dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
199dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
200dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    @Override
201dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public long getCurrentPosition() {
202dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        if (mController.getPlaybackState() == null) {
203dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            return 0;
204dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
205dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        return mController.getPlaybackState().getPosition();
206dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
207dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
208dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    @Override
209dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public long getBufferedPosition() {
210dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        if (mController.getPlaybackState() == null) {
211dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            return 0;
212dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
213dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        return mController.getPlaybackState().getBufferedPosition();
214dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
215dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
216dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    /**
217dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     * Get current media's title.
218dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     *
219dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     * @return Title of current media.
220dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     */
221dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public CharSequence getMediaTitle() {
222dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        if (mController.getMetadata() == null) {
223dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            return "";
224dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
225dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        return mController.getMetadata().getDescription().getTitle();
226dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
227dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
228dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    /**
229dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     * Get current media's subtitle.
230dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     *
231dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     * @return Subtitle of current media.
232dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     */
233dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public CharSequence getMediaSubtitle() {
234dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        if (mController.getMetadata() == null) {
235dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            return "";
236dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
237dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        return mController.getMetadata().getDescription().getSubtitle();
238dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
239dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
240dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    /**
241dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     * Get current media's drawable art.
242dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     *
243dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     * @return Drawable art of current media.
244dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     */
245dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public Drawable getMediaArt(Context context) {
246dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        if (mController.getMetadata() == null) {
247dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            return null;
248dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
249dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        Bitmap bitmap = mController.getMetadata().getDescription().getIconBitmap();
250dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        return bitmap == null ? null : new BitmapDrawable(context.getResources(), bitmap);
251dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
252dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
253dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    @Override
254dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public long getDuration() {
255dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        if (mController.getMetadata() == null) {
256dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            return 0;
257dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
258dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        return (int) mController.getMetadata().getLong(
259dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                MediaMetadataCompat.METADATA_KEY_DURATION);
260dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
261dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
262dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    @Override
263dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public void onAttachedToHost(PlaybackGlueHost host) {
264dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        mController.registerCallback(mMediaControllerCallback);
265dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
266dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
267dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    @Override
268dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public void onDetachedFromHost() {
269dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        mController.unregisterCallback(mMediaControllerCallback);
270dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
271dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
272dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    @Override
273dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public void setProgressUpdatingEnabled(boolean enabled) {
274dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        mHandler.removeCallbacks(mPositionUpdaterRunnable);
275dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        if (!enabled) {
276dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            return;
277dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
278dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        mHandler.postDelayed(mPositionUpdaterRunnable, getUpdatePeriod());
279dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
280dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
281dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    @Override
282dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    public long getSupportedActions() {
283dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        long supportedActions = 0;
284dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        if (mController.getPlaybackState() == null) {
285dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            return supportedActions;
286dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
287dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        long actionsFromController = mController.getPlaybackState().getActions();
288dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        // Translation.
289dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        if ((actionsFromController & PlaybackStateCompat.ACTION_PLAY_PAUSE) != 0) {
290dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            supportedActions |= ACTION_PLAY_PAUSE;
291dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
292dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        if ((actionsFromController & PlaybackStateCompat.ACTION_SKIP_TO_NEXT) != 0) {
293dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            supportedActions |= ACTION_SKIP_TO_NEXT;
294dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
295dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        if ((actionsFromController & PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS) != 0) {
296dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            supportedActions |= ACTION_SKIP_TO_PREVIOUS;
297dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
298dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        if ((actionsFromController & PlaybackStateCompat.ACTION_FAST_FORWARD) != 0) {
299dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            supportedActions |= ACTION_FAST_FORWARD;
300dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
301dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        if ((actionsFromController & PlaybackStateCompat.ACTION_REWIND) != 0) {
302dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            supportedActions |= ACTION_REWIND;
303dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
304dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        if ((actionsFromController & PlaybackStateCompat.ACTION_SET_REPEAT_MODE) != 0) {
305dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            supportedActions |= ACTION_REPEAT;
306dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
307bd2d1474b96d3045aa1048e06d9debced798455bHyundo Moon        if ((actionsFromController & PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE) != 0) {
308dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            supportedActions |= ACTION_SHUFFLE;
309dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
310dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        return supportedActions;
311dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
312dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
313dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    /**
314dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     * This function will translate the index of RepeatAction in PlaybackControlsRow to
315dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     * the repeat mode which is defined by PlaybackStateCompat.
316dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     *
317dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     * @param repeatActionIndex Index of RepeatAction in PlaybackControlsRow.
318dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     * @return Repeat Mode in playback state.
319dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     */
320dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    private int mapRepeatActionToRepeatMode(int repeatActionIndex) {
321dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        switch (repeatActionIndex) {
322dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            case PlaybackControlsRow.RepeatAction.INDEX_NONE:
323dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                return PlaybackStateCompat.REPEAT_MODE_NONE;
324dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            case PlaybackControlsRow.RepeatAction.INDEX_ALL:
325dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                return PlaybackStateCompat.REPEAT_MODE_ALL;
326dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            case PlaybackControlsRow.RepeatAction.INDEX_ONE:
327dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                return PlaybackStateCompat.REPEAT_MODE_ONE;
328dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
329dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        return -1;
330dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
331dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
332dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    /**
333dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     * This function will translate the index of RepeatAction in PlaybackControlsRow to
334dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     * the repeat mode which is defined by PlaybackStateCompat.
335dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     *
336dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     * @param shuffleActionIndex Index of RepeatAction in PlaybackControlsRow.
337dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     * @return Repeat Mode in playback state.
338dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli     */
339dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    private int mapShuffleActionToShuffleMode(int shuffleActionIndex) {
340dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        switch (shuffleActionIndex) {
341dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            case PlaybackControlsRow.ShuffleAction.INDEX_OFF:
342dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                return PlaybackStateCompat.SHUFFLE_MODE_NONE;
343dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli            case PlaybackControlsRow.ShuffleAction.INDEX_ON:
344dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli                return PlaybackStateCompat.SHUFFLE_MODE_ALL;
345dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        }
346dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli        return -1;
347dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli    }
348dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli}
349dbe6c87619d7543e819e55a7cfcb05dd0a9c7266jingjiangli
350