1 /* 2 * Copyright 2018 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 android.media; 18 19 import android.annotation.CallbackExecutor; 20 import android.annotation.IntDef; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.media.update.ApiLoader; 24 import android.media.update.MediaPlaylistAgentProvider; 25 26 import java.lang.annotation.Retention; 27 import java.lang.annotation.RetentionPolicy; 28 import java.util.List; 29 import java.util.concurrent.Executor; 30 31 /** 32 * @hide 33 * MediaPlaylistAgent is the abstract class an application needs to derive from to pass an object 34 * to a MediaSession2 that will override default playlist handling behaviors. It contains a set of 35 * notify methods to signal MediaSession2 that playlist-related state has changed. 36 * <p> 37 * Playlists are composed of one or multiple {@link MediaItem2} instances, which combine metadata 38 * and data sources (as {@link DataSourceDesc}) 39 * Used by {@link MediaSession2} and {@link MediaController2}. 40 */ 41 // This class only includes methods that contain {@link MediaItem2}. 42 public abstract class MediaPlaylistAgent { 43 /** 44 * @hide 45 */ 46 @IntDef({REPEAT_MODE_NONE, REPEAT_MODE_ONE, REPEAT_MODE_ALL, 47 REPEAT_MODE_GROUP}) 48 @Retention(RetentionPolicy.SOURCE) 49 public @interface RepeatMode {} 50 51 /** 52 * Playback will be stopped at the end of the playing media list. 53 */ 54 public static final int REPEAT_MODE_NONE = 0; 55 56 /** 57 * Playback of the current playing media item will be repeated. 58 */ 59 public static final int REPEAT_MODE_ONE = 1; 60 61 /** 62 * Playing media list will be repeated. 63 */ 64 public static final int REPEAT_MODE_ALL = 2; 65 66 /** 67 * Playback of the playing media group will be repeated. 68 * A group is a logical block of media items which is specified in the section 5.7 of the 69 * Bluetooth AVRCP 1.6. An example of a group is the playlist. 70 */ 71 public static final int REPEAT_MODE_GROUP = 3; 72 73 /** 74 * @hide 75 */ 76 @IntDef({SHUFFLE_MODE_NONE, SHUFFLE_MODE_ALL, SHUFFLE_MODE_GROUP}) 77 @Retention(RetentionPolicy.SOURCE) 78 public @interface ShuffleMode {} 79 80 /** 81 * Media list will be played in order. 82 */ 83 public static final int SHUFFLE_MODE_NONE = 0; 84 85 /** 86 * Media list will be played in shuffled order. 87 */ 88 public static final int SHUFFLE_MODE_ALL = 1; 89 90 /** 91 * Media group will be played in shuffled order. 92 * A group is a logical block of media items which is specified in the section 5.7 of the 93 * Bluetooth AVRCP 1.6. An example of a group is the playlist. 94 */ 95 public static final int SHUFFLE_MODE_GROUP = 2; 96 97 private final MediaPlaylistAgentProvider mProvider; 98 99 /** 100 * A callback class to receive notifications for events on the media player. See 101 * {@link MediaPlaylistAgent#registerPlaylistEventCallback(Executor, PlaylistEventCallback)} 102 * to register this callback. 103 */ 104 public static abstract class PlaylistEventCallback { 105 /** 106 * Called when a playlist is changed. 107 * 108 * @param playlistAgent playlist agent for this event 109 * @param list new playlist 110 * @param metadata new metadata 111 */ 112 public void onPlaylistChanged(@NonNull MediaPlaylistAgent playlistAgent, 113 @NonNull List<MediaItem2> list, @Nullable MediaMetadata2 metadata) { } 114 115 /** 116 * Called when a playlist metadata is changed. 117 * 118 * @param playlistAgent playlist agent for this event 119 * @param metadata new metadata 120 */ 121 public void onPlaylistMetadataChanged(@NonNull MediaPlaylistAgent playlistAgent, 122 @Nullable MediaMetadata2 metadata) { } 123 124 /** 125 * Called when the shuffle mode is changed. 126 * 127 * @param playlistAgent playlist agent for this event 128 * @param shuffleMode repeat mode 129 * @see #SHUFFLE_MODE_NONE 130 * @see #SHUFFLE_MODE_ALL 131 * @see #SHUFFLE_MODE_GROUP 132 */ 133 public void onShuffleModeChanged(@NonNull MediaPlaylistAgent playlistAgent, 134 @ShuffleMode int shuffleMode) { } 135 136 /** 137 * Called when the repeat mode is changed. 138 * 139 * @param playlistAgent playlist agent for this event 140 * @param repeatMode repeat mode 141 * @see #REPEAT_MODE_NONE 142 * @see #REPEAT_MODE_ONE 143 * @see #REPEAT_MODE_ALL 144 * @see #REPEAT_MODE_GROUP 145 */ 146 public void onRepeatModeChanged(@NonNull MediaPlaylistAgent playlistAgent, 147 @RepeatMode int repeatMode) { } 148 } 149 150 public MediaPlaylistAgent() { 151 mProvider = ApiLoader.getProvider().createMediaPlaylistAgent(this); 152 } 153 154 /** 155 * Register {@link PlaylistEventCallback} to listen changes in the underlying 156 * {@link MediaPlaylistAgent}. 157 * 158 * @param executor a callback Executor 159 * @param callback a PlaylistEventCallback 160 * @throws IllegalArgumentException if executor or callback is {@code null}. 161 */ 162 public final void registerPlaylistEventCallback( 163 @NonNull @CallbackExecutor Executor executor, @NonNull PlaylistEventCallback callback) { 164 mProvider.registerPlaylistEventCallback_impl(executor, callback); 165 } 166 167 /** 168 * Unregister the previously registered {@link PlaylistEventCallback}. 169 * 170 * @param callback the callback to be removed 171 * @throws IllegalArgumentException if the callback is {@code null}. 172 */ 173 public final void unregisterPlaylistEventCallback(@NonNull PlaylistEventCallback callback) { 174 mProvider.unregisterPlaylistEventCallback_impl(callback); 175 } 176 177 public final void notifyPlaylistChanged() { 178 mProvider.notifyPlaylistChanged_impl(); 179 } 180 181 public final void notifyPlaylistMetadataChanged() { 182 mProvider.notifyPlaylistMetadataChanged_impl(); 183 } 184 185 public final void notifyShuffleModeChanged() { 186 mProvider.notifyShuffleModeChanged_impl(); 187 } 188 189 public final void notifyRepeatModeChanged() { 190 mProvider.notifyRepeatModeChanged_impl(); 191 } 192 193 /** 194 * Returns the playlist 195 * 196 * @return playlist, or null if none is set. 197 */ 198 public @Nullable List<MediaItem2> getPlaylist() { 199 return mProvider.getPlaylist_impl(); 200 } 201 202 /** 203 * Sets the playlist. 204 * 205 * @param list playlist 206 * @param metadata metadata of the playlist 207 */ 208 public void setPlaylist(@NonNull List<MediaItem2> list, @Nullable MediaMetadata2 metadata) { 209 mProvider.setPlaylist_impl(list, metadata); 210 } 211 212 /** 213 * Returns the playlist metadata 214 * 215 * @return metadata metadata of the playlist, or null if none is set 216 */ 217 public @Nullable MediaMetadata2 getPlaylistMetadata() { 218 return mProvider.getPlaylistMetadata_impl(); 219 } 220 221 /** 222 * Updates the playlist metadata 223 * 224 * @param metadata metadata of the playlist 225 */ 226 public void updatePlaylistMetadata(@Nullable MediaMetadata2 metadata) { 227 mProvider.updatePlaylistMetadata_impl(metadata); 228 } 229 230 /** 231 * Adds the media item to the playlist at position index. Index equals or greater than 232 * the current playlist size will add the item at the end of the playlist. 233 * <p> 234 * This will not change the currently playing media item. 235 * If index is less than or equal to the current index of the playlist, 236 * the current index of the playlist will be incremented correspondingly. 237 * 238 * @param index the index you want to add 239 * @param item the media item you want to add 240 */ 241 public void addPlaylistItem(int index, @NonNull MediaItem2 item) { 242 mProvider.addPlaylistItem_impl(index, item); 243 } 244 245 /** 246 * Removes the media item from the playlist 247 * 248 * @param item media item to remove 249 */ 250 public void removePlaylistItem(@NonNull MediaItem2 item) { 251 mProvider.removePlaylistItem_impl(item); 252 } 253 254 /** 255 * Replace the media item at index in the playlist. This can be also used to update metadata of 256 * an item. 257 * 258 * @param index the index of the item to replace 259 * @param item the new item 260 */ 261 public void replacePlaylistItem(int index, @NonNull MediaItem2 item) { 262 mProvider.replacePlaylistItem_impl(index, item); 263 } 264 265 /** 266 * Skips to the the media item, and plays from it. 267 * 268 * @param item media item to start playing from 269 */ 270 public void skipToPlaylistItem(@NonNull MediaItem2 item) { 271 mProvider.skipToPlaylistItem_impl(item); 272 } 273 274 /** 275 * Skips to the previous item in the playlist. 276 */ 277 public void skipToPreviousItem() { 278 mProvider.skipToPreviousItem_impl(); 279 } 280 281 /** 282 * Skips to the next item in the playlist. 283 */ 284 public void skipToNextItem() { 285 mProvider.skipToNextItem_impl(); 286 } 287 288 /** 289 * Gets the repeat mode 290 * 291 * @return repeat mode 292 * @see #REPEAT_MODE_NONE 293 * @see #REPEAT_MODE_ONE 294 * @see #REPEAT_MODE_ALL 295 * @see #REPEAT_MODE_GROUP 296 */ 297 public @RepeatMode int getRepeatMode() { 298 return mProvider.getRepeatMode_impl(); 299 } 300 301 /** 302 * Sets the repeat mode 303 * 304 * @param repeatMode repeat mode 305 * @see #REPEAT_MODE_NONE 306 * @see #REPEAT_MODE_ONE 307 * @see #REPEAT_MODE_ALL 308 * @see #REPEAT_MODE_GROUP 309 */ 310 public void setRepeatMode(@RepeatMode int repeatMode) { 311 mProvider.setRepeatMode_impl(repeatMode); 312 } 313 314 /** 315 * Gets the shuffle mode 316 * 317 * @return The shuffle mode 318 * @see #SHUFFLE_MODE_NONE 319 * @see #SHUFFLE_MODE_ALL 320 * @see #SHUFFLE_MODE_GROUP 321 */ 322 public @ShuffleMode int getShuffleMode() { 323 return mProvider.getShuffleMode_impl(); 324 } 325 326 /** 327 * Sets the shuffle mode 328 * 329 * @param shuffleMode The shuffle mode 330 * @see #SHUFFLE_MODE_NONE 331 * @see #SHUFFLE_MODE_ALL 332 * @see #SHUFFLE_MODE_GROUP 333 */ 334 public void setShuffleMode(@ShuffleMode int shuffleMode) { 335 mProvider.setShuffleMode_impl(shuffleMode); 336 } 337 338 /** 339 * Called by {@link MediaSession2} when it wants to translate {@link DataSourceDesc} from the 340 * {@link MediaPlayerBase.PlayerEventCallback} to the {@link MediaItem2}. Override this method 341 * if you want to create {@link DataSourceDesc}s dynamically, instead of specifying them with 342 * {@link #setPlaylist(List, MediaMetadata2)}. 343 * <p> 344 * Session would throw an exception if this returns {@code null} for {@param dsd} from the 345 * {@link MediaPlayerBase.PlayerEventCallback}. 346 * <p> 347 * Default implementation calls the {@link #getPlaylist()} and searches the {@link MediaItem2} 348 * with the {@param dsd}. 349 * 350 * @param dsd The dsd to query. 351 * @return A {@link MediaItem2} object in the playlist that matches given {@code dsd}. 352 * @throws IllegalArgumentException if {@code dsd} is null 353 */ 354 public @Nullable MediaItem2 getMediaItem(@NonNull DataSourceDesc dsd) { 355 return mProvider.getMediaItem_impl(dsd); 356 } 357 } 358