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