1 /*
2  * Copyright (C) 2014 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.mediabrowserservice.utils;
18 
19 import android.media.MediaMetadata;
20 import android.media.session.MediaSession;
21 
22 import com.example.android.mediabrowserservice.model.MusicProvider;
23 
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.Iterator;
27 import java.util.List;
28 
29 import static com.example.android.mediabrowserservice.utils.MediaIDHelper.MEDIA_ID_MUSICS_BY_GENRE;
30 import static com.example.android.mediabrowserservice.utils.MediaIDHelper.MEDIA_ID_MUSICS_BY_SEARCH;
31 
32 /**
33  * Utility class to help on queue related tasks.
34  */
35 public class QueueHelper {
36 
37     private static final String TAG = LogHelper.makeLogTag(QueueHelper.class);
38 
getPlayingQueue(String mediaId, MusicProvider musicProvider)39     public static List<MediaSession.QueueItem> getPlayingQueue(String mediaId,
40             MusicProvider musicProvider) {
41 
42         // extract the browsing hierarchy from the media ID:
43         String[] hierarchy = MediaIDHelper.getHierarchy(mediaId);
44 
45         if (hierarchy.length != 2) {
46             LogHelper.e(TAG, "Could not build a playing queue for this mediaId: ", mediaId);
47             return null;
48         }
49 
50         String categoryType = hierarchy[0];
51         String categoryValue = hierarchy[1];
52         LogHelper.d(TAG, "Creating playing queue for ", categoryType, ",  ", categoryValue);
53 
54         Iterable<MediaMetadata> tracks = null;
55         // This sample only supports genre and by_search category types.
56         if (categoryType.equals(MEDIA_ID_MUSICS_BY_GENRE)) {
57             tracks = musicProvider.getMusicsByGenre(categoryValue);
58         } else if (categoryType.equals(MEDIA_ID_MUSICS_BY_SEARCH)) {
59             tracks = musicProvider.searchMusic(categoryValue);
60         }
61 
62         if (tracks == null) {
63             LogHelper.e(TAG, "Unrecognized category type: ", categoryType, " for mediaId ", mediaId);
64             return null;
65         }
66 
67         return convertToQueue(tracks, hierarchy[0], hierarchy[1]);
68     }
69 
getPlayingQueueFromSearch(String query, MusicProvider musicProvider)70     public static List<MediaSession.QueueItem> getPlayingQueueFromSearch(String query,
71             MusicProvider musicProvider) {
72 
73         LogHelper.d(TAG, "Creating playing queue for musics from search ", query);
74 
75         return convertToQueue(musicProvider.searchMusic(query), MEDIA_ID_MUSICS_BY_SEARCH, query);
76     }
77 
78 
getMusicIndexOnQueue(Iterable<MediaSession.QueueItem> queue, String mediaId)79     public static int getMusicIndexOnQueue(Iterable<MediaSession.QueueItem> queue,
80              String mediaId) {
81         int index = 0;
82         for (MediaSession.QueueItem item : queue) {
83             if (mediaId.equals(item.getDescription().getMediaId())) {
84                 return index;
85             }
86             index++;
87         }
88         return -1;
89     }
90 
getMusicIndexOnQueue(Iterable<MediaSession.QueueItem> queue, long queueId)91     public static int getMusicIndexOnQueue(Iterable<MediaSession.QueueItem> queue,
92              long queueId) {
93         int index = 0;
94         for (MediaSession.QueueItem item : queue) {
95             if (queueId == item.getQueueId()) {
96                 return index;
97             }
98             index++;
99         }
100         return -1;
101     }
102 
convertToQueue( Iterable<MediaMetadata> tracks, String... categories)103     private static List<MediaSession.QueueItem> convertToQueue(
104             Iterable<MediaMetadata> tracks, String... categories) {
105         List<MediaSession.QueueItem> queue = new ArrayList<>();
106         int count = 0;
107         for (MediaMetadata track : tracks) {
108 
109             // We create a hierarchy-aware mediaID, so we know what the queue is about by looking
110             // at the QueueItem media IDs.
111             String hierarchyAwareMediaID = MediaIDHelper.createMediaID(
112                     track.getDescription().getMediaId(), categories);
113 
114             MediaMetadata trackCopy = new MediaMetadata.Builder(track)
115                     .putString(MediaMetadata.METADATA_KEY_MEDIA_ID, hierarchyAwareMediaID)
116                     .build();
117 
118             // We don't expect queues to change after created, so we use the item index as the
119             // queueId. Any other number unique in the queue would work.
120             MediaSession.QueueItem item = new MediaSession.QueueItem(
121                     trackCopy.getDescription(), count++);
122             queue.add(item);
123         }
124         return queue;
125 
126     }
127 
128     /**
129      * Create a random queue. For simplicity sake, instead of a random queue, we create a
130      * queue using the first genre.
131      *
132      * @param musicProvider the provider used for fetching music.
133      * @return list containing {@link android.media.session.MediaSession.QueueItem}'s
134      */
getRandomQueue(MusicProvider musicProvider)135     public static List<MediaSession.QueueItem> getRandomQueue(MusicProvider musicProvider) {
136         Iterator<String> genres = musicProvider.getGenres().iterator();
137         if (!genres.hasNext()) {
138             return Collections.emptyList();
139         }
140         String genre = genres.next();
141         Iterable<MediaMetadata> tracks = musicProvider.getMusicsByGenre(genre);
142 
143         return convertToQueue(tracks, MEDIA_ID_MUSICS_BY_GENRE, genre);
144     }
145 
isIndexPlayable(int index, List<MediaSession.QueueItem> queue)146     public static boolean isIndexPlayable(int index, List<MediaSession.QueueItem> queue) {
147         return (queue != null && index >= 0 && index < queue.size());
148     }
149 }
150