1a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim/* 2a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * Copyright (C) 2015 The Android Open Source Project 3a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * 4a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * Licensed under the Apache License, Version 2.0 (the "License"); 5a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * you may not use this file except in compliance with the License. 6a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * You may obtain a copy of the License at 7a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * 8a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * http://www.apache.org/licenses/LICENSE-2.0 9a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * 10a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * Unless required by applicable law or agreed to in writing, software 11a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * distributed under the License is distributed on an "AS IS" BASIS, 12a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * See the License for the specific language governing permissions and 14a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * limitations under the License. 15a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim */ 16a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 17a907614755847b2630561a1e5949b2b416600d97Sungsoo Limpackage com.example.android.supportv4.media.utils; 18a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 19a907614755847b2630561a1e5949b2b416600d97Sungsoo Limimport android.support.v4.media.MediaMetadataCompat; 20a907614755847b2630561a1e5949b2b416600d97Sungsoo Limimport android.support.v4.media.session.MediaSessionCompat; 21a907614755847b2630561a1e5949b2b416600d97Sungsoo Limimport android.util.Log; 22a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 23a907614755847b2630561a1e5949b2b416600d97Sungsoo Limimport com.example.android.supportv4.media.model.MusicProvider; 24a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 25a907614755847b2630561a1e5949b2b416600d97Sungsoo Limimport java.util.ArrayList; 26a907614755847b2630561a1e5949b2b416600d97Sungsoo Limimport java.util.Collections; 27a907614755847b2630561a1e5949b2b416600d97Sungsoo Limimport java.util.Iterator; 28a907614755847b2630561a1e5949b2b416600d97Sungsoo Limimport java.util.List; 29a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 30a907614755847b2630561a1e5949b2b416600d97Sungsoo Limimport static com.example.android.supportv4.media.utils.MediaIDHelper.MEDIA_ID_MUSICS_BY_GENRE; 31a907614755847b2630561a1e5949b2b416600d97Sungsoo Limimport static com.example.android.supportv4.media.utils.MediaIDHelper.MEDIA_ID_MUSICS_BY_SEARCH; 32a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 33a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim/** 34a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * Utility class to help on queue related tasks. 35a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim */ 36a907614755847b2630561a1e5949b2b416600d97Sungsoo Limpublic class QueueHelper { 37a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 38a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim private static final String TAG = "QueueHelper"; 39a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 40a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim public static List<MediaSessionCompat.QueueItem> getPlayingQueue(String mediaId, 41a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim MusicProvider musicProvider) { 42a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 43a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim // extract the browsing hierarchy from the media ID: 44a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim String[] hierarchy = MediaIDHelper.getHierarchy(mediaId); 45a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 46a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim if (hierarchy.length != 2) { 47a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim Log.e(TAG, "Could not build a playing queue for this mediaId: " + mediaId); 48a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim return null; 49a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim } 50a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 51a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim String categoryType = hierarchy[0]; 52a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim String categoryValue = hierarchy[1]; 53a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim Log.d(TAG, "Creating playing queue for " + categoryType + ", " + categoryValue); 54a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 55a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim Iterable<MediaMetadataCompat> tracks = null; 56a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim // This sample only supports genre and by_search category types. 57a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim if (categoryType.equals(MEDIA_ID_MUSICS_BY_GENRE)) { 58a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim tracks = musicProvider.getMusicsByGenre(categoryValue); 59a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim } else if (categoryType.equals(MEDIA_ID_MUSICS_BY_SEARCH)) { 60a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim tracks = musicProvider.searchMusic(categoryValue); 61a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim } 62a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 63a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim if (tracks == null) { 64a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim Log.e(TAG, "Unrecognized category type: " + categoryType + " for mediaId " + mediaId); 65a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim return null; 66a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim } 67a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 68a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim return convertToQueue(tracks, hierarchy[0], hierarchy[1]); 69a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim } 70a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 71a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim public static List<MediaSessionCompat.QueueItem> getPlayingQueueFromSearch(String query, 72a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim MusicProvider musicProvider) { 73a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 74a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim Log.d(TAG, "Creating playing queue for musics from search " + query); 75a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 76a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim return convertToQueue(musicProvider.searchMusic(query), MEDIA_ID_MUSICS_BY_SEARCH, query); 77a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim } 78a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 79a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 80a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim public static int getMusicIndexOnQueue(Iterable<MediaSessionCompat.QueueItem> queue, 81a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim String mediaId) { 82a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim int index = 0; 83a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim for (MediaSessionCompat.QueueItem item : queue) { 84a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim if (mediaId.equals(item.getDescription().getMediaId())) { 85a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim return index; 86a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim } 87a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim index++; 88a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim } 89a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim return -1; 90a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim } 91a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 92a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim public static int getMusicIndexOnQueue(Iterable<MediaSessionCompat.QueueItem> queue, 93a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim long queueId) { 94a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim int index = 0; 95a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim for (MediaSessionCompat.QueueItem item : queue) { 96a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim if (queueId == item.getQueueId()) { 97a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim return index; 98a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim } 99a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim index++; 100a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim } 101a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim return -1; 102a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim } 103a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 104a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim private static List<MediaSessionCompat.QueueItem> convertToQueue( 105a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim Iterable<MediaMetadataCompat> tracks, String... categories) { 106a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim List<MediaSessionCompat.QueueItem> queue = new ArrayList<>(); 107a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim int count = 0; 108a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim for (MediaMetadataCompat track : tracks) { 109a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 110a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim // We create a hierarchy-aware mediaID, so we know what the queue is about by looking 111a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim // at the QueueItem media IDs. 112a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim String hierarchyAwareMediaID = MediaIDHelper.createMediaID( 113a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim track.getDescription().getMediaId(), categories); 114a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 115a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim MediaMetadataCompat trackCopy = new MediaMetadataCompat.Builder(track) 116a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim .putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, hierarchyAwareMediaID) 117a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim .build(); 118a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 119a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim // We don't expect queues to change after created, so we use the item index as the 120a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim // queueId. Any other number unique in the queue would work. 121a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim MediaSessionCompat.QueueItem item = new MediaSessionCompat.QueueItem( 122a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim trackCopy.getDescription(), count++); 123a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim queue.add(item); 124a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim } 125a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim return queue; 126a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 127a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim } 128a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 129a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim /** 130a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * Create a random queue. For simplicity sake, instead of a random queue, we create a 131a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * queue using the first genre. 132a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * 133a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * @param musicProvider the provider used for fetching music. 134a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim * @return list containing {@link android.media.session.MediaSession.QueueItem}'s 135a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim */ 136a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim public static List<MediaSessionCompat.QueueItem> getRandomQueue(MusicProvider musicProvider) { 137a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim Iterator<String> genres = musicProvider.getGenres().iterator(); 138a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim if (!genres.hasNext()) { 139a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim return Collections.emptyList(); 140a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim } 141a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim String genre = genres.next(); 142a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim Iterable<MediaMetadataCompat> tracks = musicProvider.getMusicsByGenre(genre); 143a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 144a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim return convertToQueue(tracks, MEDIA_ID_MUSICS_BY_GENRE, genre); 145a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim } 146a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim 147a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim public static boolean isIndexPlayable(int index, List<MediaSessionCompat.QueueItem> queue) { 148a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim return (queue != null && index >= 0 && index < queue.size()); 149a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim } 150a907614755847b2630561a1e5949b2b416600d97Sungsoo Lim} 151