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
17package com.example.android.supportv4.media.utils;
18
19import android.support.v4.media.MediaMetadataCompat;
20import android.support.v4.media.session.MediaSessionCompat;
21import android.util.Log;
22
23import com.example.android.supportv4.media.model.MusicProvider;
24
25import java.util.ArrayList;
26import java.util.Collections;
27import java.util.Iterator;
28import java.util.List;
29
30import static com.example.android.supportv4.media.utils.MediaIDHelper.MEDIA_ID_MUSICS_BY_GENRE;
31import static com.example.android.supportv4.media.utils.MediaIDHelper.MEDIA_ID_MUSICS_BY_SEARCH;
32
33/**
34 * Utility class to help on queue related tasks.
35 */
36public class QueueHelper {
37
38    private static final String TAG = "QueueHelper";
39
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
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
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
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
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     */
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
147    public static boolean isIndexPlayable(int index, List<MediaSessionCompat.QueueItem> queue) {
148        return (queue != null && index >= 0 && index < queue.size());
149    }
150}
151