Player.java revision 76d965dc41863b33f887db33d283cb7f1523f60d
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.example.android.supportv7.media; 18 19import android.content.Context; 20import android.graphics.Bitmap; 21import android.support.v4.media.MediaMetadataCompat; 22import android.support.v4.media.session.MediaSessionCompat; 23import android.support.v4.media.session.PlaybackStateCompat; 24import android.support.v7.media.MediaControlIntent; 25import android.support.v7.media.MediaRouter.RouteInfo; 26import android.util.Log; 27 28/** 29 * Abstraction of common playback operations of media items, such as play, 30 * seek, etc. Used by PlaybackManager as a backend to handle actual playback 31 * of media items. 32 * 33 * TODO: Introduce prepare() method and refactor subclasses accordingly. 34 */ 35public abstract class Player { 36 private static final String TAG = "SampleMediaRoutePlayer"; 37 protected static final int STATE_IDLE = 0; 38 protected static final int STATE_PREPARING_FOR_PLAY = 1; 39 protected static final int STATE_PREPARING_FOR_PAUSE = 2; 40 protected static final int STATE_READY = 3; 41 protected static final int STATE_PLAYING = 4; 42 protected static final int STATE_PAUSED = 5; 43 44 private static final long PLAYBACK_ACTIONS = PlaybackStateCompat.ACTION_PAUSE 45 | PlaybackStateCompat.ACTION_PLAY; 46 private static final PlaybackStateCompat INIT_PLAYBACK_STATE = new PlaybackStateCompat.Builder() 47 .setState(PlaybackStateCompat.STATE_NONE, 0, .0f).build(); 48 49 protected Callback mCallback; 50 protected MediaSessionCompat mMediaSession; 51 52 public abstract boolean isRemotePlayback(); 53 public abstract boolean isQueuingSupported(); 54 55 public abstract void connect(RouteInfo route); 56 public abstract void release(); 57 58 // basic operations that are always supported 59 public abstract void play(final PlaylistItem item); 60 public abstract void seek(final PlaylistItem item); 61 public abstract void getStatus(final PlaylistItem item, final boolean update); 62 public abstract void pause(); 63 public abstract void resume(); 64 public abstract void stop(); 65 66 // advanced queuing (enqueue & remove) are only supported 67 // if isQueuingSupported() returns true 68 public abstract void enqueue(final PlaylistItem item); 69 public abstract PlaylistItem remove(String iid); 70 71 // track info for current media item 72 public void updateTrackInfo() {} 73 public String getDescription() { return ""; } 74 public Bitmap getSnapshot() { return null; } 75 76 // presentation display 77 public void updatePresentation() {} 78 79 public void setCallback(Callback callback) { 80 mCallback = callback; 81 } 82 83 public static Player create(Context context, RouteInfo route, MediaSessionCompat session) { 84 Player player; 85 if (route != null && route.supportsControlCategory( 86 MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) { 87 player = new RemotePlayer(context); 88 } else if (route != null) { 89 player = new LocalPlayer.SurfaceViewPlayer(context); 90 } else { 91 player = new LocalPlayer.OverlayPlayer(context); 92 } 93 player.setMediaSession(session); 94 player.initMediaSession(); 95 player.connect(route); 96 return player; 97 } 98 99 protected void initMediaSession() { 100 if (mMediaSession == null) { 101 return; 102 } 103 mMediaSession.setMetadata(null); 104 mMediaSession.setPlaybackState(INIT_PLAYBACK_STATE); 105 } 106 107 protected void updateMetadata() { 108 if (mMediaSession == null) { 109 return; 110 } 111 MediaMetadataCompat.Builder bob = new MediaMetadataCompat.Builder(); 112 bob.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, getDescription()); 113 bob.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "Subtitle of the thing"); 114 bob.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_DESCRIPTION, 115 "Description of the thing"); 116 bob.putBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, getSnapshot()); 117 mMediaSession.setMetadata(bob.build()); 118 } 119 120 protected void publishState(int state) { 121 if (mMediaSession == null) { 122 return; 123 } 124 PlaybackStateCompat.Builder bob = new PlaybackStateCompat.Builder(); 125 bob.setActions(PLAYBACK_ACTIONS); 126 switch (state) { 127 case STATE_PLAYING: 128 bob.setState(PlaybackStateCompat.STATE_PLAYING, -1, 1); 129 break; 130 case STATE_READY: 131 case STATE_PAUSED: 132 bob.setState(PlaybackStateCompat.STATE_PAUSED, -1, 0); 133 break; 134 case STATE_IDLE: 135 bob.setState(PlaybackStateCompat.STATE_STOPPED, -1, 0); 136 break; 137 } 138 PlaybackStateCompat pbState = bob.build(); 139 Log.d(TAG, "Setting state to " + pbState); 140 mMediaSession.setPlaybackState(pbState); 141 if (state != STATE_IDLE) { 142 mMediaSession.setActive(true); 143 } else { 144 mMediaSession.setActive(false); 145 } 146 } 147 148 private void setMediaSession(MediaSessionCompat session) { 149 mMediaSession = session; 150 } 151 152 public interface Callback { 153 void onError(); 154 void onCompletion(); 155 void onPlaylistChanged(); 156 void onPlaylistReady(); 157 } 158} 159