OSDN Git Service

Merge "CM9-Apollo-Update Russian Translation" into ics
[android-x86/packages-apps-Eleven.git] / src / com / andrew / apollo / list / fragments / TracksFragment.java
1 /**\r
2  * \r
3  */\r
4 \r
5 package com.andrew.apollo.list.fragments;\r
6 \r
7 import android.content.BroadcastReceiver;\r
8 import android.content.Context;\r
9 import android.content.Intent;\r
10 import android.content.IntentFilter;\r
11 import android.database.Cursor;\r
12 import android.net.Uri;\r
13 import android.os.Bundle;\r
14 import android.provider.BaseColumns;\r
15 import android.provider.MediaStore.Audio;\r
16 import android.provider.MediaStore.Audio.Albums;\r
17 import android.provider.MediaStore.Audio.Artists;\r
18 import android.provider.MediaStore.Audio.AudioColumns;\r
19 import android.provider.MediaStore.Audio.Genres;\r
20 import android.provider.MediaStore.Audio.Playlists;\r
21 import android.provider.MediaStore.MediaColumns;\r
22 import android.support.v4.app.Fragment;\r
23 import android.support.v4.app.LoaderManager.LoaderCallbacks;\r
24 import android.support.v4.content.CursorLoader;\r
25 import android.support.v4.content.Loader;\r
26 import android.view.ContextMenu;\r
27 import android.view.ContextMenu.ContextMenuInfo;\r
28 import android.view.LayoutInflater;\r
29 import android.view.MenuItem;\r
30 import android.view.View;\r
31 import android.view.ViewGroup;\r
32 import android.widget.AdapterView;\r
33 import android.widget.AdapterView.AdapterContextMenuInfo;\r
34 import android.widget.AdapterView.OnItemClickListener;\r
35 import android.widget.LinearLayout;\r
36 import android.widget.ListView;\r
37 import android.widget.TextView;\r
38 \r
39 import com.andrew.apollo.Constants;\r
40 import com.andrew.apollo.NowPlayingCursor;\r
41 import com.andrew.apollo.R;\r
42 import com.andrew.apollo.adapters.TrackAdapter;\r
43 import com.andrew.apollo.service.ApolloService;\r
44 import com.andrew.apollo.utils.ApolloUtils;\r
45 import com.andrew.apollo.utils.MusicUtils;\r
46 \r
47 /**\r
48  * @author Andrew Neal\r
49  */\r
50 public class TracksFragment extends Fragment implements LoaderCallbacks<Cursor>,\r
51         OnItemClickListener, Constants {\r
52 \r
53     // Adapter\r
54     private TrackAdapter mTrackAdapter;\r
55 \r
56     // ListView\r
57     private ListView mListView;\r
58 \r
59     // Cursor\r
60     private Cursor mCursor;\r
61 \r
62     // Playlist ID\r
63     private long mPlaylistId = -1;\r
64 \r
65     // Selected position\r
66     private int mSelectedPosition;\r
67 \r
68     // Used to set ringtone\r
69     private long mSelectedId;\r
70 \r
71     // Options\r
72     private final int PLAY_SELECTION = 6;\r
73 \r
74     private final int USE_AS_RINGTONE = 7;\r
75 \r
76     private final int ADD_TO_PLAYLIST = 8;\r
77 \r
78     private final int SEARCH = 9;\r
79 \r
80     private final int REMOVE = 10;\r
81 \r
82     private boolean mEditMode = false;\r
83 \r
84     // Audio columns\r
85     public static int mTitleIndex, mAlbumIndex, mArtistIndex, mMediaIdIndex;\r
86 \r
87     // Bundle\r
88     public TracksFragment() {\r
89     }\r
90 \r
91     public TracksFragment(Bundle args) {\r
92         setArguments(args);\r
93     }\r
94 \r
95     @Override\r
96     public void onActivityCreated(Bundle savedInstanceState) {\r
97         super.onActivityCreated(savedInstanceState);\r
98 \r
99         isEditMode();\r
100 \r
101         // Adapter\r
102         mTrackAdapter = new TrackAdapter(getActivity(), R.layout.listview_items, null,\r
103                 new String[] {}, new int[] {}, 0);\r
104         mListView.setOnCreateContextMenuListener(this);\r
105         mListView.setOnItemClickListener(this);\r
106         mListView.setAdapter(mTrackAdapter);\r
107 \r
108         // Important!\r
109         getLoaderManager().initLoader(0, null, this);\r
110     }\r
111 \r
112     @Override\r
113     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {\r
114         View root = inflater.inflate(R.layout.listview, container, false);\r
115         mListView = (ListView)root.findViewById(android.R.id.list);\r
116 \r
117         // Align the track list with the header, in other words,OCD.\r
118         TextView mHeader = (TextView)root.findViewById(R.id.title);\r
119         int eight = (int)getActivity().getResources().getDimension(\r
120                 R.dimen.list_separator_padding_left_right);\r
121         mHeader.setPadding(eight, 0, 0, 0);\r
122 \r
123         // Set the header while in @TracksBrowser\r
124         String header = getActivity().getResources().getString(R.string.track_header);\r
125         int left = getActivity().getResources().getInteger(R.integer.listview_padding_left);\r
126         int right = getActivity().getResources().getInteger(R.integer.listview_padding_right);\r
127         ApolloUtils.listHeader(this, root, header);\r
128         ApolloUtils.setListPadding(this, mListView, left, 0, right, 0);\r
129 \r
130         // Hide the extra spacing from the Bottom ActionBar in the queue\r
131         // Fragment in @AudioPlayerHolder\r
132         if (getArguments() != null) {\r
133             mPlaylistId = getArguments().getLong(BaseColumns._ID);\r
134             String mimeType = getArguments().getString(MIME_TYPE);\r
135             if (Audio.Playlists.CONTENT_TYPE.equals(mimeType)) {\r
136                 switch ((int)mPlaylistId) {\r
137                     case (int)PLAYLIST_QUEUE:\r
138                         LinearLayout emptyness = (LinearLayout)root.findViewById(R.id.empty_view);\r
139                         emptyness.setVisibility(View.GONE);\r
140                 }\r
141             }\r
142         }\r
143         return root;\r
144     }\r
145 \r
146     @Override\r
147     public Loader<Cursor> onCreateLoader(int id, Bundle args) {\r
148         String[] projection = new String[] {\r
149                 BaseColumns._ID, MediaColumns.TITLE, AudioColumns.ALBUM, AudioColumns.ARTIST\r
150         };\r
151         StringBuilder where = new StringBuilder();\r
152         String sortOrder = Audio.Media.DEFAULT_SORT_ORDER;\r
153         where.append(AudioColumns.IS_MUSIC + "=1").append(" AND " + MediaColumns.TITLE + " != ''");\r
154         Uri uri = Audio.Media.EXTERNAL_CONTENT_URI;\r
155         if (getArguments() != null) {\r
156             mPlaylistId = getArguments().getLong(BaseColumns._ID);\r
157             String mimeType = getArguments().getString(MIME_TYPE);\r
158             if (Audio.Playlists.CONTENT_TYPE.equals(mimeType)) {\r
159                 where = new StringBuilder();\r
160                 where.append(AudioColumns.IS_MUSIC + "=1");\r
161                 where.append(" AND " + MediaColumns.TITLE + " != ''");\r
162                 switch ((int)mPlaylistId) {\r
163                     case (int)PLAYLIST_QUEUE:\r
164                         uri = Audio.Media.EXTERNAL_CONTENT_URI;\r
165                         long[] mNowPlaying = MusicUtils.getQueue();\r
166                         if (mNowPlaying.length == 0)\r
167                             return null;\r
168                         where = new StringBuilder();\r
169                         where.append(BaseColumns._ID + " IN (");\r
170                         if (mNowPlaying == null || mNowPlaying.length <= 0)\r
171                             return null;\r
172                         for (long queue_id : mNowPlaying) {\r
173                             where.append(queue_id + ",");\r
174                         }\r
175                         where.deleteCharAt(where.length() - 1);\r
176                         where.append(")");\r
177                         break;\r
178                     case (int)PLAYLIST_FAVORITES:\r
179                         long favorites_id = MusicUtils.getFavoritesId(getActivity());\r
180                         projection = new String[] {\r
181                                 Playlists.Members._ID, Playlists.Members.AUDIO_ID,\r
182                                 MediaColumns.TITLE, AudioColumns.ALBUM, AudioColumns.ARTIST\r
183                         };\r
184                         uri = Playlists.Members.getContentUri(EXTERNAL, favorites_id);\r
185                         sortOrder = Playlists.Members.DEFAULT_SORT_ORDER;\r
186                         break;\r
187                     default:\r
188                         if (id < 0)\r
189                             return null;\r
190                         projection = new String[] {\r
191                                 Playlists.Members._ID, Playlists.Members.AUDIO_ID,\r
192                                 MediaColumns.TITLE, AudioColumns.ALBUM, AudioColumns.ARTIST,\r
193                                 AudioColumns.DURATION\r
194                         };\r
195 \r
196                         uri = Playlists.Members.getContentUri(EXTERNAL, mPlaylistId);\r
197                         sortOrder = Playlists.Members.DEFAULT_SORT_ORDER;\r
198                         break;\r
199                 }\r
200             } else if (Audio.Genres.CONTENT_TYPE.equals(mimeType)) {\r
201                 long genreId = getArguments().getLong(BaseColumns._ID);\r
202                 uri = Genres.Members.getContentUri(EXTERNAL, genreId);\r
203                 projection = new String[] {\r
204                         BaseColumns._ID, MediaColumns.TITLE, AudioColumns.ALBUM,\r
205                         AudioColumns.ARTIST\r
206                 };\r
207                 where = new StringBuilder();\r
208                 where.append(AudioColumns.IS_MUSIC + "=1").append(\r
209                         " AND " + MediaColumns.TITLE + " != ''");\r
210                 sortOrder = Genres.Members.DEFAULT_SORT_ORDER;\r
211             } else {\r
212                 if (Audio.Albums.CONTENT_TYPE.equals(mimeType)) {\r
213                     long albumId = getArguments().getLong(BaseColumns._ID);\r
214                     where.append(" AND " + AudioColumns.ALBUM_ID + "=" + albumId);\r
215                     sortOrder = Audio.Media.TRACK + ", " + sortOrder;\r
216                 } else if (Audio.Artists.CONTENT_TYPE.equals(mimeType)) {\r
217                     sortOrder = MediaColumns.TITLE;\r
218                     long artist_id = getArguments().getLong(BaseColumns._ID);\r
219                     where.append(" AND " + AudioColumns.ARTIST_ID + "=" + artist_id);\r
220                 }\r
221             }\r
222         }\r
223         return new CursorLoader(getActivity(), uri, projection, where.toString(), null, sortOrder);\r
224     }\r
225 \r
226     @Override\r
227     public void onLoadFinished(Loader<Cursor> loader, Cursor data) {\r
228         // Check for database errors\r
229         if (data == null) {\r
230             return;\r
231         }\r
232 \r
233         if (getArguments() != null\r
234                 && Playlists.CONTENT_TYPE.equals(getArguments().getString(MIME_TYPE))\r
235                 && (getArguments().getLong(BaseColumns._ID) >= 0 || getArguments().getLong(\r
236                         BaseColumns._ID) == PLAYLIST_FAVORITES)) {\r
237             mMediaIdIndex = data.getColumnIndexOrThrow(Playlists.Members.AUDIO_ID);\r
238             mTitleIndex = data.getColumnIndexOrThrow(MediaColumns.TITLE);\r
239             mAlbumIndex = data.getColumnIndexOrThrow(AudioColumns.ALBUM);\r
240             // FIXME\r
241             // mArtistIndex =\r
242             // data.getColumnIndexOrThrow(Playlists.Members.ARTIST);\r
243         } else if (getArguments() != null\r
244                 && Genres.CONTENT_TYPE.equals(getArguments().getString(MIME_TYPE))) {\r
245             mMediaIdIndex = data.getColumnIndexOrThrow(BaseColumns._ID);\r
246             mTitleIndex = data.getColumnIndexOrThrow(MediaColumns.TITLE);\r
247             mArtistIndex = data.getColumnIndexOrThrow(AudioColumns.ARTIST);\r
248             mAlbumIndex = data.getColumnIndexOrThrow(AudioColumns.ALBUM);\r
249         } else if (getArguments() != null\r
250                 && Artists.CONTENT_TYPE.equals(getArguments().getString(MIME_TYPE))) {\r
251             mTitleIndex = data.getColumnIndexOrThrow(MediaColumns.TITLE);\r
252             // mArtistIndex is "line2" of the ListView\r
253             mArtistIndex = data.getColumnIndexOrThrow(AudioColumns.ALBUM);\r
254         } else if (getArguments() != null\r
255                 && Albums.CONTENT_TYPE.equals(getArguments().getString(MIME_TYPE))) {\r
256             mMediaIdIndex = data.getColumnIndexOrThrow(BaseColumns._ID);\r
257             mTitleIndex = data.getColumnIndexOrThrow(MediaColumns.TITLE);\r
258             mArtistIndex = data.getColumnIndexOrThrow(AudioColumns.ARTIST);\r
259         } else {\r
260             mMediaIdIndex = data.getColumnIndexOrThrow(BaseColumns._ID);\r
261             mTitleIndex = data.getColumnIndexOrThrow(MediaColumns.TITLE);\r
262             mArtistIndex = data.getColumnIndexOrThrow(AudioColumns.ARTIST);\r
263             mAlbumIndex = data.getColumnIndexOrThrow(AudioColumns.ALBUM);\r
264         }\r
265         mTrackAdapter.changeCursor(data);\r
266         mCursor = data;\r
267     }\r
268 \r
269     @Override\r
270     public void onLoaderReset(Loader<Cursor> loader) {\r
271         if (mTrackAdapter != null)\r
272             mTrackAdapter.changeCursor(null);\r
273     }\r
274 \r
275     @Override\r
276     public void onSaveInstanceState(Bundle outState) {\r
277         outState.putAll(getArguments() != null ? getArguments() : new Bundle());\r
278         super.onSaveInstanceState(outState);\r
279     }\r
280 \r
281     @Override\r
282     public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {\r
283         menu.add(0, PLAY_SELECTION, 0, getResources().getString(R.string.play_all));\r
284         menu.add(0, ADD_TO_PLAYLIST, 0, getResources().getString(R.string.add_to_playlist));\r
285         menu.add(0, USE_AS_RINGTONE, 0, getResources().getString(R.string.use_as_ringtone));\r
286         if (mEditMode) {\r
287             menu.add(0, REMOVE, 0, R.string.remove);\r
288         }\r
289         menu.add(0, SEARCH, 0, getResources().getString(R.string.search));\r
290 \r
291         AdapterContextMenuInfo mi = (AdapterContextMenuInfo)menuInfo;\r
292         mSelectedPosition = mi.position;\r
293         mCursor.moveToPosition(mSelectedPosition);\r
294 \r
295         try {\r
296             mSelectedId = mCursor.getLong(mMediaIdIndex);\r
297         } catch (IllegalArgumentException ex) {\r
298             mSelectedId = mi.id;\r
299         }\r
300 \r
301         String title = mCursor.getString(mTitleIndex);\r
302         menu.setHeaderTitle(title);\r
303         super.onCreateContextMenu(menu, v, menuInfo);\r
304     }\r
305 \r
306     @Override\r
307     public boolean onContextItemSelected(MenuItem item) {\r
308         switch (item.getItemId()) {\r
309             case PLAY_SELECTION:\r
310                 int position = mSelectedPosition;\r
311                 MusicUtils.playAll(getActivity(), mCursor, position);\r
312                 break;\r
313             case ADD_TO_PLAYLIST: {\r
314                 Intent intent = new Intent(INTENT_ADD_TO_PLAYLIST);\r
315                 long[] list = new long[] {\r
316                     mSelectedId\r
317                 };\r
318                 intent.putExtra(INTENT_PLAYLIST_LIST, list);\r
319                 getActivity().startActivity(intent);\r
320                 break;\r
321             }\r
322             case USE_AS_RINGTONE:\r
323                 MusicUtils.setRingtone(getActivity(), mSelectedId);\r
324                 break;\r
325             case REMOVE: {\r
326                 removePlaylistItem(mSelectedPosition);\r
327                 break;\r
328             }\r
329             case SEARCH: {\r
330                 MusicUtils.doSearch(getActivity(), mCursor, mTitleIndex);\r
331                 break;\r
332             }\r
333             default:\r
334                 break;\r
335         }\r
336         return super.onContextItemSelected(item);\r
337     }\r
338 \r
339     @Override\r
340     public void onItemClick(AdapterView<?> parent, View v, int position, long id) {\r
341         if (mCursor instanceof NowPlayingCursor) {\r
342             if (MusicUtils.mService != null) {\r
343                 MusicUtils.setQueuePosition(position);\r
344                 return;\r
345             }\r
346         }\r
347         MusicUtils.playAll(getActivity(), mCursor, position);\r
348     }\r
349 \r
350     /**\r
351      * Update the list as needed\r
352      */\r
353     private final BroadcastReceiver mMediaStatusReceiver = new BroadcastReceiver() {\r
354 \r
355         @Override\r
356         public void onReceive(Context context, Intent intent) {\r
357             if (mListView != null) {\r
358                 mTrackAdapter.notifyDataSetChanged();\r
359                 // Scroll to the currently playing track in the queue\r
360                 if (mPlaylistId == PLAYLIST_QUEUE)\r
361                     mListView.postDelayed(new Runnable() {\r
362                         @Override\r
363                         public void run() {\r
364                             mListView.setSelection(MusicUtils.getQueuePosition());\r
365                         }\r
366                     }, 100);\r
367             }\r
368         }\r
369 \r
370     };\r
371 \r
372     @Override\r
373     public void onStart() {\r
374         super.onStart();\r
375 \r
376         IntentFilter filter = new IntentFilter();\r
377         filter.addAction(ApolloService.META_CHANGED);\r
378         filter.addAction(ApolloService.QUEUE_CHANGED);\r
379         filter.addAction(ApolloService.PLAYSTATE_CHANGED);\r
380         getActivity().registerReceiver(mMediaStatusReceiver, filter);\r
381     }\r
382 \r
383     @Override\r
384     public void onStop() {\r
385         getActivity().unregisterReceiver(mMediaStatusReceiver);\r
386         super.onStop();\r
387     }\r
388 \r
389     /**\r
390      * @param which\r
391      */\r
392     private void removePlaylistItem(int which) {\r
393 \r
394         mCursor.moveToPosition(which);\r
395         long id = mCursor.getLong(mMediaIdIndex);\r
396         if (mPlaylistId >= 0) {\r
397             Uri uri = Playlists.Members.getContentUri(EXTERNAL, mPlaylistId);\r
398             getActivity().getContentResolver().delete(uri, Playlists.Members.AUDIO_ID + "=" + id,\r
399                     null);\r
400         } else if (mPlaylistId == PLAYLIST_QUEUE) {\r
401             MusicUtils.removeTrack(id);\r
402             reloadQueueCursor();\r
403         } else if (mPlaylistId == PLAYLIST_FAVORITES) {\r
404             MusicUtils.removeFromFavorites(getActivity(), id);\r
405         }\r
406         mListView.invalidateViews();\r
407     }\r
408 \r
409     /**\r
410      * Reload the queue after we remove a track\r
411      */\r
412     private void reloadQueueCursor() {\r
413         if (mPlaylistId == PLAYLIST_QUEUE) {\r
414             String[] cols = new String[] {\r
415                     BaseColumns._ID, MediaColumns.TITLE, MediaColumns.DATA, AudioColumns.ALBUM,\r
416                     AudioColumns.ARTIST, AudioColumns.ARTIST_ID\r
417             };\r
418             StringBuilder selection = new StringBuilder();\r
419             selection.append(AudioColumns.IS_MUSIC + "=1");\r
420             selection.append(" AND " + MediaColumns.TITLE + " != ''");\r
421             Uri uri = Audio.Media.EXTERNAL_CONTENT_URI;\r
422             long[] mNowPlaying = MusicUtils.getQueue();\r
423             if (mNowPlaying.length == 0) {\r
424             }\r
425             selection = new StringBuilder();\r
426             selection.append(BaseColumns._ID + " IN (");\r
427             for (int i = 0; i < mNowPlaying.length; i++) {\r
428                 selection.append(mNowPlaying[i]);\r
429                 if (i < mNowPlaying.length - 1) {\r
430                     selection.append(",");\r
431                 }\r
432             }\r
433             selection.append(")");\r
434             mCursor = MusicUtils.query(getActivity(), uri, cols, selection.toString(), null, null);\r
435             mTrackAdapter.changeCursor(mCursor);\r
436         }\r
437     }\r
438 \r
439     /**\r
440      * Check if we're viewing the contents of a playlist\r
441      */\r
442     public void isEditMode() {\r
443         if (getArguments() != null) {\r
444             String mimetype = getArguments().getString(MIME_TYPE);\r
445             if (Audio.Playlists.CONTENT_TYPE.equals(mimetype)) {\r
446                 mPlaylistId = getArguments().getLong(BaseColumns._ID);\r
447                 switch ((int)mPlaylistId) {\r
448                     case (int)PLAYLIST_QUEUE:\r
449                         mEditMode = true;\r
450                         break;\r
451                     case (int)PLAYLIST_FAVORITES:\r
452                         mEditMode = true;\r
453                         break;\r
454                     default:\r
455                         if (mPlaylistId > 0) {\r
456                             mEditMode = true;\r
457                         }\r
458                         break;\r
459                 }\r
460             }\r
461         }\r
462     }\r
463 }\r