OSDN Git Service

5061d2850e8e59ab44f95ba4abdc6d89b4e5514f
[android-x86/packages-apps-Eleven.git] / src / org / lineageos / eleven / loaders / NowPlayingCursor.java
1
2 package org.lineageos.eleven.loaders;
3
4 import static org.lineageos.eleven.utils.MusicUtils.mService;
5
6 import android.annotation.SuppressLint;
7 import android.content.Context;
8 import android.database.AbstractCursor;
9 import android.database.Cursor;
10 import android.os.RemoteException;
11 import android.provider.BaseColumns;
12 import android.provider.MediaStore;
13 import android.provider.MediaStore.Audio.AudioColumns;
14
15 import org.lineageos.eleven.utils.MusicUtils;
16
17 import java.util.Arrays;
18
19 /**
20  * A custom {@link Cursor} used to return the queue and allow for easy dragging
21  * and dropping of the items in it.
22  */
23 @SuppressLint("NewApi")
24 public class NowPlayingCursor extends AbstractCursor {
25
26     private static final String[] PROJECTION = new String[] {
27             /* 0 */
28             BaseColumns._ID,
29             /* 1 */
30             AudioColumns.TITLE,
31             /* 2 */
32             AudioColumns.ARTIST,
33             /* 3 */
34             AudioColumns.ALBUM_ID,
35             /* 4 */
36             AudioColumns.ALBUM,
37             /* 5 */
38             AudioColumns.DURATION,
39             /* 6 */
40             AudioColumns.YEAR,
41     };
42
43     private final Context mContext;
44
45     private long[] mNowPlaying;
46
47     private long[] mCursorIndexes;
48
49     private int mSize;
50
51     private int mCurPos;
52
53     private Cursor mQueueCursor;
54
55     /**
56      * Constructor of <code>NowPlayingCursor</code>
57      *
58      * @param context The {@link Context} to use
59      */
60     public NowPlayingCursor(final Context context) {
61         mContext = context;
62         makeNowPlayingCursor();
63     }
64
65     /**
66      * {@inheritDoc}
67      */
68     @Override
69     public int getCount() {
70         return mSize;
71     }
72
73     /**
74      * {@inheritDoc}
75      */
76     @Override
77     public boolean onMove(final int oldPosition, final int newPosition) {
78         if (oldPosition == newPosition) {
79             return true;
80         }
81
82         if (mNowPlaying == null || mCursorIndexes == null || newPosition >= mNowPlaying.length) {
83             return false;
84         }
85
86         final long id = mNowPlaying[newPosition];
87         final int cursorIndex = Arrays.binarySearch(mCursorIndexes, id);
88         mQueueCursor.moveToPosition(cursorIndex);
89         mCurPos = newPosition;
90         return true;
91     }
92
93     /**
94      * {@inheritDoc}
95      */
96     @Override
97     public String getString(final int column) {
98         try {
99             return mQueueCursor.getString(column);
100         } catch (final Exception ignored) {
101             onChange(true);
102             return "";
103         }
104     }
105
106     /**
107      * {@inheritDoc}
108      */
109     @Override
110     public short getShort(final int column) {
111         return mQueueCursor.getShort(column);
112     }
113
114     /**
115      * {@inheritDoc}
116      */
117     @Override
118     public int getInt(final int column) {
119         try {
120             return mQueueCursor.getInt(column);
121         } catch (final Exception ignored) {
122             onChange(true);
123             return 0;
124         }
125     }
126
127     /**
128      * {@inheritDoc}
129      */
130     @Override
131     public long getLong(final int column) {
132         try {
133             return mQueueCursor.getLong(column);
134         } catch (final Exception ignored) {
135             onChange(true);
136             return 0;
137         }
138     }
139
140     /**
141      * {@inheritDoc}
142      */
143     @Override
144     public float getFloat(final int column) {
145         return mQueueCursor.getFloat(column);
146     }
147
148     /**
149      * {@inheritDoc}
150      */
151     @Override
152     public double getDouble(final int column) {
153         return mQueueCursor.getDouble(column);
154     }
155
156     /**
157      * {@inheritDoc}
158      */
159     @Override
160     public int getType(final int column) {
161         return mQueueCursor.getType(column);
162     }
163
164     /**
165      * {@inheritDoc}
166      */
167     @Override
168     public boolean isNull(final int column) {
169         return mQueueCursor.isNull(column);
170     }
171
172     /**
173      * {@inheritDoc}
174      */
175     @Override
176     public String[] getColumnNames() {
177         return PROJECTION;
178     }
179
180     /**
181      * {@inheritDoc}
182      */
183     @SuppressWarnings("deprecation")
184     @Override
185     public void deactivate() {
186         if (mQueueCursor != null) {
187             mQueueCursor.deactivate();
188         }
189     }
190
191     /**
192      * {@inheritDoc}
193      */
194     @Override
195     public boolean requery() {
196         makeNowPlayingCursor();
197         return true;
198     }
199
200     /**
201      * {@inheritDoc}
202      */
203     @Override
204     public void close() {
205         try {
206             if (mQueueCursor != null) {
207                 mQueueCursor.close();
208                 mQueueCursor = null;
209             }
210         } catch (final Exception close) {
211         }
212         super.close();
213     };
214
215     /**
216      * Actually makes the queue
217      */
218     private void makeNowPlayingCursor() {
219         mQueueCursor = null;
220         mNowPlaying = MusicUtils.getQueue();
221         mSize = mNowPlaying.length;
222         if (mSize == 0) {
223             return;
224         }
225
226         final StringBuilder selection = new StringBuilder();
227         selection.append(MediaStore.Audio.Media._ID + " IN (");
228         for (int i = 0; i < mSize; i++) {
229             selection.append(mNowPlaying[i]);
230             if (i < mSize - 1) {
231                 selection.append(",");
232             }
233         }
234         selection.append(")");
235
236         mQueueCursor = mContext.getContentResolver().query(
237                 MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, PROJECTION, selection.toString(),
238                 null, MediaStore.Audio.Media._ID);
239
240         if (mQueueCursor == null) {
241             mSize = 0;
242             return;
243         }
244
245         final int playlistSize = mQueueCursor.getCount();
246         mCursorIndexes = new long[playlistSize];
247         mQueueCursor.moveToFirst();
248         final int columnIndex = mQueueCursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID);
249         for (int i = 0; i < playlistSize; i++) {
250             mCursorIndexes[i] = mQueueCursor.getLong(columnIndex);
251             mQueueCursor.moveToNext();
252         }
253         mQueueCursor.moveToFirst();
254         mCurPos = -1;
255
256         int removed = 0;
257         for (int i = mNowPlaying.length - 1; i >= 0; i--) {
258             final long trackId = mNowPlaying[i];
259             final int cursorIndex = Arrays.binarySearch(mCursorIndexes, trackId);
260             if (cursorIndex < 0) {
261                 removed += MusicUtils.removeTrack(trackId);
262             }
263         }
264         if (removed > 0) {
265             mNowPlaying = MusicUtils.getQueue();
266             mSize = mNowPlaying.length;
267             if (mSize == 0) {
268                 mCursorIndexes = null;
269                 return;
270             }
271         }
272     }
273
274     /**
275      * @param which The position to remove
276      * @return True if sucessfull, false othersise
277      */
278     public boolean removeItem(final int which) {
279         try {
280             if (mService.removeTracks(which, which) == 0) {
281                 return false;
282             }
283             int i = which;
284             mSize--;
285             while (i < mSize) {
286                 mNowPlaying[i] = mNowPlaying[i + 1];
287                 i++;
288             }
289             onMove(-1, mCurPos);
290         } catch (final RemoteException ignored) {
291         }
292         return true;
293     }
294 }