2 * Copyright (C) 2014 The CyanogenMod Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.cyanogenmod.eleven.loaders;
19 import android.content.Context;
20 import android.database.Cursor;
21 import android.provider.BaseColumns;
23 import com.cyanogenmod.eleven.provider.RecentStore;
24 import com.cyanogenmod.eleven.provider.SongPlayCount;
25 import com.cyanogenmod.eleven.provider.SongPlayCount.SongPlayCountColumns;
27 import java.util.ArrayList;
30 * Used to query {@link android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI} and return
31 * a sorted list of songs based on either the TopTracks or the RecentSongs
33 public class TopTracksLoader extends SongLoader {
34 // used for the top played results
35 public static final int NUMBER_OF_SONGS = 99;
37 public enum QueryType {
42 protected QueryType mQueryType;
44 public TopTracksLoader(final Context context, QueryType type) {
51 protected Cursor getCursor() {
52 SortedCursor retCursor = null;
53 if (mQueryType == QueryType.TopTracks) {
54 retCursor = makeTopTracksCursor(mContext);
55 } else if (mQueryType == QueryType.RecentSongs) {
56 retCursor = makeRecentTracksCursor(mContext);
59 // clean up the databases with any ids not found
60 if (retCursor != null) {
61 ArrayList<Long> missingIds = retCursor.getMissingIds();
62 if (missingIds != null && missingIds.size() > 0) {
63 // for each unfound id, remove it from the database
64 // this codepath should only really be hit if the user removes songs
65 // outside of the Eleven app
66 for (long id : missingIds) {
67 if (mQueryType == QueryType.TopTracks) {
68 SongPlayCount.getInstance(mContext).removeItem(id);
69 } else if (mQueryType == QueryType.RecentSongs) {
70 RecentStore.getInstance(mContext).removeItem(id);
80 * This creates a sorted cursor based on the top played results
81 * @param context Android context
82 * @return sorted cursor
84 public static final SortedCursor makeTopTracksCursor(final Context context) {
85 // first get the top results ids from the internal database
86 Cursor songs = SongPlayCount.getInstance(context).getTopPlayedResults(NUMBER_OF_SONGS);
89 return makeSortedCursor(context, songs,
90 songs.getColumnIndex(SongPlayCountColumns.ID));
100 * This creates a sorted cursor based on the recently played tracks
101 * @param context Android context
102 * @return sorted cursor
104 public static final SortedCursor makeRecentTracksCursor(final Context context) {
105 // first get the top results ids from the internal database
106 Cursor songs = RecentStore.getInstance(context).queryRecentIds(null);
109 return makeSortedCursor(context, songs,
110 songs.getColumnIndex(SongPlayCountColumns.ID));
120 * This creates a sorted song cursor given a cursor that contains the sort order
121 * @param context Android context
122 * @param cursor This is the cursor used to determine the order of the ids
123 * @param idColumn the id column index of the cursor
124 * @return a Sorted Cursor of songs
126 public static final SortedCursor makeSortedCursor(final Context context, final Cursor cursor,
127 final int idColumn) {
128 if (cursor != null && cursor.moveToFirst()) {
129 // create the list of ids to select against
130 StringBuilder selection = new StringBuilder();
131 selection.append(BaseColumns._ID);
132 selection.append(" IN (");
134 // this tracks the order of the ids
135 long[] order = new long[cursor.getCount()];
137 long id = cursor.getLong(idColumn);
138 selection.append(id);
139 order[cursor.getPosition()] = id;
141 while (cursor.moveToNext()) {
142 selection.append(",");
144 id = cursor.getLong(idColumn);
145 order[cursor.getPosition()] = id;
146 selection.append(String.valueOf(id));
149 selection.append(")");
151 // get a list of songs with the data given the selection statement
152 Cursor songCursor = makeSongCursor(context, selection.toString(), false);
153 if (songCursor != null) {
154 // now return the wrapped TopTracksCursor to handle sorting given order
155 return new SortedCursor(songCursor, order, BaseColumns._ID, null);