OSDN Git Service

overhaul
[android-x86/packages-apps-Eleven.git] / src / com / andrew / apollo / utils / MusicUtils.java
1 \r
2 package com.andrew.apollo.utils;\r
3 \r
4 import java.util.Arrays;\r
5 import java.util.Formatter;\r
6 import java.util.HashMap;\r
7 import java.util.List;\r
8 import java.util.Locale;\r
9 import java.util.Map;\r
10 \r
11 import android.app.Activity;\r
12 import android.app.SearchManager;\r
13 import android.content.ContentResolver;\r
14 import android.content.ContentUris;\r
15 import android.content.ContentValues;\r
16 import android.content.Context;\r
17 import android.content.ContextWrapper;\r
18 import android.content.Intent;\r
19 import android.content.ServiceConnection;\r
20 import android.content.SharedPreferences;\r
21 import android.content.res.Resources;\r
22 import android.database.Cursor;\r
23 import android.net.Uri;\r
24 import android.os.Environment;\r
25 import android.os.RemoteException;\r
26 import android.provider.BaseColumns;\r
27 import android.provider.MediaStore;\r
28 import android.provider.MediaStore.Audio;\r
29 import android.provider.MediaStore.Audio.AlbumColumns;\r
30 import android.provider.MediaStore.Audio.ArtistColumns;\r
31 import android.provider.MediaStore.Audio.AudioColumns;\r
32 import android.provider.MediaStore.Audio.Genres;\r
33 import android.provider.MediaStore.Audio.GenresColumns;\r
34 import android.provider.MediaStore.Audio.Playlists;\r
35 import android.provider.MediaStore.Audio.PlaylistsColumns;\r
36 import android.provider.MediaStore.MediaColumns;\r
37 import android.provider.Settings;\r
38 import android.support.v4.app.FragmentActivity;\r
39 import android.text.TextUtils;\r
40 import android.view.Window;\r
41 import android.widget.ImageButton;\r
42 import android.widget.Toast;\r
43 \r
44 import com.andrew.apollo.Constants;\r
45 import com.andrew.apollo.IApolloService;\r
46 import com.andrew.apollo.R;\r
47 import com.andrew.apollo.activities.ScanningProgress;\r
48 import com.andrew.apollo.service.ApolloService;\r
49 import com.andrew.apollo.service.ServiceBinder;\r
50 import com.andrew.apollo.service.ServiceToken;\r
51 \r
52 /**\r
53  * Various methods used to help with specific music statements\r
54  */\r
55 public class MusicUtils implements Constants {\r
56 \r
57     // Used to make number of albums/songs/time strings\r
58     private final static StringBuilder sFormatBuilder = new StringBuilder();\r
59 \r
60     private final static Formatter sFormatter = new Formatter(sFormatBuilder, Locale.getDefault());\r
61 \r
62     public static IApolloService mService = null;\r
63 \r
64     private static HashMap<Context, ServiceBinder> sConnectionMap = new HashMap<Context, ServiceBinder>();\r
65 \r
66     private final static long[] sEmptyList = new long[0];\r
67 \r
68     private static final Object[] sTimeArgs = new Object[5];\r
69 \r
70     private static ContentValues[] sContentValuesCache = null;\r
71 \r
72     private static String mLastSdStatus;\r
73 \r
74     private final static int SCAN_DONE = 0;\r
75 \r
76     /**\r
77      * @param context\r
78      * @return\r
79      */\r
80     public static ServiceToken bindToService(FragmentActivity context) {\r
81         return bindToService(context, null);\r
82     }\r
83 \r
84     /**\r
85      * @param context\r
86      * @param callback\r
87      * @return\r
88      */\r
89     public static ServiceToken bindToService(Context context, ServiceConnection callback) {\r
90         Activity realActivity = ((Activity)context).getParent();\r
91         if (realActivity == null) {\r
92             realActivity = (Activity)context;\r
93         }\r
94         ContextWrapper cw = new ContextWrapper(realActivity);\r
95         cw.startService(new Intent(cw, ApolloService.class));\r
96         ServiceBinder sb = new ServiceBinder(callback);\r
97         if (cw.bindService((new Intent()).setClass(cw, ApolloService.class), sb, 0)) {\r
98             sConnectionMap.put(cw, sb);\r
99             return new ServiceToken(cw);\r
100         }\r
101         return null;\r
102     }\r
103 \r
104     /**\r
105      * @param token\r
106      */\r
107     public static void unbindFromService(ServiceToken token) {\r
108         if (token == null) {\r
109             return;\r
110         }\r
111         ContextWrapper cw = token.mWrappedContext;\r
112         ServiceBinder sb = sConnectionMap.remove(cw);\r
113         if (sb == null) {\r
114             return;\r
115         }\r
116         cw.unbindService(sb);\r
117         if (sConnectionMap.isEmpty()) {\r
118             mService = null;\r
119         }\r
120     }\r
121 \r
122     /**\r
123      * @param context\r
124      * @param numalbums\r
125      * @param numsongs\r
126      * @param isUnknown\r
127      * @return a string based on the number of albums for an artist or songs for\r
128      *         an album\r
129      */\r
130     public static String makeAlbumsLabel(Context mContext, int numalbums, int numsongs,\r
131             boolean isUnknown) {\r
132 \r
133         StringBuilder songs_albums = new StringBuilder();\r
134 \r
135         Resources r = mContext.getResources();\r
136         if (isUnknown) {\r
137             String f = r.getQuantityText(R.plurals.Nsongs, numsongs).toString();\r
138             sFormatBuilder.setLength(0);\r
139             sFormatter.format(f, Integer.valueOf(numsongs));\r
140             songs_albums.append(sFormatBuilder);\r
141         } else {\r
142             String f = r.getQuantityText(R.plurals.Nalbums, numalbums).toString();\r
143             sFormatBuilder.setLength(0);\r
144             sFormatter.format(f, Integer.valueOf(numalbums));\r
145             songs_albums.append(sFormatBuilder);\r
146             songs_albums.append("\n");\r
147         }\r
148         return songs_albums.toString();\r
149     }\r
150 \r
151     /**\r
152      * @param mContext\r
153      * @return\r
154      */\r
155     public static int getCardId(Context mContext) {\r
156 \r
157         ContentResolver res = mContext.getContentResolver();\r
158         Cursor c = res.query(Uri.parse("content://media/external/fs_id"), null, null, null, null);\r
159         int id = -1;\r
160         if (c != null) {\r
161             c.moveToFirst();\r
162             id = c.getInt(0);\r
163             c.close();\r
164         }\r
165         return id;\r
166     }\r
167 \r
168     /**\r
169      * @param context\r
170      * @param uri\r
171      * @param projection\r
172      * @param selection\r
173      * @param selectionArgs\r
174      * @param sortOrder\r
175      * @param limit\r
176      * @return\r
177      */\r
178     public static Cursor query(Context context, Uri uri, String[] projection, String selection,\r
179             String[] selectionArgs, String sortOrder, int limit) {\r
180         try {\r
181             ContentResolver resolver = context.getContentResolver();\r
182             if (resolver == null) {\r
183                 return null;\r
184             }\r
185             if (limit > 0) {\r
186                 uri = uri.buildUpon().appendQueryParameter("limit", "" + limit).build();\r
187             }\r
188             return resolver.query(uri, projection, selection, selectionArgs, sortOrder);\r
189         } catch (UnsupportedOperationException ex) {\r
190             return null;\r
191         }\r
192     }\r
193 \r
194     /**\r
195      * @param context\r
196      * @param uri\r
197      * @param projection\r
198      * @param selection\r
199      * @param selectionArgs\r
200      * @param sortOrder\r
201      * @return\r
202      */\r
203     public static Cursor query(Context context, Uri uri, String[] projection, String selection,\r
204             String[] selectionArgs, String sortOrder) {\r
205         return query(context, uri, projection, selection, selectionArgs, sortOrder, 0);\r
206     }\r
207 \r
208     /**\r
209      * @param context\r
210      * @param cursor\r
211      */\r
212     public static void shuffleAll(Context context, Cursor cursor) {\r
213         playAll(context, cursor, 0, true);\r
214     }\r
215 \r
216     /**\r
217      * @param context\r
218      * @param cursor\r
219      */\r
220     public static void playAll(Context context, Cursor cursor) {\r
221         playAll(context, cursor, 0, false);\r
222     }\r
223 \r
224     /**\r
225      * @param context\r
226      * @param cursor\r
227      * @param position\r
228      */\r
229     public static void playAll(Context context, Cursor cursor, int position) {\r
230         playAll(context, cursor, position, false);\r
231     }\r
232 \r
233     /**\r
234      * @param context\r
235      * @param list\r
236      * @param position\r
237      */\r
238     public static void playAll(Context context, long[] list, int position) {\r
239         playAll(context, list, position, false);\r
240     }\r
241 \r
242     /**\r
243      * @param context\r
244      * @param cursor\r
245      * @param position\r
246      * @param force_shuffle\r
247      */\r
248     private static void playAll(Context context, Cursor cursor, int position, boolean force_shuffle) {\r
249 \r
250         long[] list = getSongListForCursor(cursor);\r
251         playAll(context, list, position, force_shuffle);\r
252     }\r
253 \r
254     /**\r
255      * @param cursor\r
256      * @return\r
257      */\r
258     public static long[] getSongListForCursor(Cursor cursor) {\r
259         if (cursor == null) {\r
260             return sEmptyList;\r
261         }\r
262         int len = cursor.getCount();\r
263         long[] list = new long[len];\r
264         cursor.moveToFirst();\r
265         int colidx = -1;\r
266         try {\r
267             colidx = cursor.getColumnIndexOrThrow(Audio.Playlists.Members.AUDIO_ID);\r
268         } catch (IllegalArgumentException ex) {\r
269             colidx = cursor.getColumnIndexOrThrow(BaseColumns._ID);\r
270         }\r
271         for (int i = 0; i < len; i++) {\r
272             list[i] = cursor.getLong(colidx);\r
273             cursor.moveToNext();\r
274         }\r
275         return list;\r
276     }\r
277 \r
278     /**\r
279      * @param context\r
280      * @param list\r
281      * @param position\r
282      * @param force_shuffle\r
283      */\r
284     private static void playAll(Context context, long[] list, int position, boolean force_shuffle) {\r
285         if (list.length == 0 || mService == null) {\r
286             return;\r
287         }\r
288         try {\r
289             if (force_shuffle) {\r
290                 mService.setShuffleMode(ApolloService.SHUFFLE_NORMAL);\r
291             }\r
292             long curid = mService.getAudioId();\r
293             int curpos = mService.getQueuePosition();\r
294             if (position != -1 && curpos == position && curid == list[position]) {\r
295                 // The selected file is the file that's currently playing;\r
296                 // figure out if we need to restart with a new playlist,\r
297                 // or just launch the playback activity.\r
298                 long[] playlist = mService.getQueue();\r
299                 if (Arrays.equals(list, playlist)) {\r
300                     // we don't need to set a new list, but we should resume\r
301                     // playback if needed\r
302                     mService.play();\r
303                     return;\r
304                 }\r
305             }\r
306             if (position < 0) {\r
307                 position = 0;\r
308             }\r
309             mService.open(list, force_shuffle ? -1 : position);\r
310             mService.play();\r
311         } catch (RemoteException ex) {\r
312             ex.printStackTrace();\r
313         }\r
314     }\r
315 \r
316     /**\r
317      * @return\r
318      */\r
319     public static long[] getQueue() {\r
320 \r
321         if (mService == null)\r
322             return sEmptyList;\r
323 \r
324         try {\r
325             return mService.getQueue();\r
326         } catch (RemoteException e) {\r
327             e.printStackTrace();\r
328         }\r
329         return sEmptyList;\r
330     }\r
331 \r
332     /**\r
333      * @param context\r
334      * @param name\r
335      * @param def\r
336      * @return number of weeks used to create the Recent tab\r
337      */\r
338     public static int getIntPref(Context context, String name, int def) {\r
339         SharedPreferences prefs = context.getSharedPreferences(context.getPackageName(),\r
340                 Context.MODE_PRIVATE);\r
341         return prefs.getInt(name, def);\r
342     }\r
343 \r
344     /**\r
345      * @param context\r
346      * @param id\r
347      * @return\r
348      */\r
349     public static long[] getSongListForArtist(Context context, long id) {\r
350         final String[] projection = new String[] {\r
351             BaseColumns._ID\r
352         };\r
353         String selection = AudioColumns.ARTIST_ID + "=" + id + " AND " + AudioColumns.IS_MUSIC\r
354                 + "=1";\r
355         String sortOrder = AudioColumns.ALBUM_KEY + "," + AudioColumns.TRACK;\r
356         Uri uri = Audio.Media.EXTERNAL_CONTENT_URI;\r
357         Cursor cursor = query(context, uri, projection, selection, null, sortOrder);\r
358         if (cursor != null) {\r
359             long[] list = getSongListForCursor(cursor);\r
360             cursor.close();\r
361             return list;\r
362         }\r
363         return sEmptyList;\r
364     }\r
365 \r
366     /**\r
367      * @param context\r
368      * @param id\r
369      * @return\r
370      */\r
371     public static long[] getSongListForAlbum(Context context, long id) {\r
372         final String[] projection = new String[] {\r
373             BaseColumns._ID\r
374         };\r
375         String selection = AudioColumns.ALBUM_ID + "=" + id + " AND " + AudioColumns.IS_MUSIC\r
376                 + "=1";\r
377         String sortOrder = AudioColumns.TRACK;\r
378         Uri uri = Audio.Media.EXTERNAL_CONTENT_URI;\r
379         Cursor cursor = query(context, uri, projection, selection, null, sortOrder);\r
380         if (cursor != null) {\r
381             long[] list = getSongListForCursor(cursor);\r
382             cursor.close();\r
383             return list;\r
384         }\r
385         return sEmptyList;\r
386     }\r
387 \r
388     /**\r
389      * @param context\r
390      * @param id\r
391      * @return\r
392      */\r
393     public static long[] getSongListForGenre(Context context, long id) {\r
394         String[] projection = new String[] {\r
395             BaseColumns._ID\r
396         };\r
397         StringBuilder selection = new StringBuilder();\r
398         selection.append(AudioColumns.IS_MUSIC + "=1");\r
399         selection.append(" AND " + MediaColumns.TITLE + "!=''");\r
400         Uri uri = Genres.Members.getContentUri(EXTERNAL, id);\r
401         Cursor cursor = context.getContentResolver().query(uri, projection, selection.toString(),\r
402                 null, null);\r
403         if (cursor != null) {\r
404             long[] list = getSongListForCursor(cursor);\r
405             cursor.close();\r
406             return list;\r
407         }\r
408         return sEmptyList;\r
409     }\r
410 \r
411     /**\r
412      * @param context\r
413      * @param id\r
414      * @return\r
415      */\r
416     public static long[] getSongListForPlaylist(Context context, long id) {\r
417         final String[] projection = new String[] {\r
418             Audio.Playlists.Members.AUDIO_ID\r
419         };\r
420         String sortOrder = Playlists.Members.DEFAULT_SORT_ORDER;\r
421         Uri uri = Playlists.Members.getContentUri(EXTERNAL, id);\r
422         Cursor cursor = query(context, uri, projection, null, null, sortOrder);\r
423         if (cursor != null) {\r
424             long[] list = getSongListForCursor(cursor);\r
425             cursor.close();\r
426             return list;\r
427         }\r
428         return sEmptyList;\r
429     }\r
430 \r
431     /**\r
432      * @param context\r
433      * @param name\r
434      * @return\r
435      */\r
436     public static long createPlaylist(Context context, String name) {\r
437 \r
438         if (name != null && name.length() > 0) {\r
439             ContentResolver resolver = context.getContentResolver();\r
440             String[] cols = new String[] {\r
441                 PlaylistsColumns.NAME\r
442             };\r
443             String whereclause = PlaylistsColumns.NAME + " = '" + name + "'";\r
444             Cursor cur = resolver.query(Audio.Playlists.EXTERNAL_CONTENT_URI, cols, whereclause,\r
445                     null, null);\r
446             if (cur.getCount() <= 0) {\r
447                 ContentValues values = new ContentValues(1);\r
448                 values.put(PlaylistsColumns.NAME, name);\r
449                 Uri uri = resolver.insert(Audio.Playlists.EXTERNAL_CONTENT_URI, values);\r
450                 return Long.parseLong(uri.getLastPathSegment());\r
451             }\r
452             return -1;\r
453         }\r
454         return -1;\r
455     }\r
456 \r
457     /**\r
458      * @param context\r
459      * @return\r
460      */\r
461     public static long getFavoritesId(Context context) {\r
462         long favorites_id = -1;\r
463         String favorites_where = PlaylistsColumns.NAME + "='" + "Favorites" + "'";\r
464         String[] favorites_cols = new String[] {\r
465             BaseColumns._ID\r
466         };\r
467         Uri favorites_uri = Audio.Playlists.EXTERNAL_CONTENT_URI;\r
468         Cursor cursor = query(context, favorites_uri, favorites_cols, favorites_where, null, null);\r
469         if (cursor.getCount() <= 0) {\r
470             favorites_id = createPlaylist(context, "Favorites");\r
471         } else {\r
472             cursor.moveToFirst();\r
473             favorites_id = cursor.getLong(0);\r
474             cursor.close();\r
475         }\r
476         return favorites_id;\r
477     }\r
478 \r
479     /**\r
480      * @param context\r
481      * @param id\r
482      */\r
483     public static void setRingtone(Context context, long id) {\r
484         ContentResolver resolver = context.getContentResolver();\r
485         // Set the flag in the database to mark this as a ringtone\r
486         Uri ringUri = ContentUris.withAppendedId(Audio.Media.EXTERNAL_CONTENT_URI, id);\r
487         try {\r
488             ContentValues values = new ContentValues(2);\r
489             values.put(AudioColumns.IS_RINGTONE, "1");\r
490             values.put(AudioColumns.IS_ALARM, "1");\r
491             resolver.update(ringUri, values, null, null);\r
492         } catch (UnsupportedOperationException ex) {\r
493             // most likely the card just got unmounted\r
494             return;\r
495         }\r
496 \r
497         String[] cols = new String[] {\r
498                 BaseColumns._ID, MediaColumns.DATA, MediaColumns.TITLE\r
499         };\r
500 \r
501         String where = BaseColumns._ID + "=" + id;\r
502         Cursor cursor = query(context, Audio.Media.EXTERNAL_CONTENT_URI, cols, where, null, null);\r
503         try {\r
504             if (cursor != null && cursor.getCount() == 1) {\r
505                 // Set the system setting to make this the current ringtone\r
506                 cursor.moveToFirst();\r
507                 Settings.System.putString(resolver, Settings.System.RINGTONE, ringUri.toString());\r
508                 String message = context.getString(R.string.set_as_ringtone, cursor.getString(2));\r
509                 Toast.makeText(context, message, Toast.LENGTH_SHORT).show();\r
510             }\r
511         } finally {\r
512             if (cursor != null) {\r
513                 cursor.close();\r
514             }\r
515         }\r
516     }\r
517 \r
518     /**\r
519      * @param context\r
520      * @param plid\r
521      */\r
522     public static void clearPlaylist(Context context, int plid) {\r
523         Uri uri = Audio.Playlists.Members.getContentUri(EXTERNAL, plid);\r
524         context.getContentResolver().delete(uri, null, null);\r
525         return;\r
526     }\r
527 \r
528     /**\r
529      * @param context\r
530      * @param ids\r
531      * @param playlistid\r
532      */\r
533     public static void addToPlaylist(Context context, long[] ids, long playlistid) {\r
534 \r
535         if (ids == null) {\r
536         } else {\r
537             int size = ids.length;\r
538             ContentResolver resolver = context.getContentResolver();\r
539             // need to determine the number of items currently in the playlist,\r
540             // so the play_order field can be maintained.\r
541             String[] cols = new String[] {\r
542                 "count(*)"\r
543             };\r
544             Uri uri = Audio.Playlists.Members.getContentUri(EXTERNAL, playlistid);\r
545             Cursor cur = resolver.query(uri, cols, null, null, null);\r
546             cur.moveToFirst();\r
547             int base = cur.getInt(0);\r
548             cur.close();\r
549             int numinserted = 0;\r
550             for (int i = 0; i < size; i += 1000) {\r
551                 makeInsertItems(ids, i, 1000, base);\r
552                 numinserted += resolver.bulkInsert(uri, sContentValuesCache);\r
553             }\r
554             String message = context.getResources().getQuantityString(\r
555                     R.plurals.NNNtrackstoplaylist, numinserted, numinserted);\r
556             Toast.makeText(context, message, Toast.LENGTH_SHORT).show();\r
557         }\r
558     }\r
559 \r
560     /**\r
561      * @param ids\r
562      * @param offset\r
563      * @param len\r
564      * @param base\r
565      */\r
566     private static void makeInsertItems(long[] ids, int offset, int len, int base) {\r
567 \r
568         // adjust 'len' if would extend beyond the end of the source array\r
569         if (offset + len > ids.length) {\r
570             len = ids.length - offset;\r
571         }\r
572         // allocate the ContentValues array, or reallocate if it is the wrong\r
573         // size\r
574         if (sContentValuesCache == null || sContentValuesCache.length != len) {\r
575             sContentValuesCache = new ContentValues[len];\r
576         }\r
577         // fill in the ContentValues array with the right values for this pass\r
578         for (int i = 0; i < len; i++) {\r
579             if (sContentValuesCache[i] == null) {\r
580                 sContentValuesCache[i] = new ContentValues();\r
581             }\r
582 \r
583             sContentValuesCache[i].put(Playlists.Members.PLAY_ORDER, base + offset + i);\r
584             sContentValuesCache[i].put(Playlists.Members.AUDIO_ID, ids[offset + i]);\r
585         }\r
586     }\r
587 \r
588     /**\r
589      * Toggle favorites\r
590      */\r
591     public static void toggleFavorite() {\r
592 \r
593         if (mService == null)\r
594             return;\r
595         try {\r
596             mService.toggleFavorite();\r
597         } catch (RemoteException e) {\r
598             e.printStackTrace();\r
599         }\r
600     }\r
601 \r
602     /**\r
603      * @param context\r
604      * @param id\r
605      */\r
606     public static void addToFavorites(Context context, long id) {\r
607 \r
608         long favorites_id;\r
609 \r
610         if (id < 0) {\r
611 \r
612         } else {\r
613             ContentResolver resolver = context.getContentResolver();\r
614 \r
615             String favorites_where = PlaylistsColumns.NAME + "='" + PLAYLIST_NAME_FAVORITES + "'";\r
616             String[] favorites_cols = new String[] {\r
617                 BaseColumns._ID\r
618             };\r
619             Uri favorites_uri = Audio.Playlists.EXTERNAL_CONTENT_URI;\r
620             Cursor cursor = resolver.query(favorites_uri, favorites_cols, favorites_where, null,\r
621                     null);\r
622             if (cursor.getCount() <= 0) {\r
623                 favorites_id = createPlaylist(context, PLAYLIST_NAME_FAVORITES);\r
624             } else {\r
625                 cursor.moveToFirst();\r
626                 favorites_id = cursor.getLong(0);\r
627                 cursor.close();\r
628             }\r
629 \r
630             String[] cols = new String[] {\r
631                 Playlists.Members.AUDIO_ID\r
632             };\r
633             Uri uri = Playlists.Members.getContentUri(EXTERNAL, favorites_id);\r
634             Cursor cur = resolver.query(uri, cols, null, null, null);\r
635 \r
636             int base = cur.getCount();\r
637             cur.moveToFirst();\r
638             while (!cur.isAfterLast()) {\r
639                 if (cur.getLong(0) == id)\r
640                     return;\r
641                 cur.moveToNext();\r
642             }\r
643             cur.close();\r
644 \r
645             ContentValues values = new ContentValues();\r
646             values.put(Playlists.Members.AUDIO_ID, id);\r
647             values.put(Playlists.Members.PLAY_ORDER, base + 1);\r
648             resolver.insert(uri, values);\r
649         }\r
650     }\r
651 \r
652     /**\r
653      * @param context\r
654      * @param id\r
655      * @return\r
656      */\r
657     public static boolean isFavorite(Context context, long id) {\r
658 \r
659         long favorites_id;\r
660 \r
661         if (id < 0) {\r
662 \r
663         } else {\r
664             ContentResolver resolver = context.getContentResolver();\r
665 \r
666             String favorites_where = PlaylistsColumns.NAME + "='" + PLAYLIST_NAME_FAVORITES + "'";\r
667             String[] favorites_cols = new String[] {\r
668                 BaseColumns._ID\r
669             };\r
670             Uri favorites_uri = Audio.Playlists.EXTERNAL_CONTENT_URI;\r
671             Cursor cursor = resolver.query(favorites_uri, favorites_cols, favorites_where, null,\r
672                     null);\r
673             if (cursor.getCount() <= 0) {\r
674                 favorites_id = createPlaylist(context, PLAYLIST_NAME_FAVORITES);\r
675             } else {\r
676                 cursor.moveToFirst();\r
677                 favorites_id = cursor.getLong(0);\r
678                 cursor.close();\r
679             }\r
680 \r
681             String[] cols = new String[] {\r
682                 Playlists.Members.AUDIO_ID\r
683             };\r
684             Uri uri = Playlists.Members.getContentUri(EXTERNAL, favorites_id);\r
685             Cursor cur = resolver.query(uri, cols, null, null, null);\r
686 \r
687             cur.moveToFirst();\r
688             while (!cur.isAfterLast()) {\r
689                 if (cur.getLong(0) == id) {\r
690                     cur.close();\r
691                     return true;\r
692                 }\r
693                 cur.moveToNext();\r
694             }\r
695             cur.close();\r
696             return false;\r
697         }\r
698         return false;\r
699     }\r
700 \r
701     /**\r
702      * @param context\r
703      * @param id\r
704      */\r
705     public static void removeFromFavorites(Context context, long id) {\r
706         long favorites_id;\r
707         if (id < 0) {\r
708         } else {\r
709             ContentResolver resolver = context.getContentResolver();\r
710             String favorites_where = PlaylistsColumns.NAME + "='" + PLAYLIST_NAME_FAVORITES + "'";\r
711             String[] favorites_cols = new String[] {\r
712                 BaseColumns._ID\r
713             };\r
714             Uri favorites_uri = Audio.Playlists.EXTERNAL_CONTENT_URI;\r
715             Cursor cursor = resolver.query(favorites_uri, favorites_cols, favorites_where, null,\r
716                     null);\r
717             if (cursor.getCount() <= 0) {\r
718                 favorites_id = createPlaylist(context, PLAYLIST_NAME_FAVORITES);\r
719             } else {\r
720                 cursor.moveToFirst();\r
721                 favorites_id = cursor.getLong(0);\r
722                 cursor.close();\r
723             }\r
724             Uri uri = Playlists.Members.getContentUri(EXTERNAL, favorites_id);\r
725             resolver.delete(uri, Playlists.Members.AUDIO_ID + "=" + id, null);\r
726         }\r
727     }\r
728 \r
729     /**\r
730      * @param mService\r
731      * @param mImageButton\r
732      * @param id\r
733      */\r
734     public static void setFavoriteImage(ImageButton mImageButton) {\r
735         try {\r
736             if (MusicUtils.mService.isFavorite(MusicUtils.mService.getAudioId())) {\r
737                 mImageButton.setImageResource(R.drawable.apollo_holo_light_favorite_selected);\r
738             } else {\r
739                 mImageButton.setImageResource(R.drawable.apollo_holo_light_favorite_normal);\r
740                 // Theme chooser\r
741                 ThemeUtils.setImageButton(mImageButton.getContext(), mImageButton,\r
742                         "apollo_favorite_normal");\r
743             }\r
744         } catch (RemoteException e) {\r
745             e.printStackTrace();\r
746         }\r
747     }\r
748 \r
749     /**\r
750      * @param mContext\r
751      * @param id\r
752      * @param name\r
753      */\r
754     public static void renamePlaylist(Context mContext, long id, String name) {\r
755 \r
756         if (name != null && name.length() > 0) {\r
757             ContentResolver resolver = mContext.getContentResolver();\r
758             ContentValues values = new ContentValues(1);\r
759             values.put(PlaylistsColumns.NAME, name);\r
760             resolver.update(Audio.Playlists.EXTERNAL_CONTENT_URI, values, BaseColumns._ID + "=?",\r
761                     new String[] {\r
762                         String.valueOf(id)\r
763                     });\r
764             Toast.makeText(mContext, "Playlist renamed", Toast.LENGTH_SHORT).show();\r
765         }\r
766     }\r
767 \r
768     /**\r
769      * @param mContext\r
770      * @param list\r
771      */\r
772     public static void addToCurrentPlaylist(Context mContext, long[] list) {\r
773 \r
774         if (mService == null)\r
775             return;\r
776         try {\r
777             mService.enqueue(list, ApolloService.LAST);\r
778             String message = mContext.getResources().getQuantityString(\r
779                     R.plurals.NNNtrackstoplaylist, list.length, Integer.valueOf(list.length));\r
780             Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();\r
781         } catch (RemoteException ex) {\r
782         }\r
783     }\r
784 \r
785     /**\r
786      * @param context\r
787      * @param secs\r
788      * @return time String\r
789      */\r
790     public static String makeTimeString(Context context, long secs) {\r
791 \r
792         String durationformat = context.getString(secs < 3600 ? R.string.durationformatshort\r
793                 : R.string.durationformatlong);\r
794 \r
795         /*\r
796          * Provide multiple arguments so the format can be changed easily by\r
797          * modifying the xml.\r
798          */\r
799         sFormatBuilder.setLength(0);\r
800 \r
801         final Object[] timeArgs = sTimeArgs;\r
802         timeArgs[0] = secs / 3600;\r
803         timeArgs[1] = secs / 60;\r
804         timeArgs[2] = secs / 60 % 60;\r
805         timeArgs[3] = secs;\r
806         timeArgs[4] = secs % 60;\r
807 \r
808         return sFormatter.format(durationformat, timeArgs).toString();\r
809     }\r
810 \r
811     /**\r
812      * @return current album ID\r
813      */\r
814     public static long getCurrentAlbumId() {\r
815 \r
816         if (mService != null) {\r
817             try {\r
818                 return mService.getAlbumId();\r
819             } catch (RemoteException ex) {\r
820             }\r
821         }\r
822         return -1;\r
823     }\r
824 \r
825     /**\r
826      * @return current artist ID\r
827      */\r
828     public static long getCurrentArtistId() {\r
829 \r
830         if (MusicUtils.mService != null) {\r
831             try {\r
832                 return mService.getArtistId();\r
833             } catch (RemoteException ex) {\r
834             }\r
835         }\r
836         return -1;\r
837     }\r
838 \r
839     /**\r
840      * @return current track ID\r
841      */\r
842     public static long getCurrentAudioId() {\r
843 \r
844         if (MusicUtils.mService != null) {\r
845             try {\r
846                 return mService.getAudioId();\r
847             } catch (RemoteException ex) {\r
848             }\r
849         }\r
850         return -1;\r
851     }\r
852 \r
853     /**\r
854      * @return current artist name\r
855      */\r
856     public static String getArtistName() {\r
857 \r
858         if (mService != null) {\r
859             try {\r
860                 return mService.getArtistName();\r
861             } catch (RemoteException ex) {\r
862             }\r
863         }\r
864         return null;\r
865     }\r
866 \r
867     /**\r
868      * @return current album name\r
869      */\r
870     public static String getAlbumName() {\r
871 \r
872         if (mService != null) {\r
873             try {\r
874                 return mService.getAlbumName();\r
875             } catch (RemoteException ex) {\r
876             }\r
877         }\r
878         return null;\r
879     }\r
880 \r
881     /**\r
882      * @return current track name\r
883      */\r
884     public static String getTrackName() {\r
885 \r
886         if (mService != null) {\r
887             try {\r
888                 return mService.getTrackName();\r
889             } catch (RemoteException ex) {\r
890             }\r
891         }\r
892         return null;\r
893     }\r
894 \r
895     /**\r
896      * @return duration of a track\r
897      */\r
898     public static long getDuration() {\r
899         if (mService != null) {\r
900             try {\r
901                 return mService.duration();\r
902             } catch (RemoteException e) {\r
903             }\r
904         }\r
905         return 0;\r
906     }\r
907 \r
908     /**\r
909      * @param context\r
910      * @return whether the mediascanner is running\r
911      */\r
912     public static boolean isMediaScannerScanning(Context context) {\r
913         boolean result = false;\r
914         Cursor cursor = query(context, MediaStore.getMediaScannerUri(), new String[] {\r
915             MediaStore.MEDIA_SCANNER_VOLUME\r
916         }, null, null, null);\r
917         if (cursor != null) {\r
918             if (cursor.getCount() == 1) {\r
919                 cursor.moveToFirst();\r
920                 result = EXTERNAL.equals(cursor.getString(0));\r
921             }\r
922             cursor.close();\r
923         }\r
924         return result;\r
925     }\r
926 \r
927     /**\r
928      * @param a\r
929      */\r
930     public static void setSpinnerState(Activity a) {\r
931         if (isMediaScannerScanning(a)) {\r
932             // Start the progress spinner\r
933             a.getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS,\r
934                     Window.PROGRESS_INDETERMINATE_ON);\r
935 \r
936             a.getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS,\r
937                     Window.PROGRESS_VISIBILITY_ON);\r
938         } else {\r
939             // Stop the progress spinner\r
940             a.getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS,\r
941                     Window.PROGRESS_VISIBILITY_OFF);\r
942         }\r
943     }\r
944 \r
945     /**\r
946      * @param a\r
947      * @param resID\r
948      */\r
949     public static void displayDatabaseError(Activity a) {\r
950         if (a.isFinishing()) {\r
951             return;\r
952         }\r
953 \r
954         String status = Environment.getExternalStorageState();\r
955         if (status.equals(Environment.MEDIA_MOUNTED)) {\r
956             Intent intent = new Intent();\r
957             intent.setClass(a, ScanningProgress.class);\r
958             a.startActivityForResult(intent, SCAN_DONE);\r
959         } else if (!TextUtils.equals(mLastSdStatus, status)) {\r
960             mLastSdStatus = status;\r
961         }\r
962     }\r
963 \r
964     /**\r
965      * Create a Search Chooser\r
966      */\r
967     public static void doSearch(Context mContext, Cursor mCursor, int index) {\r
968         CharSequence title = null;\r
969         Intent i = new Intent();\r
970         i.setAction(MediaStore.INTENT_ACTION_MEDIA_SEARCH);\r
971         i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);\r
972         String query = mCursor.getString(index);\r
973         title = "";\r
974         i.putExtra("", query);\r
975         title = title + " " + query;\r
976         title = "Search " + title;\r
977         i.putExtra(SearchManager.QUERY, query);\r
978         mContext.startActivity(Intent.createChooser(i, title));\r
979     }\r
980 \r
981     /**\r
982      * @param id\r
983      * @return removes track from a playlist\r
984      */\r
985     public static int removeTrack(long id) {\r
986         if (mService == null)\r
987             return 0;\r
988 \r
989         try {\r
990             return mService.removeTrack(id);\r
991         } catch (RemoteException e) {\r
992             e.printStackTrace();\r
993         }\r
994         return 0;\r
995     }\r
996 \r
997     /**\r
998      * @param index\r
999      */\r
1000     public static void setQueuePosition(int index) {\r
1001         if (mService == null)\r
1002             return;\r
1003         try {\r
1004             mService.setQueuePosition(index);\r
1005         } catch (RemoteException e) {\r
1006         }\r
1007     }\r
1008 \r
1009     public static String getArtistName(Context mContext, long artist_id, boolean default_name) {\r
1010         String where = BaseColumns._ID + "=" + artist_id;\r
1011         String[] cols = new String[] {\r
1012             ArtistColumns.ARTIST\r
1013         };\r
1014         Uri uri = Audio.Artists.EXTERNAL_CONTENT_URI;\r
1015         Cursor cursor = mContext.getContentResolver().query(uri, cols, where, null, null);\r
1016         if (cursor.getCount() <= 0) {\r
1017             if (default_name)\r
1018                 return mContext.getString(R.string.unknown);\r
1019             else\r
1020                 return MediaStore.UNKNOWN_STRING;\r
1021         } else {\r
1022             cursor.moveToFirst();\r
1023             String name = cursor.getString(0);\r
1024             cursor.close();\r
1025             if (name == null || MediaStore.UNKNOWN_STRING.equals(name)) {\r
1026                 if (default_name)\r
1027                     return mContext.getString(R.string.unknown);\r
1028                 else\r
1029                     return MediaStore.UNKNOWN_STRING;\r
1030             }\r
1031             return name;\r
1032         }\r
1033     }\r
1034 \r
1035     /**\r
1036      * @param mContext\r
1037      * @param album_id\r
1038      * @param default_name\r
1039      * @return album name\r
1040      */\r
1041     public static String getAlbumName(Context mContext, long album_id, boolean default_name) {\r
1042         String where = BaseColumns._ID + "=" + album_id;\r
1043         String[] cols = new String[] {\r
1044             AlbumColumns.ALBUM\r
1045         };\r
1046         Uri uri = Audio.Albums.EXTERNAL_CONTENT_URI;\r
1047         Cursor cursor = mContext.getContentResolver().query(uri, cols, where, null, null);\r
1048         if (cursor.getCount() <= 0) {\r
1049             if (default_name)\r
1050                 return mContext.getString(R.string.unknown);\r
1051             else\r
1052                 return MediaStore.UNKNOWN_STRING;\r
1053         } else {\r
1054             cursor.moveToFirst();\r
1055             String name = cursor.getString(0);\r
1056             cursor.close();\r
1057             if (name == null || MediaStore.UNKNOWN_STRING.equals(name)) {\r
1058                 if (default_name)\r
1059                     return mContext.getString(R.string.unknown);\r
1060                 else\r
1061                     return MediaStore.UNKNOWN_STRING;\r
1062             }\r
1063             return name;\r
1064         }\r
1065     }\r
1066 \r
1067     /**\r
1068      * @param playlist_id\r
1069      * @return playlist name\r
1070      */\r
1071     public static String getPlaylistName(Context mContext, long playlist_id) {\r
1072         String where = BaseColumns._ID + "=" + playlist_id;\r
1073         String[] cols = new String[] {\r
1074             PlaylistsColumns.NAME\r
1075         };\r
1076         Uri uri = Audio.Playlists.EXTERNAL_CONTENT_URI;\r
1077         Cursor cursor = mContext.getContentResolver().query(uri, cols, where, null, null);\r
1078         if (cursor.getCount() <= 0)\r
1079             return "";\r
1080         cursor.moveToFirst();\r
1081         String name = cursor.getString(0);\r
1082         cursor.close();\r
1083         return name;\r
1084     }\r
1085 \r
1086     /**\r
1087      * @param mContext\r
1088      * @param genre_id\r
1089      * @param default_name\r
1090      * @return genre name\r
1091      */\r
1092     public static String getGenreName(Context mContext, long genre_id, boolean default_name) {\r
1093         String where = BaseColumns._ID + "=" + genre_id;\r
1094         String[] cols = new String[] {\r
1095             GenresColumns.NAME\r
1096         };\r
1097         Uri uri = Audio.Genres.EXTERNAL_CONTENT_URI;\r
1098         Cursor cursor = mContext.getContentResolver().query(uri, cols, where, null, null);\r
1099         if (cursor.getCount() <= 0) {\r
1100             if (default_name)\r
1101                 return mContext.getString(R.string.unknown);\r
1102             else\r
1103                 return MediaStore.UNKNOWN_STRING;\r
1104         } else {\r
1105             cursor.moveToFirst();\r
1106             String name = cursor.getString(0);\r
1107             cursor.close();\r
1108             if (name == null || MediaStore.UNKNOWN_STRING.equals(name)) {\r
1109                 if (default_name)\r
1110                     return mContext.getString(R.string.unknown);\r
1111                 else\r
1112                     return MediaStore.UNKNOWN_STRING;\r
1113             }\r
1114             return name;\r
1115         }\r
1116     }\r
1117 \r
1118     /**\r
1119      * @param genre\r
1120      * @return parsed genre name\r
1121      */\r
1122     public static String parseGenreName(Context mContext, String genre) {\r
1123         int genre_id = -1;\r
1124 \r
1125         if (genre == null || genre.trim().length() <= 0)\r
1126             return mContext.getResources().getString(R.string.unknown);\r
1127 \r
1128         try {\r
1129             genre_id = Integer.parseInt(genre);\r
1130         } catch (NumberFormatException e) {\r
1131             return genre;\r
1132         }\r
1133         if (genre_id >= 0 && genre_id < GENRES_DB.length)\r
1134             return GENRES_DB[genre_id];\r
1135         else\r
1136             return mContext.getResources().getString(R.string.unknown);\r
1137     }\r
1138 \r
1139     /**\r
1140      * @return if music is playing\r
1141      */\r
1142     public static boolean isPlaying() {\r
1143         if (mService == null)\r
1144             return false;\r
1145 \r
1146         try {\r
1147             mService.isPlaying();\r
1148         } catch (RemoteException e) {\r
1149         }\r
1150         return false;\r
1151     }\r
1152 \r
1153     /**\r
1154      * @return current track's queue position\r
1155      */\r
1156     public static int getQueuePosition() {\r
1157         if (mService == null)\r
1158             return 0;\r
1159         try {\r
1160             return mService.getQueuePosition();\r
1161         } catch (RemoteException e) {\r
1162         }\r
1163         return 0;\r
1164     }\r
1165 \r
1166     /**\r
1167      * @param mContext\r
1168      * @param create_shortcut\r
1169      * @param list\r
1170      */\r
1171     public static void makePlaylistList(Context mContext, boolean create_shortcut,\r
1172             List<Map<String, String>> list) {\r
1173 \r
1174         Map<String, String> map;\r
1175 \r
1176         String[] cols = new String[] {\r
1177                 Audio.Playlists._ID, Audio.Playlists.NAME\r
1178         };\r
1179         StringBuilder where = new StringBuilder();\r
1180 \r
1181         ContentResolver resolver = mContext.getContentResolver();\r
1182         if (resolver == null) {\r
1183             System.out.println("resolver = null");\r
1184         } else {\r
1185             where.append(Audio.Playlists.NAME + " != ''");\r
1186             where.append(" AND " + Audio.Playlists.NAME + " != '" + PLAYLIST_NAME_FAVORITES + "'");\r
1187             Cursor cur = resolver.query(Audio.Playlists.EXTERNAL_CONTENT_URI, cols,\r
1188                     where.toString(), null, Audio.Playlists.NAME);\r
1189             list.clear();\r
1190 \r
1191             // map = new HashMap<String, String>();\r
1192             // map.put("id", String.valueOf(PLAYLIST_FAVORITES));\r
1193             // map.put("name", mContext.getString(R.string.favorite));\r
1194             // list.add(map);\r
1195 \r
1196             map = new HashMap<String, String>();\r
1197             map.put("id", String.valueOf(PLAYLIST_QUEUE));\r
1198             map.put("name", mContext.getString(R.string.queue));\r
1199             list.add(map);\r
1200 \r
1201             map = new HashMap<String, String>();\r
1202             map.put("id", String.valueOf(PLAYLIST_NEW));\r
1203             map.put("name", mContext.getString(R.string.new_playlist));\r
1204             list.add(map);\r
1205 \r
1206             if (cur != null && cur.getCount() > 0) {\r
1207                 cur.moveToFirst();\r
1208                 while (!cur.isAfterLast()) {\r
1209                     map = new HashMap<String, String>();\r
1210                     map.put("id", String.valueOf(cur.getLong(0)));\r
1211                     map.put("name", cur.getString(1));\r
1212                     list.add(map);\r
1213                     cur.moveToNext();\r
1214                 }\r
1215             }\r
1216             if (cur != null) {\r
1217                 cur.close();\r
1218             }\r
1219         }\r
1220     }\r
1221 \r
1222 }\r