blob: a582e6107f7db61eab74e7eb33657d064891d397 [file] [log] [blame]
The Android Open Source Project792a2202009-03-03 19:32:30 -08001/*
2 * Copyright (C) 2007 The Android Open Source 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
17package com.android.music;
18
The Android Open Source Project792a2202009-03-03 19:32:30 -080019import android.app.ListActivity;
20import android.content.AsyncQueryHandler;
21import android.content.BroadcastReceiver;
22import android.content.ComponentName;
23import android.content.ContentResolver;
24import android.content.ContentUris;
25import android.content.Context;
26import android.content.Intent;
27import android.content.IntentFilter;
28import android.content.ServiceConnection;
The Android Open Source Project792a2202009-03-03 19:32:30 -080029import android.database.Cursor;
Marco Nelissen9825b3c2010-01-04 16:55:00 -080030import android.database.MatrixCursor;
The Android Open Source Project792a2202009-03-03 19:32:30 -080031import android.database.MergeCursor;
32import android.database.sqlite.SQLiteException;
33import android.media.AudioManager;
34import android.net.Uri;
35import android.os.Bundle;
36import android.os.Handler;
37import android.os.IBinder;
38import android.os.Message;
39import android.provider.MediaStore;
40import android.util.Log;
41import android.view.ContextMenu;
42import android.view.Menu;
43import android.view.MenuItem;
44import android.view.View;
45import android.view.ViewGroup;
46import android.view.Window;
47import android.view.ContextMenu.ContextMenuInfo;
48import android.widget.ImageView;
49import android.widget.ListView;
50import android.widget.SimpleCursorAdapter;
51import android.widget.TextView;
52import android.widget.Toast;
53import android.widget.AdapterView.AdapterContextMenuInfo;
54
Marco Nelissen9825b3c2010-01-04 16:55:00 -080055import java.text.Collator;
56import java.util.ArrayList;
57
The Android Open Source Project792a2202009-03-03 19:32:30 -080058public class PlaylistBrowserActivity extends ListActivity
59 implements View.OnCreateContextMenuListener, MusicUtils.Defs
60{
61 private static final String TAG = "PlaylistBrowserActivity";
62 private static final int DELETE_PLAYLIST = CHILD_MENU_BASE + 1;
63 private static final int EDIT_PLAYLIST = CHILD_MENU_BASE + 2;
64 private static final int RENAME_PLAYLIST = CHILD_MENU_BASE + 3;
65 private static final int CHANGE_WEEKS = CHILD_MENU_BASE + 4;
66 private static final long RECENTLY_ADDED_PLAYLIST = -1;
67 private static final long ALL_SONGS_PLAYLIST = -2;
68 private static final long PODCASTS_PLAYLIST = -3;
69 private PlaylistListAdapter mAdapter;
70 boolean mAdapterSent;
Marco Nelissenec0c57a2009-12-12 12:27:11 -080071 private static int mLastListPosCourse = -1;
72 private static int mLastListPosFine = -1;
The Android Open Source Project792a2202009-03-03 19:32:30 -080073
74 private boolean mCreateShortcut;
75
76 public PlaylistBrowserActivity()
77 {
78 }
79
80 /** Called when the activity is first created. */
81 @Override
82 public void onCreate(Bundle icicle)
83 {
84 super.onCreate(icicle);
85
86 final Intent intent = getIntent();
87 final String action = intent.getAction();
88 if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) {
89 mCreateShortcut = true;
90 }
91
92 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
Marco Nelissenec0c57a2009-12-12 12:27:11 -080093 requestWindowFeature(Window.FEATURE_NO_TITLE);
The Android Open Source Project792a2202009-03-03 19:32:30 -080094 setVolumeControlStream(AudioManager.STREAM_MUSIC);
95 MusicUtils.bindToService(this, new ServiceConnection() {
96 public void onServiceConnected(ComponentName classname, IBinder obj) {
97 if (Intent.ACTION_VIEW.equals(action)) {
98 long id = Long.parseLong(intent.getExtras().getString("playlist"));
99 if (id == RECENTLY_ADDED_PLAYLIST) {
100 playRecentlyAdded();
101 } else if (id == PODCASTS_PLAYLIST) {
102 playPodcasts();
103 } else if (id == ALL_SONGS_PLAYLIST) {
Marco Nelissenbd447b62009-06-29 14:52:05 -0700104 long [] list = MusicUtils.getAllSongs(PlaylistBrowserActivity.this);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800105 if (list != null) {
106 MusicUtils.playAll(PlaylistBrowserActivity.this, list, 0);
107 }
108 } else {
109 MusicUtils.playPlaylist(PlaylistBrowserActivity.this, id);
110 }
111 finish();
Marco Nelissenec0c57a2009-12-12 12:27:11 -0800112 return;
The Android Open Source Project792a2202009-03-03 19:32:30 -0800113 }
Marco Nelissenec0c57a2009-12-12 12:27:11 -0800114 MusicUtils.updateNowPlaying(PlaylistBrowserActivity.this);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800115 }
116
117 public void onServiceDisconnected(ComponentName classname) {
118 }
119
120 });
121 IntentFilter f = new IntentFilter();
122 f.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
123 f.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
124 f.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
125 f.addDataScheme("file");
126 registerReceiver(mScanListener, f);
127
128 setContentView(R.layout.media_picker_activity);
Marco Nelissenec0c57a2009-12-12 12:27:11 -0800129 MusicUtils.updateButtonBar(this, R.id.playlisttab);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800130 ListView lv = getListView();
131 lv.setOnCreateContextMenuListener(this);
132 lv.setTextFilterEnabled(true);
133
134 mAdapter = (PlaylistListAdapter) getLastNonConfigurationInstance();
135 if (mAdapter == null) {
136 //Log.i("@@@", "starting query");
137 mAdapter = new PlaylistListAdapter(
138 getApplication(),
139 this,
140 R.layout.track_list_item,
141 mPlaylistCursor,
142 new String[] { MediaStore.Audio.Playlists.NAME},
143 new int[] { android.R.id.text1 });
144 setListAdapter(mAdapter);
145 setTitle(R.string.working_playlists);
146 getPlaylistCursor(mAdapter.getQueryHandler(), null);
147 } else {
148 mAdapter.setActivity(this);
149 setListAdapter(mAdapter);
150 mPlaylistCursor = mAdapter.getCursor();
151 // If mPlaylistCursor is null, this can be because it doesn't have
152 // a cursor yet (because the initial query that sets its cursor
153 // is still in progress), or because the query failed.
154 // In order to not flash the error dialog at the user for the
155 // first case, simply retry the query when the cursor is null.
156 // Worst case, we end up doing the same query twice.
157 if (mPlaylistCursor != null) {
158 init(mPlaylistCursor);
159 } else {
160 setTitle(R.string.working_playlists);
161 getPlaylistCursor(mAdapter.getQueryHandler(), null);
162 }
163 }
164 }
165
166 @Override
167 public Object onRetainNonConfigurationInstance() {
168 PlaylistListAdapter a = mAdapter;
169 mAdapterSent = true;
170 return a;
171 }
172
173 @Override
174 public void onDestroy() {
Marco Nelissenec0c57a2009-12-12 12:27:11 -0800175 ListView lv = getListView();
Marco Nelissen9e0f1fd2009-12-12 13:41:34 -0800176 if (lv != null) {
177 mLastListPosCourse = lv.getFirstVisiblePosition();
Marco Nelissen23b531e2009-12-12 14:07:59 -0800178 View cv = lv.getChildAt(0);
179 if (cv != null) {
180 mLastListPosFine = cv.getTop();
181 }
Marco Nelissen9e0f1fd2009-12-12 13:41:34 -0800182 }
The Android Open Source Project792a2202009-03-03 19:32:30 -0800183 MusicUtils.unbindFromService(this);
Marco Nelissen0e175782009-12-03 14:24:53 -0800184 // If we have an adapter and didn't send it off to another activity yet, we should
185 // close its cursor, which we do by assigning a null cursor to it. Doing this
186 // instead of closing the cursor directly keeps the framework from accessing
187 // the closed cursor later.
Marco Nelissen8e732ff2009-10-12 12:29:09 -0700188 if (!mAdapterSent && mAdapter != null) {
Marco Nelissen0e175782009-12-03 14:24:53 -0800189 mAdapter.changeCursor(null);
190 }
Marco Nelissen0164ebf2009-08-13 09:58:43 -0700191 // Because we pass the adapter to the next activity, we need to make
192 // sure it doesn't keep a reference to this activity. We can do this
193 // by clearing its DatasetObservers, which setListAdapter(null) does.
194 setListAdapter(null);
195 mAdapter = null;
The Android Open Source Project792a2202009-03-03 19:32:30 -0800196 unregisterReceiver(mScanListener);
197 super.onDestroy();
198 }
199
200 @Override
201 public void onResume() {
202 super.onResume();
203
204 MusicUtils.setSpinnerState(this);
Marco Nelissenec0c57a2009-12-12 12:27:11 -0800205 MusicUtils.updateNowPlaying(PlaylistBrowserActivity.this);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800206 }
207 @Override
208 public void onPause() {
209 mReScanHandler.removeCallbacksAndMessages(null);
210 super.onPause();
211 }
212 private BroadcastReceiver mScanListener = new BroadcastReceiver() {
213 @Override
214 public void onReceive(Context context, Intent intent) {
215 MusicUtils.setSpinnerState(PlaylistBrowserActivity.this);
216 mReScanHandler.sendEmptyMessage(0);
217 }
218 };
219
220 private Handler mReScanHandler = new Handler() {
Marco Nelissen42bcc212009-09-01 13:22:19 -0700221 @Override
The Android Open Source Project792a2202009-03-03 19:32:30 -0800222 public void handleMessage(Message msg) {
Marco Nelissen42bcc212009-09-01 13:22:19 -0700223 if (mAdapter != null) {
224 getPlaylistCursor(mAdapter.getQueryHandler(), null);
225 }
The Android Open Source Project792a2202009-03-03 19:32:30 -0800226 }
227 };
228 public void init(Cursor cursor) {
229
Marco Nelissen42bcc212009-09-01 13:22:19 -0700230 if (mAdapter == null) {
231 return;
232 }
The Android Open Source Project792a2202009-03-03 19:32:30 -0800233 mAdapter.changeCursor(cursor);
234
235 if (mPlaylistCursor == null) {
236 MusicUtils.displayDatabaseError(this);
237 closeContextMenu();
238 mReScanHandler.sendEmptyMessageDelayed(0, 1000);
239 return;
240 }
241
Marco Nelissenec0c57a2009-12-12 12:27:11 -0800242 // restore previous position
243 if (mLastListPosCourse >= 0) {
244 getListView().setSelectionFromTop(mLastListPosCourse, mLastListPosFine);
245 mLastListPosCourse = -1;
246 }
The Android Open Source Project792a2202009-03-03 19:32:30 -0800247 MusicUtils.hideDatabaseError(this);
Marco Nelissen9e0f1fd2009-12-12 13:41:34 -0800248 MusicUtils.updateButtonBar(this, R.id.playlisttab);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800249 setTitle();
250 }
251
252 private void setTitle() {
253 setTitle(R.string.playlists_title);
254 }
255
256 @Override
257 public boolean onCreateOptionsMenu(Menu menu) {
258 if (!mCreateShortcut) {
Marco Nelissenec0c57a2009-12-12 12:27:11 -0800259 menu.add(0, PARTY_SHUFFLE, 0, R.string.party_shuffle); // icon will be set in onPrepareOptionsMenu()
The Android Open Source Project792a2202009-03-03 19:32:30 -0800260 }
261 return super.onCreateOptionsMenu(menu);
262 }
263
264 @Override
Marco Nelissenec0c57a2009-12-12 12:27:11 -0800265 public boolean onPrepareOptionsMenu(Menu menu) {
266 MusicUtils.setPartyShuffleMenuIcon(menu);
267 return super.onPrepareOptionsMenu(menu);
268 }
269
270 @Override
The Android Open Source Project792a2202009-03-03 19:32:30 -0800271 public boolean onOptionsItemSelected(MenuItem item) {
272 Intent intent;
273 switch (item.getItemId()) {
Marco Nelissenec0c57a2009-12-12 12:27:11 -0800274 case PARTY_SHUFFLE:
275 MusicUtils.togglePartyShuffle();
276 break;
The Android Open Source Project792a2202009-03-03 19:32:30 -0800277 }
278 return super.onOptionsItemSelected(item);
279 }
280
281 public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfoIn) {
282 if (mCreateShortcut) {
283 return;
284 }
285
286 AdapterContextMenuInfo mi = (AdapterContextMenuInfo) menuInfoIn;
287
288 menu.add(0, PLAY_SELECTION, 0, R.string.play_selection);
289
290 if (mi.id >= 0 /*|| mi.id == PODCASTS_PLAYLIST*/) {
291 menu.add(0, DELETE_PLAYLIST, 0, R.string.delete_playlist_menu);
292 }
293
294 if (mi.id == RECENTLY_ADDED_PLAYLIST) {
295 menu.add(0, EDIT_PLAYLIST, 0, R.string.edit_playlist_menu);
296 }
297
298 if (mi.id >= 0) {
299 menu.add(0, RENAME_PLAYLIST, 0, R.string.rename_playlist_menu);
300 }
301
302 mPlaylistCursor.moveToPosition(mi.position);
303 menu.setHeaderTitle(mPlaylistCursor.getString(mPlaylistCursor.getColumnIndexOrThrow(
304 MediaStore.Audio.Playlists.NAME)));
305 }
306
307 @Override
308 public boolean onContextItemSelected(MenuItem item) {
309 AdapterContextMenuInfo mi = (AdapterContextMenuInfo) item.getMenuInfo();
310 switch (item.getItemId()) {
311 case PLAY_SELECTION:
312 if (mi.id == RECENTLY_ADDED_PLAYLIST) {
313 playRecentlyAdded();
314 } else if (mi.id == PODCASTS_PLAYLIST) {
315 playPodcasts();
316 } else {
317 MusicUtils.playPlaylist(this, mi.id);
318 }
319 break;
320 case DELETE_PLAYLIST:
321 Uri uri = ContentUris.withAppendedId(
322 MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, mi.id);
323 getContentResolver().delete(uri, null, null);
324 Toast.makeText(this, R.string.playlist_deleted_message, Toast.LENGTH_SHORT).show();
325 if (mPlaylistCursor.getCount() == 0) {
326 setTitle(R.string.no_playlists_title);
327 }
328 break;
329 case EDIT_PLAYLIST:
330 if (mi.id == RECENTLY_ADDED_PLAYLIST) {
331 Intent intent = new Intent();
332 intent.setClass(this, WeekSelector.class);
333 startActivityForResult(intent, CHANGE_WEEKS);
334 return true;
335 } else {
336 Log.e(TAG, "should not be here");
337 }
338 break;
339 case RENAME_PLAYLIST:
340 Intent intent = new Intent();
341 intent.setClass(this, RenamePlaylist.class);
342 intent.putExtra("rename", mi.id);
343 startActivityForResult(intent, RENAME_PLAYLIST);
344 break;
345 }
346 return true;
347 }
348
349 @Override
350 protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
351 switch (requestCode) {
352 case SCAN_DONE:
353 if (resultCode == RESULT_CANCELED) {
354 finish();
Marco Nelissen42bcc212009-09-01 13:22:19 -0700355 } else if (mAdapter != null) {
The Android Open Source Project792a2202009-03-03 19:32:30 -0800356 getPlaylistCursor(mAdapter.getQueryHandler(), null);
357 }
358 break;
359 }
360 }
361
362 @Override
363 protected void onListItemClick(ListView l, View v, int position, long id)
364 {
365 if (mCreateShortcut) {
366 final Intent shortcut = new Intent();
367 shortcut.setAction(Intent.ACTION_VIEW);
368 shortcut.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/playlist");
369 shortcut.putExtra("playlist", String.valueOf(id));
370
371 final Intent intent = new Intent();
372 intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcut);
373 intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, ((TextView) v.findViewById(R.id.line1)).getText());
374 intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(
Romain Guye013d772009-03-24 18:10:17 -0700375 this, R.drawable.ic_launcher_shortcut_music_playlist));
The Android Open Source Project792a2202009-03-03 19:32:30 -0800376
377 setResult(RESULT_OK, intent);
378 finish();
379 return;
380 }
381 if (id == RECENTLY_ADDED_PLAYLIST) {
382 Intent intent = new Intent(Intent.ACTION_PICK);
383 intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
384 intent.putExtra("playlist", "recentlyadded");
385 startActivity(intent);
386 } else if (id == PODCASTS_PLAYLIST) {
387 Intent intent = new Intent(Intent.ACTION_PICK);
388 intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
389 intent.putExtra("playlist", "podcasts");
390 startActivity(intent);
391 } else {
392 Intent intent = new Intent(Intent.ACTION_EDIT);
393 intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
394 intent.putExtra("playlist", Long.valueOf(id).toString());
395 startActivity(intent);
396 }
397 }
398
399 private void playRecentlyAdded() {
400 // do a query for all songs added in the last X weeks
401 int X = MusicUtils.getIntPref(this, "numweeks", 2) * (3600 * 24 * 7);
402 final String[] ccols = new String[] { MediaStore.Audio.Media._ID};
403 String where = MediaStore.MediaColumns.DATE_ADDED + ">" + (System.currentTimeMillis() / 1000 - X);
404 Cursor cursor = MusicUtils.query(this, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
405 ccols, where, null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
406
407 if (cursor == null) {
408 // Todo: show a message
409 return;
410 }
411 try {
412 int len = cursor.getCount();
Marco Nelissenbd447b62009-06-29 14:52:05 -0700413 long [] list = new long[len];
The Android Open Source Project792a2202009-03-03 19:32:30 -0800414 for (int i = 0; i < len; i++) {
415 cursor.moveToNext();
Marco Nelissenbd447b62009-06-29 14:52:05 -0700416 list[i] = cursor.getLong(0);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800417 }
418 MusicUtils.playAll(this, list, 0);
419 } catch (SQLiteException ex) {
420 } finally {
421 cursor.close();
422 }
423 }
424
425 private void playPodcasts() {
426 // do a query for all files that are podcasts
427 final String[] ccols = new String[] { MediaStore.Audio.Media._ID};
428 Cursor cursor = MusicUtils.query(this, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
429 ccols, MediaStore.Audio.Media.IS_PODCAST + "=1",
430 null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
431
432 if (cursor == null) {
433 // Todo: show a message
434 return;
435 }
436 try {
437 int len = cursor.getCount();
Marco Nelissenbd447b62009-06-29 14:52:05 -0700438 long [] list = new long[len];
The Android Open Source Project792a2202009-03-03 19:32:30 -0800439 for (int i = 0; i < len; i++) {
440 cursor.moveToNext();
Marco Nelissenbd447b62009-06-29 14:52:05 -0700441 list[i] = cursor.getLong(0);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800442 }
443 MusicUtils.playAll(this, list, 0);
444 } catch (SQLiteException ex) {
445 } finally {
446 cursor.close();
447 }
448 }
449
450
451 String[] mCols = new String[] {
452 MediaStore.Audio.Playlists._ID,
453 MediaStore.Audio.Playlists.NAME
454 };
455
456 private Cursor getPlaylistCursor(AsyncQueryHandler async, String filterstring) {
457
458 StringBuilder where = new StringBuilder();
459 where.append(MediaStore.Audio.Playlists.NAME + " != ''");
460
461 // Add in the filtering constraints
462 String [] keywords = null;
463 if (filterstring != null) {
464 String [] searchWords = filterstring.split(" ");
465 keywords = new String[searchWords.length];
466 Collator col = Collator.getInstance();
467 col.setStrength(Collator.PRIMARY);
468 for (int i = 0; i < searchWords.length; i++) {
469 keywords[i] = '%' + searchWords[i] + '%';
470 }
471 for (int i = 0; i < searchWords.length; i++) {
472 where.append(" AND ");
473 where.append(MediaStore.Audio.Playlists.NAME + " LIKE ?");
474 }
475 }
476
477 String whereclause = where.toString();
478
479
480 if (async != null) {
481 async.startQuery(0, null, MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
482 mCols, whereclause, keywords, MediaStore.Audio.Playlists.NAME);
483 return null;
484 }
485 Cursor c = null;
486 c = MusicUtils.query(this, MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
487 mCols, whereclause, keywords, MediaStore.Audio.Playlists.NAME);
488
489 return mergedCursor(c);
490 }
491
492 private Cursor mergedCursor(Cursor c) {
493 if (c == null) {
494 return null;
495 }
496 if (c instanceof MergeCursor) {
497 // this shouldn't happen, but fail gracefully
498 Log.d("PlaylistBrowserActivity", "Already wrapped");
499 return c;
500 }
Marco Nelissen9825b3c2010-01-04 16:55:00 -0800501 MatrixCursor autoplaylistscursor = new MatrixCursor(mCols);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800502 if (mCreateShortcut) {
503 ArrayList<Object> all = new ArrayList<Object>(2);
504 all.add(ALL_SONGS_PLAYLIST);
505 all.add(getString(R.string.play_all));
Marco Nelissen9825b3c2010-01-04 16:55:00 -0800506 autoplaylistscursor.addRow(all);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800507 }
508 ArrayList<Object> recent = new ArrayList<Object>(2);
509 recent.add(RECENTLY_ADDED_PLAYLIST);
510 recent.add(getString(R.string.recentlyadded));
Marco Nelissen9825b3c2010-01-04 16:55:00 -0800511 autoplaylistscursor.addRow(recent);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800512
513 // check if there are any podcasts
514 Cursor counter = MusicUtils.query(this, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
515 new String[] {"count(*)"}, "is_podcast=1", null, null);
516 if (counter != null) {
517 counter.moveToFirst();
518 int numpodcasts = counter.getInt(0);
519 counter.close();
520 if (numpodcasts > 0) {
521 ArrayList<Object> podcasts = new ArrayList<Object>(2);
522 podcasts.add(PODCASTS_PLAYLIST);
523 podcasts.add(getString(R.string.podcasts_listitem));
Marco Nelissen9825b3c2010-01-04 16:55:00 -0800524 autoplaylistscursor.addRow(podcasts);
The Android Open Source Project792a2202009-03-03 19:32:30 -0800525 }
526 }
527
The Android Open Source Project792a2202009-03-03 19:32:30 -0800528 Cursor cc = new MergeCursor(new Cursor [] {autoplaylistscursor, c});
529 return cc;
530 }
531
532 static class PlaylistListAdapter extends SimpleCursorAdapter {
533 int mTitleIdx;
534 int mIdIdx;
535 private PlaylistBrowserActivity mActivity = null;
536 private AsyncQueryHandler mQueryHandler;
537 private String mConstraint = null;
538 private boolean mConstraintIsValid = false;
539
540 class QueryHandler extends AsyncQueryHandler {
541 QueryHandler(ContentResolver res) {
542 super(res);
543 }
544
545 @Override
546 protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
547 //Log.i("@@@", "query complete: " + cursor.getCount() + " " + mActivity);
548 if (cursor != null) {
549 cursor = mActivity.mergedCursor(cursor);
550 }
551 mActivity.init(cursor);
552 }
553 }
554
555 PlaylistListAdapter(Context context, PlaylistBrowserActivity currentactivity,
556 int layout, Cursor cursor, String[] from, int[] to) {
557 super(context, layout, cursor, from, to);
558 mActivity = currentactivity;
559 getColumnIndices(cursor);
560 mQueryHandler = new QueryHandler(context.getContentResolver());
561 }
562 private void getColumnIndices(Cursor cursor) {
563 if (cursor != null) {
564 mTitleIdx = cursor.getColumnIndexOrThrow(MediaStore.Audio.Playlists.NAME);
565 mIdIdx = cursor.getColumnIndexOrThrow(MediaStore.Audio.Playlists._ID);
566 }
567 }
568
569 public void setActivity(PlaylistBrowserActivity newactivity) {
570 mActivity = newactivity;
571 }
572
573 public AsyncQueryHandler getQueryHandler() {
574 return mQueryHandler;
575 }
576
577 @Override
578 public void bindView(View view, Context context, Cursor cursor) {
579
580 TextView tv = (TextView) view.findViewById(R.id.line1);
581
582 String name = cursor.getString(mTitleIdx);
583 tv.setText(name);
584
585 long id = cursor.getLong(mIdIdx);
586
587 ImageView iv = (ImageView) view.findViewById(R.id.icon);
588 if (id == RECENTLY_ADDED_PLAYLIST) {
589 iv.setImageResource(R.drawable.ic_mp_playlist_recently_added_list);
590 } else {
591 iv.setImageResource(R.drawable.ic_mp_playlist_list);
592 }
593 ViewGroup.LayoutParams p = iv.getLayoutParams();
594 p.width = ViewGroup.LayoutParams.WRAP_CONTENT;
595 p.height = ViewGroup.LayoutParams.WRAP_CONTENT;
596
597 iv = (ImageView) view.findViewById(R.id.play_indicator);
598 iv.setVisibility(View.GONE);
599
600 view.findViewById(R.id.line2).setVisibility(View.GONE);
601 }
602
603 @Override
604 public void changeCursor(Cursor cursor) {
Marco Nelissend99bc1e2009-12-04 08:48:06 -0800605 if (mActivity.isFinishing() && cursor != null) {
606 cursor.close();
607 cursor = null;
Marco Nelissen0e175782009-12-03 14:24:53 -0800608 }
The Android Open Source Project792a2202009-03-03 19:32:30 -0800609 if (cursor != mActivity.mPlaylistCursor) {
610 mActivity.mPlaylistCursor = cursor;
611 super.changeCursor(cursor);
612 getColumnIndices(cursor);
613 }
614 }
615
616 @Override
617 public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
618 String s = constraint.toString();
619 if (mConstraintIsValid && (
620 (s == null && mConstraint == null) ||
621 (s != null && s.equals(mConstraint)))) {
622 return getCursor();
623 }
624 Cursor c = mActivity.getPlaylistCursor(null, s);
625 mConstraint = s;
626 mConstraintIsValid = true;
627 return c;
628 }
629 }
630
631 private Cursor mPlaylistCursor;
632}
633