1b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park/* 2b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * Copyright 2018 The Android Open Source Project 3b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * 4b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * Licensed under the Apache License, Version 2.0 (the "License"); 5b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * you may not use this file except in compliance with the License. 6b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * You may obtain a copy of the License at 7b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * 8b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * http://www.apache.org/licenses/LICENSE-2.0 9b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * 10b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * Unless required by applicable law or agreed to in writing, software 11b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * distributed under the License is distributed on an "AS IS" BASIS, 12b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * See the License for the specific language governing permissions and 14b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * limitations under the License. 15b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park */ 16b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 17b2c540ac761909e40c34bba937925814ca630c54Jin Seok Parkpackage androidx.media.widget; 18b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 19b2c540ac761909e40c34bba937925814ca630c54Jin Seok Parkimport static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 20b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 21b2c540ac761909e40c34bba937925814ca630c54Jin Seok Parkimport android.content.Context; 22b2c540ac761909e40c34bba937925814ca630c54Jin Seok Parkimport android.media.session.MediaSession; 23b2c540ac761909e40c34bba937925814ca630c54Jin Seok Parkimport android.net.Uri; 24b2c540ac761909e40c34bba937925814ca630c54Jin Seok Parkimport android.os.Build; 25b2c540ac761909e40c34bba937925814ca630c54Jin Seok Parkimport android.os.Bundle; 26b2c540ac761909e40c34bba937925814ca630c54Jin Seok Parkimport android.support.v4.media.session.PlaybackStateCompat; 27b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 28b2c540ac761909e40c34bba937925814ca630c54Jin Seok Parkimport androidx.annotation.RequiresApi; 29b2c540ac761909e40c34bba937925814ca630c54Jin Seok Parkimport androidx.annotation.RestrictTo; 30b2c540ac761909e40c34bba937925814ca630c54Jin Seok Parkimport androidx.mediarouter.media.MediaItemStatus; 31b2c540ac761909e40c34bba937925814ca630c54Jin Seok Parkimport androidx.mediarouter.media.MediaRouter; 32b2c540ac761909e40c34bba937925814ca630c54Jin Seok Parkimport androidx.mediarouter.media.MediaSessionStatus; 33b2c540ac761909e40c34bba937925814ca630c54Jin Seok Parkimport androidx.mediarouter.media.RemotePlaybackClient; 34b2c540ac761909e40c34bba937925814ca630c54Jin Seok Parkimport androidx.mediarouter.media.RemotePlaybackClient.ItemActionCallback; 35b2c540ac761909e40c34bba937925814ca630c54Jin Seok Parkimport androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback; 36b2c540ac761909e40c34bba937925814ca630c54Jin Seok Parkimport androidx.mediarouter.media.RemotePlaybackClient.StatusCallback; 37b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 38b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park/** 39b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * @hide 40b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park */ 41b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park@RestrictTo(LIBRARY_GROUP) 42b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 43b2c540ac761909e40c34bba937925814ca630c54Jin Seok Parkpublic class RoutePlayer extends MediaSession.Callback { 44b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public static final long PLAYBACK_ACTIONS = PlaybackStateCompat.ACTION_PAUSE 45b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park | PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_SEEK_TO 46b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park | PlaybackStateCompat.ACTION_FAST_FORWARD | PlaybackStateCompat.ACTION_REWIND; 47b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 48b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park private RemotePlaybackClient mClient; 49b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park private String mSessionId; 50b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park private String mItemId; 51b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park private PlayerEventCallback mCallback; 52b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 53b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park private StatusCallback mStatusCallback = new StatusCallback() { 54b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park @Override 55b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public void onItemStatusChanged(Bundle data, 56b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park String sessionId, MediaSessionStatus sessionStatus, 57b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park String itemId, MediaItemStatus itemStatus) { 58b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park updateSessionStatus(sessionId, sessionStatus); 59b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park updateItemStatus(itemId, itemStatus); 60b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 61b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park }; 62b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 63b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public RoutePlayer(Context context, MediaRouter.RouteInfo route) { 64b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park mClient = new RemotePlaybackClient(context, route); 65b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park mClient.setStatusCallback(mStatusCallback); 66b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park if (mClient.isSessionManagementSupported()) { 67b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park mClient.startSession(null, new SessionActionCallback() { 68b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park @Override 69b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public void onResult(Bundle data, 70b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park String sessionId, MediaSessionStatus sessionStatus) { 71b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park updateSessionStatus(sessionId, sessionStatus); 72b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 73b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park }); 74b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 75b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 76b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 77b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park @Override 78b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public void onPlay() { 79b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park if (mClient.isSessionManagementSupported()) { 80b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park mClient.resume(null, new SessionActionCallback() { 81b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park @Override 82b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public void onResult(Bundle data, 83b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park String sessionId, MediaSessionStatus sessionStatus) { 84b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park updateSessionStatus(sessionId, sessionStatus); 85b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 86b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park }); 87b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 88b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 89b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 90b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park @Override 91b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public void onPause() { 92b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park if (mClient.isSessionManagementSupported()) { 93b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park mClient.pause(null, new SessionActionCallback() { 94b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park @Override 95b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public void onResult(Bundle data, 96b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park String sessionId, MediaSessionStatus sessionStatus) { 97b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park updateSessionStatus(sessionId, sessionStatus); 98b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 99b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park }); 100b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 101b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 102b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 103b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park @Override 104b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public void onSeekTo(long pos) { 105b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park if (mClient.isSessionManagementSupported()) { 106b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park mClient.seek(mItemId, pos, null, new ItemActionCallback() { 107b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park @Override 108b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public void onResult(Bundle data, 109b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park String sessionId, MediaSessionStatus sessionStatus, 110b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park String itemId, MediaItemStatus itemStatus) { 111b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park updateSessionStatus(sessionId, sessionStatus); 112b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park updateItemStatus(itemId, itemStatus); 113b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 114b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park }); 115b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 116b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 117b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 118b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park @Override 119b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public void onStop() { 120b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park if (mClient.isSessionManagementSupported()) { 121b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park mClient.stop(null, new SessionActionCallback() { 122b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park @Override 123b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public void onResult(Bundle data, 124b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park String sessionId, MediaSessionStatus sessionStatus) { 125b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park updateSessionStatus(sessionId, sessionStatus); 126b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 127b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park }); 128b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 129b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 130b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 131b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park /** 132b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * Sets a callback to be notified of events for this player. 133b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * @param callback the callback to receive the events. 134b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park */ 135b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public void setPlayerEventCallback(PlayerEventCallback callback) { 136b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park mCallback = callback; 137b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 138b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 139b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park // b/77556429 140b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park// public void openVideo(DataSourceDesc dsd) { 141b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park// mClient.play(dsd.getUri(), "video/mp4", null, 0, null, new ItemActionCallback() { 142b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park// @Override 143b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park// public void onResult(Bundle data, 144b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park// String sessionId, MediaSessionStatus sessionStatus, 145b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park// String itemId, MediaItemStatus itemStatus) { 146b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park// updateSessionStatus(sessionId, sessionStatus); 147b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park// updateItemStatus(itemId, itemStatus); 148b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park// playInternal(dsd.getUri()); 149b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park// } 150b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park// }); 151b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park// } 152b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 153b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park /** 154b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * Opens the video based on the given uri and updates the media session and item statuses. 155b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * @param uri link to the video 156b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park */ 157b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public void openVideo(Uri uri) { 158b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park mClient.play(uri, "video/mp4", null, 0, null, new ItemActionCallback() { 159b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park @Override 160b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public void onResult(Bundle data, 161b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park String sessionId, MediaSessionStatus sessionStatus, 162b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park String itemId, MediaItemStatus itemStatus) { 163b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park updateSessionStatus(sessionId, sessionStatus); 164b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park updateItemStatus(itemId, itemStatus); 165b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 166b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park }); 167b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 168b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 169b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park /** 170b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * Releases the {@link RemotePlaybackClient} and {@link PlayerEventCallback} instances. 171b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park */ 172b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public void release() { 173b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park if (mClient != null) { 174b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park mClient.release(); 175b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park mClient = null; 176b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 177b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park if (mCallback != null) { 178b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park mCallback = null; 179b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 180b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 181b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 182b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park private void playInternal(Uri uri) { 183b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park mClient.play(uri, "video/mp4", null, 0, null, new ItemActionCallback() { 184b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park @Override 185b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public void onResult(Bundle data, 186b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park String sessionId, MediaSessionStatus sessionStatus, 187b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park String itemId, MediaItemStatus itemStatus) { 188b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park updateSessionStatus(sessionId, sessionStatus); 189b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park updateItemStatus(itemId, itemStatus); 190b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 191b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park }); 192b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 193b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 194b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park private void updateSessionStatus(String sessionId, MediaSessionStatus sessionStatus) { 195b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park mSessionId = sessionId; 196b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 197b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 198b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park private void updateItemStatus(String itemId, MediaItemStatus itemStatus) { 199b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park mItemId = itemId; 200b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park if (itemStatus == null || mCallback == null) return; 201b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park mCallback.onPlayerStateChanged(itemStatus); 202b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 203b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park 204b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park /** 205b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * A callback class to receive notifications for events on the route player. 206b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park */ 207b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public abstract static class PlayerEventCallback { 208b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park /** 209b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * Override to handle changes in playback state. 210b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * 211b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park * @param itemStatus The new MediaItemStatus of the RoutePlayer 212b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park */ 213b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park public void onPlayerStateChanged(MediaItemStatus itemStatus) { } 214b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park } 215b2c540ac761909e40c34bba937925814ca630c54Jin Seok Park} 216