| /* |
| * 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 androidx.leanback.media; |
| |
| import android.content.Context; |
| |
| import androidx.annotation.CallSuper; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * Base class for abstraction of media play/pause feature. A subclass of PlaybackGlue will contain |
| * implementation of Media Player or a connection to playback Service. App initializes |
| * PlaybackGlue subclass, associated it with a {@link PlaybackGlueHost}. {@link PlaybackGlueHost} |
| * is typically implemented by a Fragment or an Activity, it provides the environment to render UI |
| * for PlaybackGlue object, it optionally provides SurfaceHolder via {@link SurfaceHolderGlueHost} |
| * to render video. A typical PlaybackGlue should release resources (e.g. MediaPlayer or connection |
| * to playback Service) in {@link #onDetachedFromHost()}. |
| * {@link #onDetachedFromHost()} is called in two cases: |
| * <ul> |
| * <li> app manually change it using {@link #setHost(PlaybackGlueHost)} call</li> |
| * <li> When host (fragment or activity) is destroyed </li> |
| * </ul> |
| * In rare case if an PlaybackGlue wants to live outside fragment / activity life cycle, it may |
| * manages resource release by itself. |
| * |
| * @see PlaybackGlueHost |
| */ |
| public abstract class PlaybackGlue { |
| private final Context mContext; |
| private PlaybackGlueHost mPlaybackGlueHost; |
| |
| /** |
| * Interface to allow clients to take action once the video is ready to play and start stop. |
| */ |
| public abstract static class PlayerCallback { |
| /** |
| * Event for {@link #isPrepared()} changed. |
| * @param glue The PlaybackGlue that has changed {@link #isPrepared()}. |
| */ |
| public void onPreparedStateChanged(PlaybackGlue glue) { |
| } |
| |
| /** |
| * Event for Play/Pause state change. See {@link #isPlaying()}}. |
| * @param glue The PlaybackGlue that has changed playing or pausing state. |
| */ |
| public void onPlayStateChanged(PlaybackGlue glue) { |
| } |
| |
| /** |
| * Event of the current media is finished. |
| * @param glue The PlaybackGlue that has finished current media playing. |
| */ |
| public void onPlayCompleted(PlaybackGlue glue) { |
| } |
| } |
| |
| ArrayList<PlayerCallback> mPlayerCallbacks; |
| |
| /** |
| * Constructor. |
| */ |
| public PlaybackGlue(Context context) { |
| this.mContext = context; |
| } |
| |
| /** |
| * Returns the context. |
| */ |
| public Context getContext() { |
| return mContext; |
| } |
| |
| /** |
| * Returns true when the media player is prepared to start media playback. When returning false, |
| * app may listen to {@link PlayerCallback#onPreparedStateChanged(PlaybackGlue)} event. |
| * @return True if prepared, false otherwise. |
| */ |
| public boolean isPrepared() { |
| return true; |
| } |
| |
| /** |
| * Add a PlayerCallback. |
| * @param playerCallback The callback to add. |
| */ |
| public void addPlayerCallback(PlayerCallback playerCallback) { |
| if (mPlayerCallbacks == null) { |
| mPlayerCallbacks = new ArrayList(); |
| } |
| mPlayerCallbacks.add(playerCallback); |
| } |
| |
| /** |
| * Remove a PlayerCallback. |
| * @param callback The callback to remove. |
| */ |
| public void removePlayerCallback(PlayerCallback callback) { |
| if (mPlayerCallbacks != null) { |
| mPlayerCallbacks.remove(callback); |
| } |
| } |
| |
| /** |
| * @return A snapshot of list of PlayerCallbacks set on the Glue. |
| */ |
| protected List<PlayerCallback> getPlayerCallbacks() { |
| if (mPlayerCallbacks == null) { |
| return null; |
| } |
| return new ArrayList(mPlayerCallbacks); |
| } |
| |
| /** |
| * Returns true if media is currently playing. |
| */ |
| public boolean isPlaying() { |
| return false; |
| } |
| |
| /** |
| * Starts the media player. Does nothing if {@link #isPrepared()} is false. To wait |
| * {@link #isPrepared()} to be true before playing, use {@link #playWhenPrepared()}. |
| */ |
| public void play() { |
| } |
| |
| /** |
| * Starts play when {@link #isPrepared()} becomes true. |
| */ |
| public void playWhenPrepared() { |
| if (isPrepared()) { |
| play(); |
| } else { |
| addPlayerCallback(new PlayerCallback() { |
| @Override |
| public void onPreparedStateChanged(PlaybackGlue glue) { |
| if (glue.isPrepared()) { |
| removePlayerCallback(this); |
| play(); |
| } |
| } |
| }); |
| } |
| } |
| |
| /** |
| * Pauses the media player. |
| */ |
| public void pause() { |
| } |
| |
| /** |
| * Goes to the next media item. This method is optional. |
| */ |
| public void next() { |
| } |
| |
| /** |
| * Goes to the previous media item. This method is optional. |
| */ |
| public void previous() { |
| } |
| |
| /** |
| * This method is used to associate a PlaybackGlue with the {@link PlaybackGlueHost} which |
| * provides UI and optional {@link SurfaceHolderGlueHost}. |
| * |
| * @param host The host for the PlaybackGlue. Set to null to detach from the host. |
| */ |
| public final void setHost(PlaybackGlueHost host) { |
| if (mPlaybackGlueHost == host) { |
| return; |
| } |
| if (mPlaybackGlueHost != null) { |
| mPlaybackGlueHost.attachToGlue(null); |
| } |
| mPlaybackGlueHost = host; |
| if (mPlaybackGlueHost != null) { |
| mPlaybackGlueHost.attachToGlue(this); |
| } |
| } |
| |
| /** |
| * This method is called when {@link PlaybackGlueHost is started. Subclass may override. |
| */ |
| protected void onHostStart() { |
| } |
| |
| /** |
| * This method is called when {@link PlaybackGlueHost is stopped. Subclass may override. |
| */ |
| protected void onHostStop() { |
| } |
| |
| /** |
| * This method is called when {@link PlaybackGlueHost is resumed. Subclass may override. |
| */ |
| protected void onHostResume() { |
| } |
| |
| /** |
| * This method is called when {@link PlaybackGlueHost is paused. Subclass may override. |
| */ |
| protected void onHostPause() { |
| } |
| |
| /** |
| * This method is called attached to associated {@link PlaybackGlueHost}. Subclass may override |
| * and call super.onAttachedToHost(). |
| */ |
| @CallSuper |
| protected void onAttachedToHost(PlaybackGlueHost host) { |
| mPlaybackGlueHost = host; |
| mPlaybackGlueHost.setHostCallback(new PlaybackGlueHost.HostCallback() { |
| @Override |
| public void onHostStart() { |
| PlaybackGlue.this.onHostStart(); |
| } |
| |
| @Override |
| public void onHostStop() { |
| PlaybackGlue.this.onHostStop(); |
| } |
| |
| @Override |
| public void onHostResume() { |
| PlaybackGlue.this.onHostResume(); |
| } |
| |
| @Override |
| public void onHostPause() { |
| PlaybackGlue.this.onHostPause(); |
| } |
| |
| @Override |
| public void onHostDestroy() { |
| setHost(null); |
| } |
| }); |
| } |
| |
| /** |
| * This method is called when current associated {@link PlaybackGlueHost} is attached to a |
| * different {@link PlaybackGlue} or {@link PlaybackGlueHost} is destroyed . Subclass may |
| * override and call super.onDetachedFromHost() at last. A typical PlaybackGlue will release |
| * resources (e.g. MediaPlayer or connection to playback service) in this method. |
| */ |
| @CallSuper |
| protected void onDetachedFromHost() { |
| if (mPlaybackGlueHost != null) { |
| mPlaybackGlueHost.setHostCallback(null); |
| mPlaybackGlueHost = null; |
| } |
| } |
| |
| /** |
| * @return Associated {@link PlaybackGlueHost} or null if not attached to host. |
| */ |
| public PlaybackGlueHost getHost() { |
| return mPlaybackGlueHost; |
| } |
| } |