Home | History | Annotate | Download | only in leanback
      1 /* This file is auto-generated from PlaybackControlHelper.java.  DO NOT MODIFY. */
      2 
      3 /*
      4  * Copyright (C) 2015 The Android Open Source Project
      5  *
      6  * Licensed under the Apache License, Version 2.0 (the "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *      http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License
     17  */
     18 
     19 package com.example.android.leanback;
     20 
     21 import android.content.Context;
     22 import android.graphics.drawable.Drawable;
     23 import android.os.Handler;
     24 import android.support.v17.leanback.app.PlaybackControlSupportGlue;
     25 import android.support.v17.leanback.widget.Action;
     26 import android.support.v17.leanback.widget.ArrayObjectAdapter;
     27 import android.support.v17.leanback.widget.ControlButtonPresenterSelector;
     28 import android.support.v17.leanback.widget.PlaybackControlsRow;
     29 import android.support.v17.leanback.widget.PlaybackControlsRowPresenter;
     30 import android.support.v17.leanback.widget.PresenterSelector;
     31 import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
     32 import android.view.KeyEvent;
     33 import android.view.View;
     34 import android.widget.Toast;
     35 
     36 abstract class PlaybackControlSupportHelper extends PlaybackControlSupportGlue {
     37     /**
     38      * Change the location of the thumbs up/down controls
     39      */
     40     private static final boolean THUMBS_PRIMARY = true;
     41 
     42     private static final String FAUX_TITLE = "A short song of silence";
     43     private static final String FAUX_SUBTITLE = "2014";
     44     private static final int FAUX_DURATION = 33 * 1000;
     45 
     46     // These should match the playback service FF behavior
     47     private static int[] sFastForwardSpeeds = { 2, 3, 4, 5 };
     48 
     49     private boolean mIsPlaying;
     50     private int mSpeed = PlaybackControlSupportGlue.PLAYBACK_SPEED_PAUSED;
     51     private long mStartTime;
     52     private long mStartPosition = 0;
     53 
     54     private PlaybackControlsRow.RepeatAction mRepeatAction;
     55     private PlaybackControlsRow.ThumbsUpAction mThumbsUpAction;
     56     private PlaybackControlsRow.ThumbsDownAction mThumbsDownAction;
     57     private PlaybackControlsRow.PictureInPictureAction mPipAction;
     58 
     59     private Handler mHandler = new Handler();
     60     private final Runnable mUpdateProgressRunnable = new Runnable() {
     61         @Override
     62         public void run() {
     63             updateProgress();
     64             mHandler.postDelayed(this, getUpdatePeriod());
     65         }
     66     };
     67 
     68     public PlaybackControlSupportHelper(Context context, PlaybackOverlaySupportFragment fragment) {
     69         super(context, fragment, sFastForwardSpeeds);
     70         mThumbsUpAction = new PlaybackControlsRow.ThumbsUpAction(context);
     71         mThumbsUpAction.setIndex(PlaybackControlsRow.ThumbsUpAction.OUTLINE);
     72         mThumbsDownAction = new PlaybackControlsRow.ThumbsDownAction(context);
     73         mThumbsDownAction.setIndex(PlaybackControlsRow.ThumbsDownAction.OUTLINE);
     74         mRepeatAction = new PlaybackControlsRow.RepeatAction(context);
     75         mPipAction = new PlaybackControlsRow.PictureInPictureAction(context);
     76     }
     77 
     78     @Override
     79     public PlaybackControlsRowPresenter createControlsRowAndPresenter() {
     80         PlaybackControlsRowPresenter presenter = super.createControlsRowAndPresenter();
     81 
     82         ArrayObjectAdapter adapter = new ArrayObjectAdapter(new ControlButtonPresenterSelector());
     83         getControlsRow().setSecondaryActionsAdapter(adapter);
     84         if (!THUMBS_PRIMARY) {
     85             adapter.add(mThumbsDownAction);
     86         }
     87         if (android.os.Build.VERSION.SDK_INT > 23) {
     88             adapter.add(mPipAction);
     89         }
     90         adapter.add(mRepeatAction);
     91         if (!THUMBS_PRIMARY) {
     92             adapter.add(mThumbsUpAction);
     93         }
     94 
     95         return presenter;
     96     }
     97 
     98     @Override
     99     protected SparseArrayObjectAdapter createPrimaryActionsAdapter(
    100             PresenterSelector presenterSelector) {
    101         SparseArrayObjectAdapter adapter = new SparseArrayObjectAdapter(presenterSelector);
    102         if (THUMBS_PRIMARY) {
    103             adapter.set(PlaybackControlSupportGlue.ACTION_CUSTOM_LEFT_FIRST, mThumbsUpAction);
    104             adapter.set(PlaybackControlSupportGlue.ACTION_CUSTOM_RIGHT_FIRST, mThumbsDownAction);
    105         }
    106         return adapter;
    107     }
    108 
    109     @Override
    110     public void onActionClicked(Action action) {
    111         if (shouldDispatchAction(action)) {
    112             dispatchAction(action);
    113             return;
    114         }
    115         super.onActionClicked(action);
    116     }
    117 
    118     @Override
    119     public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
    120         if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
    121             Action action = getControlsRow().getActionForKeyCode(keyEvent.getKeyCode());
    122             if (shouldDispatchAction(action)) {
    123                 dispatchAction(action);
    124                 return true;
    125             }
    126         }
    127         return super.onKey(view, keyCode, keyEvent);
    128     }
    129 
    130     private boolean shouldDispatchAction(Action action) {
    131         return action == mRepeatAction || action == mThumbsUpAction || action == mThumbsDownAction;
    132     }
    133 
    134     private void dispatchAction(Action action) {
    135         Toast.makeText(getContext(), action.toString(), Toast.LENGTH_SHORT).show();
    136         PlaybackControlsRow.MultiAction multiAction = (PlaybackControlsRow.MultiAction) action;
    137         multiAction.nextIndex();
    138         notifyActionChanged(multiAction);
    139     }
    140 
    141     private void notifyActionChanged(PlaybackControlsRow.MultiAction action) {
    142         int index;
    143         index = getPrimaryActionsAdapter().indexOf(action);
    144         if (index >= 0) {
    145             getPrimaryActionsAdapter().notifyArrayItemRangeChanged(index, 1);
    146         } else {
    147             index = getSecondaryActionsAdapter().indexOf(action);
    148             if (index >= 0) {
    149                 getSecondaryActionsAdapter().notifyArrayItemRangeChanged(index, 1);
    150             }
    151         }
    152     }
    153 
    154     private SparseArrayObjectAdapter getPrimaryActionsAdapter() {
    155         return (SparseArrayObjectAdapter) getControlsRow().getPrimaryActionsAdapter();
    156     }
    157 
    158     private ArrayObjectAdapter getSecondaryActionsAdapter() {
    159         return (ArrayObjectAdapter) getControlsRow().getSecondaryActionsAdapter();
    160     }
    161 
    162     @Override
    163     public boolean hasValidMedia() {
    164         return true;
    165     }
    166 
    167     @Override
    168     public boolean isMediaPlaying() {
    169         return mIsPlaying;
    170     }
    171 
    172     @Override
    173     public CharSequence getMediaTitle() {
    174         return FAUX_TITLE;
    175     }
    176 
    177     @Override
    178     public CharSequence getMediaSubtitle() {
    179         return FAUX_SUBTITLE;
    180     }
    181 
    182     @Override
    183     public int getMediaDuration() {
    184         return FAUX_DURATION;
    185     }
    186 
    187     @Override
    188     public Drawable getMediaArt() {
    189         return null;
    190     }
    191 
    192     @Override
    193     public long getSupportedActions() {
    194         return PlaybackControlSupportGlue.ACTION_PLAY_PAUSE |
    195                 PlaybackControlSupportGlue.ACTION_FAST_FORWARD |
    196                 PlaybackControlSupportGlue.ACTION_REWIND;
    197     }
    198 
    199     @Override
    200     public int getCurrentSpeedId() {
    201         return mSpeed;
    202     }
    203 
    204     @Override
    205     public int getCurrentPosition() {
    206         int speed;
    207         if (mSpeed == PlaybackControlSupportGlue.PLAYBACK_SPEED_PAUSED) {
    208             speed = 0;
    209         } else if (mSpeed == PlaybackControlSupportGlue.PLAYBACK_SPEED_NORMAL) {
    210             speed = 1;
    211         } else if (mSpeed >= PlaybackControlSupportGlue.PLAYBACK_SPEED_FAST_L0) {
    212             int index = mSpeed - PlaybackControlSupportGlue.PLAYBACK_SPEED_FAST_L0;
    213             speed = getFastForwardSpeeds()[index];
    214         } else if (mSpeed <= -PlaybackControlSupportGlue.PLAYBACK_SPEED_FAST_L0) {
    215             int index = -mSpeed - PlaybackControlSupportGlue.PLAYBACK_SPEED_FAST_L0;
    216             speed = -getRewindSpeeds()[index];
    217         } else {
    218             return -1;
    219         }
    220         long position = mStartPosition +
    221                 (System.currentTimeMillis() - mStartTime) * speed;
    222         if (position > getMediaDuration()) {
    223             position = getMediaDuration();
    224             onPlaybackComplete(true);
    225         } else if (position < 0) {
    226             position = 0;
    227             onPlaybackComplete(false);
    228         }
    229         return (int) position;
    230     }
    231 
    232     void onPlaybackComplete(final boolean ended) {
    233         mHandler.post(new Runnable() {
    234             @Override
    235             public void run() {
    236                 if (mRepeatAction.getIndex() == PlaybackControlsRow.RepeatAction.NONE) {
    237                     pausePlayback();
    238                 } else {
    239                     startPlayback(PlaybackControlSupportGlue.PLAYBACK_SPEED_NORMAL);
    240                 }
    241                 mStartPosition = 0;
    242                 onStateChanged();
    243             }
    244         });
    245     }
    246 
    247     @Override
    248     protected void startPlayback(int speed) {
    249         if (speed == mSpeed) {
    250             return;
    251         }
    252         mStartPosition = getCurrentPosition();
    253         mSpeed = speed;
    254         mIsPlaying = true;
    255         mStartTime = System.currentTimeMillis();
    256     }
    257 
    258     @Override
    259     protected void pausePlayback() {
    260         if (mSpeed == PlaybackControlSupportGlue.PLAYBACK_SPEED_PAUSED) {
    261             return;
    262         }
    263         mStartPosition = getCurrentPosition();
    264         mSpeed = PlaybackControlSupportGlue.PLAYBACK_SPEED_PAUSED;
    265         mIsPlaying = false;
    266     }
    267 
    268     @Override
    269     protected void skipToNext() {
    270         // Not supported
    271     }
    272 
    273     @Override
    274     protected void skipToPrevious() {
    275         // Not supported
    276     }
    277 
    278     @Override
    279     public void enableProgressUpdating(boolean enable) {
    280         mHandler.removeCallbacks(mUpdateProgressRunnable);
    281         if (enable) {
    282             mUpdateProgressRunnable.run();
    283         }
    284     }
    285 };
    286