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