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