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 17 package com.example.android.supportv7.media; 18 19 import android.app.PendingIntent; 20 import android.content.ComponentName; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.graphics.Bitmap; 24 import android.support.v4.media.MediaMetadataCompat; 25 import android.support.v4.media.session.MediaSessionCompat; 26 import android.support.v4.media.session.PlaybackStateCompat; 27 import android.support.v7.media.MediaControlIntent; 28 import android.support.v7.media.MediaRouter.RouteInfo; 29 import android.util.Log; 30 31 /** 32 * Abstraction of common playback operations of media items, such as play, 33 * seek, etc. Used by PlaybackManager as a backend to handle actual playback 34 * of media items. 35 */ 36 public abstract class Player { 37 private static final String TAG = "SampleMediaRoutePlayer"; 38 protected static final int STATE_IDLE = 0; 39 protected static final int STATE_PLAY_PENDING = 1; 40 protected static final int STATE_READY = 2; 41 protected static final int STATE_PLAYING = 3; 42 protected static final int STATE_PAUSED = 4; 43 44 private static final long PLAYBACK_ACTIONS = PlaybackStateCompat.ACTION_PAUSE 45 | PlaybackStateCompat.ACTION_PLAY; 46 47 protected Callback mCallback; 48 protected MediaSessionCompat mMediaSession; 49 50 public abstract boolean isRemotePlayback(); 51 public abstract boolean isQueuingSupported(); 52 53 public abstract void connect(RouteInfo route); 54 public abstract void release(); 55 56 // basic operations that are always supported 57 public abstract void play(final PlaylistItem item); 58 public abstract void seek(final PlaylistItem item); 59 public abstract void getStatus(final PlaylistItem item, final boolean update); 60 public abstract void pause(); 61 public abstract void resume(); 62 public abstract void stop(); 63 64 // advanced queuing (enqueue & remove) are only supported 65 // if isQueuingSupported() returns true 66 public abstract void enqueue(final PlaylistItem item); 67 public abstract PlaylistItem remove(String iid); 68 69 // track info for current media item 70 public void updateTrackInfo() {} 71 public String getDescription() { return ""; } 72 public Bitmap getSnapshot() { return null; } 73 74 // presentation display 75 public void updatePresentation() {} 76 77 public void setCallback(Callback callback) { 78 mCallback = callback; 79 } 80 81 public static Player create(Context context, RouteInfo route, MediaSessionCompat session) { 82 Player player; 83 if (route != null && route.supportsControlCategory( 84 MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) { 85 player = new RemotePlayer(context); 86 } else if (route != null) { 87 player = new LocalPlayer.SurfaceViewPlayer(context); 88 } else { 89 player = new LocalPlayer.OverlayPlayer(context); 90 } 91 player.initMediaSession(session); 92 player.connect(route); 93 return player; 94 } 95 96 public MediaSessionCompat getMediaSession() { 97 return mMediaSession; 98 } 99 100 protected void updateMetadata() { 101 if (mMediaSession == null) { 102 return; 103 } 104 MediaMetadataCompat.Builder bob = new MediaMetadataCompat.Builder(); 105 bob.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, getDescription()); 106 bob.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "Subtitle of the thing"); 107 bob.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_DESCRIPTION, 108 "Description of the thing"); 109 bob.putBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, getSnapshot()); 110 mMediaSession.setMetadata(bob.build()); 111 } 112 113 protected void publishState(int state) { 114 if (mMediaSession == null) { 115 return; 116 } 117 PlaybackStateCompat.Builder bob = new PlaybackStateCompat.Builder(); 118 bob.setActions(PLAYBACK_ACTIONS); 119 switch (state) { 120 case STATE_PLAYING: 121 bob.setState(PlaybackStateCompat.STATE_PLAYING, -1, 1); 122 break; 123 case STATE_READY: 124 case STATE_PAUSED: 125 bob.setState(PlaybackStateCompat.STATE_PAUSED, -1, 0); 126 break; 127 case STATE_IDLE: 128 bob.setState(PlaybackStateCompat.STATE_STOPPED, -1, 0); 129 break; 130 } 131 PlaybackStateCompat pbState = bob.build(); 132 Log.d(TAG, "Setting state to " + pbState); 133 mMediaSession.setPlaybackState(pbState); 134 if (state != STATE_IDLE) { 135 mMediaSession.setActive(true); 136 } else { 137 mMediaSession.setActive(false); 138 } 139 } 140 141 private void initMediaSession(MediaSessionCompat session) { 142 mMediaSession = session; 143 updateMetadata(); 144 } 145 146 147 public interface Callback { 148 void onError(); 149 void onCompletion(); 150 void onPlaylistChanged(); 151 void onPlaylistReady(); 152 } 153 }