blob: 730bf3a47afbf95ec02a3cdd45e5d209fb356d21 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.support.v17.leanback.media;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.util.Log;
/**
* A helper class for implementing a glue layer for {@link MediaControllerCompat}.
*/
public abstract class MediaControllerGlue extends PlaybackControlGlue {
static final String TAG = "MediaControllerGlue";
static final boolean DEBUG = false;
MediaControllerCompat mMediaController;
private final MediaControllerCompat.Callback mCallback = new MediaControllerCompat.Callback() {
@Override
public void onMetadataChanged(MediaMetadataCompat metadata) {
if (DEBUG) Log.v(TAG, "onMetadataChanged");
MediaControllerGlue.this.onMetadataChanged();
}
@Override
public void onPlaybackStateChanged(PlaybackStateCompat state) {
if (DEBUG) Log.v(TAG, "onPlaybackStateChanged");
onStateChanged();
}
@Override
public void onSessionDestroyed() {
if (DEBUG) Log.v(TAG, "onSessionDestroyed");
mMediaController = null;
}
@Override
public void onSessionEvent(String event, Bundle extras) {
if (DEBUG) Log.v(TAG, "onSessionEvent");
}
};
/**
* Constructor for the glue.
*
* @param context
* @param fastForwardSpeeds Array of seek speeds for fast forward.
* @param rewindSpeeds Array of seek speeds for rewind.
*/
public MediaControllerGlue(Context context,
int[] fastForwardSpeeds,
int[] rewindSpeeds) {
super(context, fastForwardSpeeds, rewindSpeeds);
}
/**
* Attaches to the given media controller.
*/
public void attachToMediaController(MediaControllerCompat mediaController) {
if (mediaController != mMediaController) {
if (DEBUG) Log.v(TAG, "New media controller " + mediaController);
detach();
mMediaController = mediaController;
if (mMediaController != null) {
mMediaController.registerCallback(mCallback);
}
onMetadataChanged();
onStateChanged();
}
}
/**
* Detaches from the media controller. Must be called when the object is no longer
* needed.
*/
public void detach() {
if (mMediaController != null) {
mMediaController.unregisterCallback(mCallback);
}
mMediaController = null;
}
/**
* Returns the media controller currently attached.
*/
public final MediaControllerCompat getMediaController() {
return mMediaController;
}
@Override
public boolean hasValidMedia() {
return mMediaController != null && mMediaController.getMetadata() != null;
}
@Override
public boolean isMediaPlaying() {
return mMediaController.getPlaybackState().getState() == PlaybackStateCompat.STATE_PLAYING;
}
@Override
public int getCurrentSpeedId() {
int speed = (int) mMediaController.getPlaybackState().getPlaybackSpeed();
if (speed == 0) {
return PLAYBACK_SPEED_PAUSED;
} else if (speed == 1) {
return PLAYBACK_SPEED_NORMAL;
} else if (speed > 0) {
int[] seekSpeeds = getFastForwardSpeeds();
for (int index = 0; index < seekSpeeds.length; index++) {
if (speed == seekSpeeds[index]) {
return PLAYBACK_SPEED_FAST_L0 + index;
}
}
} else {
int[] seekSpeeds = getRewindSpeeds();
for (int index = 0; index < seekSpeeds.length; index++) {
if (-speed == seekSpeeds[index]) {
return -PLAYBACK_SPEED_FAST_L0 - index;
}
}
}
Log.w(TAG, "Couldn't find index for speed " + speed);
return PLAYBACK_SPEED_INVALID;
}
@Override
public CharSequence getMediaTitle() {
return mMediaController.getMetadata().getDescription().getTitle();
}
@Override
public CharSequence getMediaSubtitle() {
return mMediaController.getMetadata().getDescription().getSubtitle();
}
@Override
public int getMediaDuration() {
return (int) mMediaController.getMetadata().getLong(
MediaMetadataCompat.METADATA_KEY_DURATION);
}
@Override
public int getCurrentPosition() {
return (int) mMediaController.getPlaybackState().getPosition();
}
@Override
public Drawable getMediaArt() {
Bitmap bitmap = mMediaController.getMetadata().getDescription().getIconBitmap();
return bitmap == null ? null : new BitmapDrawable(getContext().getResources(), bitmap);
}
@Override
public long getSupportedActions() {
long result = 0;
long actions = mMediaController.getPlaybackState().getActions();
if ((actions & PlaybackStateCompat.ACTION_PLAY_PAUSE) != 0) {
result |= ACTION_PLAY_PAUSE;
}
if ((actions & PlaybackStateCompat.ACTION_SKIP_TO_NEXT) != 0) {
result |= ACTION_SKIP_TO_NEXT;
}
if ((actions & PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS) != 0) {
result |= ACTION_SKIP_TO_PREVIOUS;
}
if ((actions & PlaybackStateCompat.ACTION_FAST_FORWARD) != 0) {
result |= ACTION_FAST_FORWARD;
}
if ((actions & PlaybackStateCompat.ACTION_REWIND) != 0) {
result |= ACTION_REWIND;
}
return result;
}
@Override
public void play(int speed) {
if (DEBUG) Log.v(TAG, "startPlayback speed " + speed);
if (speed == PLAYBACK_SPEED_NORMAL) {
mMediaController.getTransportControls().play();
} else if (speed > 0) {
mMediaController.getTransportControls().fastForward();
} else {
mMediaController.getTransportControls().rewind();
}
}
@Override
public void pause() {
if (DEBUG) Log.v(TAG, "pausePlayback");
mMediaController.getTransportControls().pause();
}
@Override
public void next() {
if (DEBUG) Log.v(TAG, "skipToNext");
mMediaController.getTransportControls().skipToNext();
}
@Override
public void previous() {
if (DEBUG) Log.v(TAG, "skipToPrevious");
mMediaController.getTransportControls().skipToPrevious();
}
}