OSDN Git Service

f1ea033939f1da57b2f3cc255879baa5597332fe
[android-x86/packages-apps-Eleven.git] / src / com / cyanogenmod / eleven / loaders / TopTracksLoader.java
1 /*
2 * Copyright (C) 2014 The CyanogenMod 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.cyanogenmod.eleven.loaders;
18
19 import android.content.Context;
20 import android.database.Cursor;
21 import android.provider.BaseColumns;
22
23 import com.cyanogenmod.eleven.provider.RecentStore;
24 import com.cyanogenmod.eleven.provider.SongPlayCount;
25 import com.cyanogenmod.eleven.provider.SongPlayCount.SongPlayCountColumns;
26
27 import java.util.ArrayList;
28
29 /**
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
32  */
33 public class TopTracksLoader extends SongLoader {
34     // used for the top played results
35     public static final int NUMBER_OF_SONGS = 99;
36
37     public enum QueryType {
38         TopTracks,
39         RecentSongs,
40     }
41
42     protected QueryType mQueryType;
43
44     public TopTracksLoader(final Context context, QueryType type) {
45         super(context);
46
47         mQueryType = type;
48     }
49
50     @Override
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);
57         }
58
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);
71                     }
72                 }
73             }
74         }
75
76         return retCursor;
77     }
78
79     /**
80      * This creates a sorted cursor based on the top played results
81      * @param context Android context
82      * @return sorted cursor
83      */
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);
87
88         try {
89             return makeSortedCursor(context, songs,
90                     songs.getColumnIndex(SongPlayCountColumns.ID));
91         } finally {
92             if (songs != null) {
93                 songs.close();
94                 songs = null;
95             }
96         }
97     }
98
99     /**
100      * This creates a sorted cursor based on the recently played tracks
101      * @param context Android context
102      * @return sorted cursor
103      */
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);
107
108         try {
109             return makeSortedCursor(context, songs,
110                     songs.getColumnIndex(SongPlayCountColumns.ID));
111         } finally {
112             if (songs != null) {
113                 songs.close();
114                 songs = null;
115             }
116         }
117     }
118
119     /**
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
125      */
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 (");
133
134             // this tracks the order of the ids
135             long[] order = new long[cursor.getCount()];
136
137             long id = cursor.getLong(idColumn);
138             selection.append(id);
139             order[cursor.getPosition()] = id;
140
141             while (cursor.moveToNext()) {
142                 selection.append(",");
143
144                 id = cursor.getLong(idColumn);
145                 order[cursor.getPosition()] = id;
146                 selection.append(String.valueOf(id));
147             }
148
149             selection.append(")");
150
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);
156             }
157         }
158
159         return null;
160     }
161 }