OSDN Git Service

theme engine fixes
[android-x86/packages-apps-Eleven.git] / src / com / android / music / AlbumBrowserActivity.java
1 /*
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
17 package com.android.music;
18
19 import java.util.HashSet;
20
21 import android.app.ListActivity;
22 import android.app.SearchManager;
23 import android.content.AsyncQueryHandler;
24 import android.content.BroadcastReceiver;
25 import android.content.ComponentName;
26 import android.content.ContentResolver;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.IntentFilter;
30 import android.content.ServiceConnection;
31 import android.content.SharedPreferences;
32 import android.content.pm.PackageManager;
33 import android.content.pm.PackageManager.NameNotFoundException;
34 import android.content.res.Configuration;
35 import android.content.res.Resources;
36 import android.database.Cursor;
37 import android.database.sqlite.SQLiteException;
38 import android.graphics.Bitmap;
39 import android.graphics.BitmapFactory;
40 import android.graphics.drawable.AnimationDrawable;
41 import android.graphics.drawable.BitmapDrawable;
42 import android.graphics.drawable.Drawable;
43 import android.media.AudioManager;
44 import android.net.Uri;
45 import android.os.Bundle;
46 import android.os.Handler;
47 import android.os.IBinder;
48 import android.os.Message;
49 import android.os.RemoteException;
50 import android.provider.BaseColumns;
51 import android.provider.MediaStore;
52 import android.provider.MediaStore.Audio.AlbumColumns;
53 import android.provider.MediaStore.Audio.AudioColumns;
54 import android.text.TextUtils;
55 import android.util.Log;
56 import android.util.SparseBooleanArray;
57 import android.view.ActionMode;
58 import android.view.ContextMenu;
59 import android.view.ContextMenu.ContextMenuInfo;
60 import android.view.GestureDetector;
61 import android.view.GestureDetector.SimpleOnGestureListener;
62 import android.view.KeyEvent;
63 import android.view.LayoutInflater;
64 import android.view.Menu;
65 import android.view.MenuInflater;
66 import android.view.MenuItem;
67 import android.view.MotionEvent;
68 import android.view.SubMenu;
69 import android.view.View;
70 import android.view.ViewGroup;
71 import android.view.Window;
72 import android.widget.AdapterView.AdapterContextMenuInfo;
73 import android.widget.AlphabetIndexer;
74 import android.widget.FrameLayout;
75 import android.widget.ImageButton;
76 import android.widget.ImageView;
77 import android.widget.LinearLayout;
78 import android.widget.ListView;
79 import android.widget.ProgressBar;
80 import android.widget.RelativeLayout;
81 import android.widget.SectionIndexer;
82 import android.widget.SimpleCursorAdapter;
83 import android.widget.TabWidget;
84 import android.widget.TextView;
85
86 import com.android.music.MusicUtils.ServiceToken;
87
88 public class AlbumBrowserActivity extends ListActivity implements
89                 View.OnCreateContextMenuListener, MusicUtils.Defs, ServiceConnection {
90         private String mCurrentAlbumId;
91         private String mCurrentAlbumName;
92         private String mCurrentArtistNameForAlbum;
93         boolean mIsUnknownArtist;
94         boolean mIsUnknownAlbum;
95         private AlbumListAdapter mAdapter;
96         private boolean mAdapterSent;
97         private final static int SEARCH = CHILD_MENU_BASE;
98         private static int mLastListPosCourse = -1;
99         private static int mLastListPosFine = -1;
100         private ServiceToken mToken;
101         private ListView lv;
102         private IMediaPlaybackService mService = null;
103         private SharedPreferences mPreferences;
104         // Artist tab layout
105         public LinearLayout mAlbumTab;
106         public TabWidget mButtonBar;
107         public TextView mButtonBarArtist;
108         public TextView mButtonBarAlbum;
109         public TextView mButtonBarSong;
110         public TextView mButtonBarPlaylist;
111         public TextView mButtonBarNP;
112         public RelativeLayout mGroup;
113         public RelativeLayout mChild;
114         // Smaller now playing window buttons
115         private LinearLayout mNowPlaying;
116         private ImageView mInfoDivider;
117         private ProgressBar mProgress;
118         private ImageButton mDoSearch;
119         private ImageButton mMarket;
120         private ImageButton mNext;
121         private ImageButton mPlay;
122         private ImageButton mPlusPlaylist;
123         private ImageButton mPrev;
124         private ImageButton mShare;
125         private ImageButton mFlow;
126         // Back button long press
127         public String back_button_db;
128         // Smaller now playing window swipe gesture
129         public GestureDetector gestureDetector;
130         private static final int SWIPE_MIN_DISTANCE = 120;
131         private static final int SWIPE_MAX_OFF_PATH = 250;
132         private static final int SWIPE_THRESHOLD_VELOCITY = 200;
133         private String np_swipe_gesture_db;
134         // Swipe tabs
135         private GestureDetector swipetabs;
136         // ADW Theme constants
137         public static final int THEME_ITEM_BACKGROUND = 0;
138         public static final int THEME_ITEM_FOREGROUND = 1;
139         public static final int THEME_ITEM_TEXT_DRAWABLE = 2;
140
141         public AlbumBrowserActivity() {
142         }
143
144         /** Called when the activity is first created. */
145         @Override
146         public void onCreate(Bundle icicle) {
147                 if (icicle != null) {
148                         mCurrentAlbumId = icicle.getString("selectedalbum");
149                         mArtistId = icicle.getString("artist");
150                 } else {
151                         mArtistId = getIntent().getStringExtra("artist");
152                 }
153                 super.onCreate(icicle);
154                 mPreferences = getSharedPreferences(
155                                 MusicSettingsActivity.PREFERENCES_FILE, MODE_PRIVATE);
156
157                 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
158                 requestWindowFeature(Window.FEATURE_NO_TITLE);
159                 setVolumeControlStream(AudioManager.STREAM_MUSIC);
160
161                 IntentFilter f = new IntentFilter();
162                 f.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
163                 f.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
164                 f.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
165                 f.addDataScheme("file");
166                 registerReceiver(mScanListener, f);
167
168                 setContentView(R.layout.media_picker_activity);
169
170                 MusicUtils.updateButtonBar(this, R.id.albumtab);
171                 MusicUtils.updateNowPlaying(AlbumBrowserActivity.this);
172
173                 lv = (ListView) findViewById(android.R.id.list);
174                 lv.setTextFilterEnabled(true);
175                 lv.setOnCreateContextMenuListener(this);
176                 lv.setMultiChoiceModeListener(new ModeCallback());
177
178                 mToken = MusicUtils.bindToService(this, osc);
179
180                 // Swipe up gesture
181                 gestureDetector = new GestureDetector(new NowPlayingGesture());
182                 View nowplayingview = (View) findViewById(R.id.nowplaying);
183                 // Tab swipe
184                 swipetabs = new GestureDetector(new TabSwipe());
185                 View mainview = (View) findViewById(android.R.id.list);
186
187                 // Set the touch listener for the main view to be our custom gesture
188                 // listener
189                 mainview.setOnTouchListener(new View.OnTouchListener() {
190                         public boolean onTouch(View v, MotionEvent event) {
191                                 if (swipetabs.onTouchEvent(event)) {
192                                         return false;
193                                 }
194                                 return false;
195                         }
196                 });
197
198                 // Smaller now playing window buttons
199                 mShare = (ImageButton) findViewById(R.id.share_song);
200                 mPlay = (ImageButton) findViewById(R.id.media_play);
201                 mNext = (ImageButton) findViewById(R.id.media_next);
202                 mPrev = (ImageButton) findViewById(R.id.media_prev);
203                 mMarket = (ImageButton) findViewById(R.id.market_music);
204                 mDoSearch = (ImageButton) findViewById(R.id.doSearch);
205                 mPlusPlaylist = (ImageButton) findViewById(R.id.plus_playlist);
206                 mFlow = (ImageButton) findViewById(R.id.overFlow);
207                 // I found that without setting the onClickListeners in Portrait mode
208                 // only, flipping into Landscape force closes.
209                 if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
210                         // Smaller now playing window actions
211                         mDoSearch.setOnClickListener(mDoSearchListener);
212                         mMarket.setOnClickListener(mMarketSearch);
213                         mPlay.setOnClickListener(mMediaPlay);
214                         mNext.setOnClickListener(mMediaNext);
215                         mPrev.setOnClickListener(mMediaPrev);
216                         mShare.setOnClickListener(mShareSong);
217                         mFlow.setOnClickListener(mOverFlow);
218                         // I only want this to show in the Playlist activity
219                         mPlusPlaylist.setVisibility(View.GONE);
220                         // Swipe gesture
221                         nowplayingview.setOnTouchListener(new View.OnTouchListener() {
222                                 public boolean onTouch(View vee, MotionEvent nowplayingevent) {
223                                         if (gestureDetector.onTouchEvent(nowplayingevent)) {
224                                                 return false;
225                                         }
226                                         return false;
227                                 }
228                         });
229                 }
230                 // ADW: Load the specified theme
231                 String themePackage = MusicUtils.getThemePackageName(this,
232                                 MusicSettingsActivity.THEME_DEFAULT);
233                 PackageManager pm = getPackageManager();
234                 Resources themeResources = null;
235                 if (!themePackage.equals(MusicSettingsActivity.THEME_DEFAULT)) {
236                         try {
237                                 themeResources = pm.getResourcesForApplication(themePackage);
238                         } catch (NameNotFoundException e) {
239                                 // ADW The saved theme was uninstalled so we save the
240                                 // default one
241                                 MusicUtils.setThemePackageName(this,
242                                                 MusicSettingsActivity.THEME_DEFAULT);
243                         }
244                 }
245                 // Set Views for themes
246                 if (themeResources != null) {
247                         // Artist tab
248                         mAlbumTab = (LinearLayout) findViewById(R.id.album_tab);
249                         mButtonBar = (TabWidget) findViewById(R.id.buttonbar);
250                         mButtonBarArtist = (TextView) findViewById(R.id.artisttab);
251                         mButtonBarAlbum = (TextView) findViewById(R.id.albumtab);
252                         mButtonBarSong = (TextView) findViewById(R.id.songtab);
253                         mButtonBarPlaylist = (TextView) findViewById(R.id.playlisttab);
254                         mButtonBarNP = (TextView) findViewById(R.id.nowplayingtab);
255                         ArtistAlbumBrowserActivity
256                                         .loadThemeResource(themeResources, themePackage,
257                                                         "tab_album", mAlbumTab, THEME_ITEM_BACKGROUND);
258                         ArtistAlbumBrowserActivity.loadThemeResource(themeResources,
259                                         themePackage, "buttonbar", mButtonBar,
260                                         THEME_ITEM_BACKGROUND);
261                         ArtistAlbumBrowserActivity.loadThemeResource(themeResources,
262                                         themePackage, "tab_bg_artist", mButtonBarArtist,
263                                         THEME_ITEM_BACKGROUND);
264                         ArtistAlbumBrowserActivity.loadThemeResource(themeResources,
265                                         themePackage, "tab_bg_album", mButtonBarAlbum,
266                                         THEME_ITEM_BACKGROUND);
267                         ArtistAlbumBrowserActivity.loadThemeResource(themeResources,
268                                         themePackage, "tab_bg_song", mButtonBarSong,
269                                         THEME_ITEM_BACKGROUND);
270                         ArtistAlbumBrowserActivity.loadThemeResource(themeResources,
271                                         themePackage, "tab_bg_playlist", mButtonBarPlaylist,
272                                         THEME_ITEM_BACKGROUND);
273                         ArtistAlbumBrowserActivity.loadThemeResource(themeResources,
274                                         themePackage, "tab_bg_nowplaying", mButtonBarNP,
275                                         THEME_ITEM_BACKGROUND);
276                         // Small now playing window
277                         mNowPlaying = (LinearLayout) findViewById(R.id.nowplaying);
278                         mInfoDivider = (ImageView) findViewById(R.id.info_divider);
279                         mProgress = (ProgressBar) findViewById(R.id.progress);
280                         mShare = (ImageButton) findViewById(R.id.share_song);
281                         mPlay = (ImageButton) findViewById(R.id.media_play);
282                         mNext = (ImageButton) findViewById(R.id.media_next);
283                         mPrev = (ImageButton) findViewById(R.id.media_prev);
284                         mMarket = (ImageButton) findViewById(R.id.market_music);
285                         mDoSearch = (ImageButton) findViewById(R.id.doSearch);
286                         mFlow = (ImageButton) findViewById(R.id.overFlow);
287                         if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
288                                 ArtistAlbumBrowserActivity.loadThemeResource(themeResources,
289                                                 themePackage, "snp_background", mNowPlaying,
290                                                 THEME_ITEM_BACKGROUND);
291                                 ArtistAlbumBrowserActivity.loadThemeResource(themeResources,
292                                                 themePackage, "snp_progress", mProgress,
293                                                 THEME_ITEM_BACKGROUND);
294                                 ArtistAlbumBrowserActivity.loadThemeResource(themeResources,
295                                                 themePackage, "snp_info_divider", mInfoDivider,
296                                                 THEME_ITEM_BACKGROUND);
297                                 ArtistAlbumBrowserActivity.loadThemeResource(themeResources,
298                                                 themePackage, "snp_share", mShare,
299                                                 THEME_ITEM_FOREGROUND);
300                                 ArtistAlbumBrowserActivity.loadThemeResource(themeResources,
301                                                 themePackage, "snp_play", mPlay, THEME_ITEM_FOREGROUND);
302                                 ArtistAlbumBrowserActivity.loadThemeResource(themeResources,
303                                                 themePackage, "snp_next", mNext, THEME_ITEM_FOREGROUND);
304                                 ArtistAlbumBrowserActivity.loadThemeResource(themeResources,
305                                                 themePackage, "snp_prev", mPrev, THEME_ITEM_FOREGROUND);
306                                 ArtistAlbumBrowserActivity.loadThemeResource(themeResources,
307                                                 themePackage, "snp_market", mMarket,
308                                                 THEME_ITEM_FOREGROUND);
309                                 ArtistAlbumBrowserActivity.loadThemeResource(themeResources,
310                                                 themePackage, "snp_search", mDoSearch,
311                                                 THEME_ITEM_FOREGROUND);
312                                 ArtistAlbumBrowserActivity.loadThemeResource(themeResources,
313                                                 themePackage, "snp_flow", mFlow, THEME_ITEM_FOREGROUND);
314                         }
315                 }
316
317                 mAdapter = (AlbumListAdapter) getLastNonConfigurationInstance();
318                 if (mAdapter == null) {
319                         // Log.i("@@@", "starting query");
320                         mAdapter = new AlbumListAdapter(getApplication(), this,
321                                         R.layout.track_list_item, mAlbumCursor, new String[] {},
322                                         new int[] {});
323                         setListAdapter(mAdapter);
324                         setTitle(R.string.working_albums);
325                         getAlbumCursor(mAdapter.getQueryHandler(), null);
326                 } else {
327                         mAdapter.setActivity(this);
328                         setListAdapter(mAdapter);
329                         mAlbumCursor = mAdapter.getCursor();
330                         if (mAlbumCursor != null) {
331                                 init(mAlbumCursor);
332                         } else {
333                                 getAlbumCursor(mAdapter.getQueryHandler(), null);
334                         }
335                 }
336         }
337
338         private class ModeCallback implements ListView.MultiChoiceModeListener {
339                 private View mMultiSelectActionBarView;
340                 private TextView mSelectedConvCount;
341                 private HashSet<Long> mSelectedThreadIds;
342
343                 public boolean onCreateActionMode(ActionMode mode, Menu menu) {
344                         MenuInflater inflater = getMenuInflater();
345                         mSelectedThreadIds = new HashSet<Long>();
346                         inflater.inflate(R.menu.action_menu, menu);
347
348                         if (mMultiSelectActionBarView == null) {
349                                 mMultiSelectActionBarView = (ViewGroup) LayoutInflater.from(
350                                                 AlbumBrowserActivity.this).inflate(
351                                                 R.layout.action_menu_layout, null);
352
353                                 mSelectedConvCount = (TextView) mMultiSelectActionBarView
354                                                 .findViewById(R.id.selected_conv_count);
355                         }
356                         mode.setCustomView(mMultiSelectActionBarView);
357                         ((TextView) mMultiSelectActionBarView.findViewById(R.id.title))
358                                         .setText("Albums");
359
360                         return true;
361                 }
362
363                 public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
364                         if (mMultiSelectActionBarView == null) {
365
366                                 ViewGroup v = (ViewGroup) LayoutInflater.from(
367                                                 AlbumBrowserActivity.this).inflate(
368                                                 R.layout.action_menu_layout, null);
369                                 mode.setCustomView(v);
370
371                                 mSelectedConvCount = (TextView) v
372                                                 .findViewById(R.id.selected_conv_count);
373
374                         }
375                         return true;
376                 }
377
378                 public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
379                         int len = lv.getCount();
380                         SparseBooleanArray checked = lv.getCheckedItemPositions();
381                         switch (item.getItemId()) {
382                         case R.id.delete:
383                                 // This is used to do things in bulk.
384                                 for (int i = 0; i < len; i++)
385                                         if (checked.get(i)) {
386
387                                         }
388                                 mode.finish();
389                                 break;
390                         case R.id.add:
391                                 // This is used to do things in bulk.
392                                 for (int i = 0; i < len; i++)
393                                         if (checked.get(i)) {
394
395                                         }
396                                 mode.finish();
397                                 break;
398                         default:
399                                 break;
400                         }
401                         return true;
402                 }
403
404                 @Override
405                 public void onDestroyActionMode(ActionMode mode) {
406                 }
407
408                 public void onItemCheckedStateChanged(ActionMode mode, int position,
409                                 long id, boolean checked) {
410                         ListView listView = getListView();
411                         final int checkedCount = listView.getCheckedItemCount();
412                         mSelectedConvCount.setText(Integer.toString(checkedCount));
413
414                 }
415         }
416
417         @Override
418         public Object onRetainNonConfigurationInstance() {
419                 mAdapterSent = true;
420                 return mAdapter;
421         }
422
423         @Override
424         public void onSaveInstanceState(Bundle outcicle) {
425                 // need to store the selected item so we don't lose it in case
426                 // of an orientation switch. Otherwise we could lose it while
427                 // in the middle of specifying a playlist to add the item to.
428                 outcicle.putString("selectedalbum", mCurrentAlbumId);
429                 outcicle.putString("artist", mArtistId);
430                 super.onSaveInstanceState(outcicle);
431         }
432
433         // Tab Swipe
434         class TabSwipe extends SimpleOnGestureListener {
435                 @Override
436                 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
437                                 float velocityY) {
438                         Intent intent = new Intent(Intent.ACTION_PICK);
439
440                         try {
441                                 if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
442                                         return false;
443                                 if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
444                                                 && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
445                                         intent.setDataAndType(Uri.EMPTY,
446                                                         "vnd.android.cursor.dir/track");
447                                         intent.putExtra("withtabs", true);
448                                         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
449                                         startActivity(intent);
450                                         finish();
451                                         AlbumBrowserActivity.this.overridePendingTransition(
452                                                         R.anim.slide_in_right, R.anim.slide_out_left);
453                                         return true;
454                                 } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
455                                                 && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
456                                         intent.setDataAndType(Uri.EMPTY,
457                                                         "vnd.android.cursor.dir/artistalbum");
458                                         intent.putExtra("withtabs", true);
459                                         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
460                                         startActivity(intent);
461                                         finish();
462                                         AlbumBrowserActivity.this.overridePendingTransition(
463                                                         R.anim.slide_in_left, R.anim.slide_out_right);
464                                         return true;
465
466                                 }
467
468                         } catch (Exception e) {
469                                 Log.e("Fling", "There was an error processing the Fling event:"
470                                                 + e.getMessage());
471                         }
472                         return true;
473                 }
474
475                 // It is necessary to return true from onDown for the onFling event to
476                 // register
477                 @Override
478                 public boolean onDown(MotionEvent e) {
479                         return true;
480                 }
481         }
482
483         // Swipe gesture
484         class NowPlayingGesture extends SimpleOnGestureListener {
485                 @Override
486                 public boolean onFling(MotionEvent e3, MotionEvent e4, float vX,
487                                 float vY) {
488                         np_swipe_gesture_db = mPreferences.getString("np_swipe_gesture",
489                                         "0");
490                         if (np_swipe_gesture_db.equals("0")) {
491                                 if (e3.getY() - e4.getY() > SWIPE_MIN_DISTANCE
492                                                 && Math.abs(vY) > SWIPE_THRESHOLD_VELOCITY) {
493                                         // NONE
494                                 }
495                         }
496
497                         np_swipe_gesture_db = mPreferences.getString("np_swipe_gesture",
498                                         "1");
499                         if (np_swipe_gesture_db.equals("1")) {
500                                 if (e3.getY() - e4.getY() > SWIPE_MIN_DISTANCE
501                                                 && Math.abs(vY) > SWIPE_THRESHOLD_VELOCITY) {
502                                         doPauseResume();
503                                 }
504                         }
505
506                         np_swipe_gesture_db = mPreferences.getString("np_swipe_gesture",
507                                         "2");
508                         if (np_swipe_gesture_db.equals("2")) {
509                                 if (e3.getY() - e4.getY() > SWIPE_MIN_DISTANCE
510                                                 && Math.abs(vY) > SWIPE_THRESHOLD_VELOCITY) {
511                                         doNext();
512                                 }
513                         }
514                         np_swipe_gesture_db = mPreferences.getString("np_swipe_gesture",
515                                         "3");
516                         if (np_swipe_gesture_db.equals("3")) {
517                                 if (e3.getY() - e4.getY() > SWIPE_MIN_DISTANCE
518                                                 && Math.abs(vY) > SWIPE_THRESHOLD_VELOCITY) {
519                                         doPrev();
520                                 }
521                         }
522                         return false;
523
524                 }
525
526                 @Override
527                 public boolean onDown(MotionEvent f) {
528                         return true;
529                 }
530         }
531
532         // Smaller now playing window OnClickListerners
533         private View.OnClickListener mMarketSearch = new View.OnClickListener() {
534                 public void onClick(View v) {
535                         Uri marketUri = null;
536                         try {
537                                 marketUri = Uri.parse("market://search?q= "
538                                                 + mService.getArtistName());
539                         } catch (RemoteException e) {
540                                 // TODO Auto-generated catch block
541                                 e.printStackTrace();
542                         }
543                         Intent marketIntent = new Intent(Intent.ACTION_VIEW)
544                                         .setData(marketUri);
545                         startActivity(marketIntent);
546                         finish();
547
548                 }
549         };
550         private View.OnClickListener mShareSong = new View.OnClickListener() {
551
552                 @Override
553                 public void onClick(View v) {
554                         // TODO Auto-generated method stub
555                         try {
556                                 shareCurrentTrack();
557                         } catch (RemoteException e) {
558                                 // TODO Auto-generated catch block
559                                 e.printStackTrace();
560                         }
561
562                 }
563
564         };
565
566         private String shareCurrentTrack() throws RemoteException {
567                 if (mService.getTrackName() == null || mService.getArtistName() == null) {
568
569                 }
570
571                 Intent shareIntent = new Intent();
572                 String currentTrackMessage = "Now listening to: "
573                                 + mService.getTrackName() + " by " + mService.getArtistName();
574
575                 shareIntent.setAction(Intent.ACTION_SEND);
576                 shareIntent.setType("text/plain");
577                 shareIntent.putExtra(Intent.EXTRA_TEXT, currentTrackMessage);
578
579                 startActivity(Intent.createChooser(shareIntent, "Share track using"));
580                 return currentTrackMessage;
581         }
582
583         private View.OnClickListener mOverFlow = new View.OnClickListener() {
584                 public void onClick(View v) {
585                         openOptionsMenu();
586                 }
587         };
588         private View.OnClickListener mDoSearchListener = new View.OnClickListener() {
589                 public void onClick(View v) {
590                         onSearchRequested();
591                 }
592         };
593         private View.OnClickListener mMediaPlay = new View.OnClickListener() {
594                 public void onClick(View v) {
595                         doPauseResume();
596                 }
597         };
598         private View.OnClickListener mMediaNext = new View.OnClickListener() {
599                 public void onClick(View v) {
600                         doNext();
601                 }
602         };
603         private View.OnClickListener mMediaPrev = new View.OnClickListener() {
604                 public void onClick(View v) {
605                         doPrev();
606                 }
607         };
608
609         @Override
610         public void onDestroy() {
611                 ListView lv = getListView();
612                 if (lv != null) {
613                         mLastListPosCourse = lv.getFirstVisiblePosition();
614                         View cv = lv.getChildAt(0);
615                         if (cv != null) {
616                                 mLastListPosFine = cv.getTop();
617                         }
618                 }
619                 MusicUtils.unbindFromService(mToken);
620                 // If we have an adapter and didn't send it off to another activity yet,
621                 // we should
622                 // close its cursor, which we do by assigning a null cursor to it. Doing
623                 // this
624                 // instead of closing the cursor directly keeps the framework from
625                 // accessing
626                 // the closed cursor later.
627                 if (!mAdapterSent && mAdapter != null) {
628                         mAdapter.changeCursor(null);
629                 }
630                 // Because we pass the adapter to the next activity, we need to make
631                 // sure it doesn't keep a reference to this activity. We can do this
632                 // by clearing its DatasetObservers, which setListAdapter(null) does.
633                 setListAdapter(null);
634                 mAdapter = null;
635                 unregisterReceiver(mScanListener);
636                 super.onDestroy();
637         }
638
639         private void startPlayback() {
640
641                 if (mService == null)
642                         return;
643                 Intent intent = getIntent();
644                 String filename = "";
645                 Uri uri = intent.getData();
646                 if (uri != null && uri.toString().length() > 0) {
647                         // If this is a file:// URI, just use the path directly instead
648                         // of going through the open-from-filedescriptor codepath.
649                         String scheme = uri.getScheme();
650                         if ("file".equals(scheme)) {
651                                 filename = uri.getPath();
652                         } else {
653                                 filename = uri.toString();
654                         }
655                         try {
656                                 refreshProgress();
657                                 mService.stop();
658                                 mService.openFile(filename);
659                                 mService.play();
660                                 setIntent(new Intent());
661                         } catch (Exception ex) {
662                                 Log.d("MediaPlaybackActivity", "couldn't start playback: " + ex);
663                         }
664                 }
665         }
666
667         private ServiceConnection osc = new ServiceConnection() {
668                 public void onServiceConnected(ComponentName classname, IBinder obj) {
669                         mService = IMediaPlaybackService.Stub.asInterface(obj);
670                         startPlayback();
671                         // This is for orientation changes or entering the tab from a
672                         // different activity
673                         if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
674                                 setPauseButtonImage();
675                                 // This is so the controls will load correctly according to the
676                                 // user's settings
677                                 MusicUtils.updateNowPlaying(AlbumBrowserActivity.this);
678                         }
679                         try {
680                                 if (mService.getAudioId() >= 0 || mService.isPlaying()
681                                                 || mService.getPath() != null) {
682                                         return;
683                                 }
684                         } catch (RemoteException ex) {
685                         }
686                         if (getIntent().getData() == null) {
687                                 Intent intent = new Intent(Intent.ACTION_MAIN);
688                                 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
689                                 intent.setClass(AlbumBrowserActivity.this,
690                                                 MusicBrowserActivity.class);
691                                 startActivity(intent);
692                         }
693                 }
694
695                 public void onServiceDisconnected(ComponentName classname) {
696                         mService = null;
697                 }
698         };
699
700         @Override
701         public void onResume() {
702                 super.onResume();
703                 IntentFilter f = new IntentFilter();
704                 f.addAction(MediaPlaybackService.META_CHANGED);
705                 f.addAction(MediaPlaybackService.QUEUE_CHANGED);
706                 f.addAction(MediaPlaybackService.PROGRESSBAR_CHANGED);
707                 f.addAction(MediaPlaybackService.PLAYSTATE_CHANGED);
708                 registerReceiver(mTrackListListener, f);
709
710                 MusicUtils.setSpinnerState(this);
711         }
712
713         private BroadcastReceiver mTrackListListener = new BroadcastReceiver() {
714                 @Override
715                 public void onReceive(Context context, Intent intent) {
716                         String action = intent.getAction();
717                         getListView().invalidateViews();
718                         MusicUtils.updateNowPlaying(AlbumBrowserActivity.this);
719                         if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
720                                 refreshProgress();
721                                 if (action.equals(MediaPlaybackService.PLAYSTATE_CHANGED)) {
722                                         setPauseButtonImage();
723                                 }
724                         }
725                 }
726         };
727         private BroadcastReceiver mScanListener = new BroadcastReceiver() {
728                 @Override
729                 public void onReceive(Context context, Intent intent) {
730                         MusicUtils.setSpinnerState(AlbumBrowserActivity.this);
731                         mReScanHandler.sendEmptyMessage(0);
732                         if (intent.getAction().equals(Intent.ACTION_MEDIA_UNMOUNTED)) {
733                                 MusicUtils.clearAlbumArtCache();
734                         }
735                 }
736         };
737
738         private Handler mReScanHandler = new Handler() {
739                 @Override
740                 public void handleMessage(Message msg) {
741                         if (mAdapter != null) {
742                                 getAlbumCursor(mAdapter.getQueryHandler(), null);
743                         }
744                 }
745         };
746
747         @Override
748         public void onPause() {
749                 unregisterReceiver(mTrackListListener);
750                 mReScanHandler.removeCallbacksAndMessages(null);
751                 super.onPause();
752         }
753
754         public void init(Cursor c) {
755
756                 if (mAdapter == null) {
757                         return;
758                 }
759                 mAdapter.changeCursor(c); // also sets mAlbumCursor
760
761                 if (mAlbumCursor == null) {
762                         MusicUtils.displayDatabaseError(this);
763                         closeContextMenu();
764                         mReScanHandler.sendEmptyMessageDelayed(0, 1000);
765                         return;
766                 }
767
768                 // restore previous position
769                 if (mLastListPosCourse >= 0) {
770                         getListView().setSelectionFromTop(mLastListPosCourse,
771                                         mLastListPosFine);
772                         mLastListPosCourse = -1;
773                 }
774
775                 MusicUtils.hideDatabaseError(this);
776                 MusicUtils.updateButtonBar(this, R.id.albumtab);
777                 setTitle();
778         }
779
780         private void setTitle() {
781                 CharSequence fancyName = "";
782                 if (mAlbumCursor != null && mAlbumCursor.getCount() > 0) {
783                         mAlbumCursor.moveToFirst();
784                         fancyName = mAlbumCursor.getString(mAlbumCursor
785                                         .getColumnIndex(MediaStore.Audio.Albums.ARTIST));
786                         if (fancyName == null
787                                         || fancyName.equals(MediaStore.UNKNOWN_STRING))
788                                 fancyName = getText(R.string.unknown_artist_name);
789                 }
790
791                 if (mArtistId != null && fancyName != null)
792                         setTitle(fancyName);
793                 else
794                         setTitle(R.string.albums_title);
795         }
796
797         @Override
798         public void onCreateContextMenu(ContextMenu menu, View view,
799                         ContextMenuInfo menuInfoIn) {
800                 menu.add(0, PLAY_SELECTION, 0, R.string.play_selection);
801                 SubMenu sub = menu.addSubMenu(0, ADD_TO_PLAYLIST, 0,
802                                 R.string.add_to_playlist);
803                 MusicUtils.makePlaylistMenu(this, sub);
804                 menu.add(0, DELETE_ITEM, 0, R.string.delete_item);
805
806                 AdapterContextMenuInfo mi = (AdapterContextMenuInfo) menuInfoIn;
807                 mAlbumCursor.moveToPosition(mi.position);
808                 mCurrentAlbumId = mAlbumCursor.getString(mAlbumCursor
809                                 .getColumnIndexOrThrow(MediaStore.Audio.Albums._ID));
810                 mCurrentAlbumName = mAlbumCursor.getString(mAlbumCursor
811                                 .getColumnIndexOrThrow(MediaStore.Audio.Albums.ALBUM));
812                 mCurrentArtistNameForAlbum = mAlbumCursor.getString(mAlbumCursor
813                                 .getColumnIndexOrThrow(MediaStore.Audio.Albums.ARTIST));
814                 mIsUnknownArtist = mCurrentArtistNameForAlbum == null
815                                 || mCurrentArtistNameForAlbum.equals(MediaStore.UNKNOWN_STRING);
816                 mIsUnknownAlbum = mCurrentAlbumName == null
817                                 || mCurrentAlbumName.equals(MediaStore.UNKNOWN_STRING);
818                 if (mIsUnknownAlbum) {
819                         menu.setHeaderTitle(getString(R.string.unknown_album_name));
820                 } else {
821                         menu.setHeaderTitle(mCurrentAlbumName);
822                 }
823                 if (!mIsUnknownAlbum || !mIsUnknownArtist) {
824                         menu.add(0, SEARCH, 0, R.string.search_title);
825                 }
826         }
827
828         @Override
829         public boolean onContextItemSelected(MenuItem item) {
830                 switch (item.getItemId()) {
831                 case PLAY_SELECTION: {
832                         // play the selected album
833                         long[] list = MusicUtils.getSongListForAlbum(this,
834                                         Long.parseLong(mCurrentAlbumId));
835                         MusicUtils.playAll(this, list, 0);
836                         return true;
837                 }
838
839                 case QUEUE: {
840                         long[] list = MusicUtils.getSongListForAlbum(this,
841                                         Long.parseLong(mCurrentAlbumId));
842                         MusicUtils.addToCurrentPlaylist(this, list);
843                         return true;
844                 }
845
846                 case NEW_PLAYLIST: {
847                         Intent intent = new Intent();
848                         intent.setClass(this, CreatePlaylist.class);
849                         startActivityForResult(intent, NEW_PLAYLIST);
850                         return true;
851                 }
852
853                 case PLAYLIST_SELECTED: {
854                         long[] list = MusicUtils.getSongListForAlbum(this,
855                                         Long.parseLong(mCurrentAlbumId));
856                         long playlist = item.getIntent().getLongExtra("playlist", 0);
857                         MusicUtils.addToPlaylist(this, list, playlist);
858                         return true;
859                 }
860                 case DELETE_ITEM: {
861                         long[] list = MusicUtils.getSongListForAlbum(this,
862                                         Long.parseLong(mCurrentAlbumId));
863                         String f;
864                         if (android.os.Environment.isExternalStorageRemovable()) {
865                                 f = getString(R.string.delete_album_desc);
866                         } else {
867                                 f = getString(R.string.delete_album_desc_nosdcard);
868                         }
869                         String desc = String.format(f, mCurrentAlbumName);
870                         Bundle b = new Bundle();
871                         b.putString("description", desc);
872                         b.putLongArray("items", list);
873                         Intent intent = new Intent();
874                         intent.setClass(this, DeleteItems.class);
875                         intent.putExtras(b);
876                         startActivityForResult(intent, -1);
877                         return true;
878                 }
879                 case SEARCH:
880                         doSearch();
881                         return true;
882
883                 }
884                 return super.onContextItemSelected(item);
885         }
886
887         void doSearch() {
888                 CharSequence title = null;
889                 String query = "";
890
891                 Intent i = new Intent();
892                 i.setAction(MediaStore.INTENT_ACTION_MEDIA_SEARCH);
893                 i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
894
895                 title = "";
896                 if (!mIsUnknownAlbum) {
897                         query = mCurrentAlbumName;
898                         i.putExtra(MediaStore.EXTRA_MEDIA_ALBUM, mCurrentAlbumName);
899                         title = mCurrentAlbumName;
900                 }
901                 if (!mIsUnknownArtist) {
902                         query = query + " " + mCurrentArtistNameForAlbum;
903                         i.putExtra(MediaStore.EXTRA_MEDIA_ARTIST,
904                                         mCurrentArtistNameForAlbum);
905                         title = title + " " + mCurrentArtistNameForAlbum;
906                 }
907                 // Since we hide the 'search' menu item when both album and artist are
908                 // unknown, the query and title strings will have at least one of those.
909                 i.putExtra(MediaStore.EXTRA_MEDIA_FOCUS,
910                                 MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE);
911                 title = getString(R.string.mediasearch, title);
912                 i.putExtra(SearchManager.QUERY, query);
913
914                 startActivity(Intent.createChooser(i, title));
915         }
916
917         @Override
918         protected void onActivityResult(int requestCode, int resultCode,
919                         Intent intent) {
920                 switch (requestCode) {
921                 case SCAN_DONE:
922                         if (resultCode == RESULT_CANCELED) {
923                                 finish();
924                         } else {
925                                 getAlbumCursor(mAdapter.getQueryHandler(), null);
926                         }
927                         break;
928
929                 case NEW_PLAYLIST:
930                         if (resultCode == RESULT_OK) {
931                                 Uri uri = intent.getData();
932                                 if (uri != null) {
933                                         long[] list = MusicUtils.getSongListForAlbum(this,
934                                                         Long.parseLong(mCurrentAlbumId));
935                                         MusicUtils.addToPlaylist(this, list,
936                                                         Long.parseLong(uri.getLastPathSegment()));
937                                 }
938                         }
939                         break;
940                 }
941         }
942
943         @Override
944         protected void onListItemClick(ListView l, View v, int position, long id) {
945                 Intent intent = new Intent(Intent.ACTION_PICK);
946                 intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
947                 intent.putExtra("album", Long.valueOf(id).toString());
948                 intent.putExtra("artist", mArtistId);
949                 startActivity(intent);
950         }
951
952         @Override
953         public boolean onCreateOptionsMenu(Menu menu) {
954                 super.onCreateOptionsMenu(menu);
955                 menu.add(0, PARTY_SHUFFLE, 0, R.string.party_shuffle);
956                 menu.add(0, SHUFFLE_ALL, 0, R.string.shuffle_all);
957                 menu.add(0, SETTINGS, 0, R.string.settings);
958                 return true;
959         }
960
961         @Override
962         public boolean onPrepareOptionsMenu(Menu menu) {
963                 MusicUtils.setPartyShuffleMenuIcon(menu);
964                 return super.onPrepareOptionsMenu(menu);
965         }
966
967         @Override
968         public boolean onOptionsItemSelected(MenuItem item) {
969                 Intent intent;
970                 Cursor cursor;
971                 switch (item.getItemId()) {
972                 case PARTY_SHUFFLE:
973                         MusicUtils.togglePartyShuffle();
974                         break;
975
976                 case SHUFFLE_ALL:
977                         cursor = MusicUtils.query(this,
978                                         MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
979                                         new String[] { MediaStore.Audio.Media._ID },
980                                         MediaStore.Audio.Media.IS_MUSIC + "=1", null,
981                                         MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
982                         if (cursor != null) {
983                                 MusicUtils.shuffleAll(this, cursor);
984                                 cursor.close();
985                         }
986                         return true;
987                 case SETTINGS:
988                         intent = new Intent();
989                         intent.setClass(this, MusicSettingsActivity.class);
990                         startActivityForResult(intent, SETTINGS);
991                         return true;
992                 }
993                 return super.onOptionsItemSelected(item);
994         }
995
996         private Cursor getAlbumCursor(AsyncQueryHandler async, String filter) {
997                 String[] cols = new String[] { MediaStore.Audio.Albums._ID,
998                                 MediaStore.Audio.Albums.ARTIST, MediaStore.Audio.Albums.ALBUM,
999                                 MediaStore.Audio.Albums.ALBUM_ART };
1000
1001                 Cursor ret = null;
1002                 if (mArtistId != null) {
1003                         Uri uri = MediaStore.Audio.Artists.Albums.getContentUri("external",
1004                                         Long.valueOf(mArtistId));
1005                         if (!TextUtils.isEmpty(filter)) {
1006                                 uri = uri.buildUpon()
1007                                                 .appendQueryParameter("filter", Uri.encode(filter))
1008                                                 .build();
1009                         }
1010                         if (async != null) {
1011                                 async.startQuery(0, null, uri, cols, null, null,
1012                                                 MediaStore.Audio.Albums.DEFAULT_SORT_ORDER);
1013                         } else {
1014                                 ret = MusicUtils.query(this, uri, cols, null, null,
1015                                                 MediaStore.Audio.Albums.DEFAULT_SORT_ORDER);
1016                         }
1017                 } else {
1018                         Uri uri = MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI;
1019                         if (!TextUtils.isEmpty(filter)) {
1020                                 uri = uri.buildUpon()
1021                                                 .appendQueryParameter("filter", Uri.encode(filter))
1022                                                 .build();
1023                         }
1024                         if (async != null) {
1025                                 async.startQuery(0, null, uri, cols, null, null,
1026                                                 MediaStore.Audio.Albums.DEFAULT_SORT_ORDER);
1027                         } else {
1028                                 ret = MusicUtils.query(this, uri, cols, null, null,
1029                                                 MediaStore.Audio.Albums.DEFAULT_SORT_ORDER);
1030                         }
1031                 }
1032                 return ret;
1033         }
1034
1035         static class AlbumListAdapter extends SimpleCursorAdapter implements
1036                         SectionIndexer {
1037
1038                 private final BitmapDrawable mDefaultAlbumIcon;
1039                 private int mAlbumIdx;
1040                 private int mArtistIdx;
1041                 private int mAlbumArtIndex;
1042                 private final Resources mResources;
1043                 private final StringBuilder mStringBuilder = new StringBuilder();
1044                 private String mUnknownAlbum;
1045                 private final String mUnknownArtist;
1046                 private final String mAlbumSongSeparator;
1047                 private final Object[] mFormatArgs = new Object[1];
1048                 private AlphabetIndexer mIndexer;
1049                 private AlbumBrowserActivity mActivity;
1050                 private AsyncQueryHandler mQueryHandler;
1051                 private String mConstraint = null;
1052                 private boolean mConstraintIsValid = false;
1053
1054                 static class ViewHolder {
1055                         TextView line1;
1056                         TextView line2;
1057                         ImageView play_indicator;
1058                         ImageView icon;
1059                         ImageView mCM;
1060                         public FrameLayout mContextMenu;
1061                 }
1062
1063                 class QueryHandler extends AsyncQueryHandler {
1064                         QueryHandler(ContentResolver res) {
1065                                 super(res);
1066                         }
1067
1068                         @Override
1069                         protected void onQueryComplete(int token, Object cookie,
1070                                         Cursor cursor) {
1071                                 // Log.i("@@@", "query complete");
1072                                 mActivity.init(cursor);
1073                         }
1074                 }
1075
1076                 AlbumListAdapter(Context context, AlbumBrowserActivity currentactivity,
1077                                 int layout, Cursor cursor, String[] from, int[] to) {
1078                         super(context, layout, cursor, from, to);
1079
1080                         mActivity = currentactivity;
1081                         mQueryHandler = new QueryHandler(context.getContentResolver());
1082
1083                         mUnknownAlbum = context.getString(R.string.unknown_album_name);
1084                         mUnknownArtist = context.getString(R.string.unknown_artist_name);
1085                         mAlbumSongSeparator = context
1086                                         .getString(R.string.albumsongseparator);
1087
1088                         Resources r = context.getResources();
1089
1090                         Bitmap b = BitmapFactory.decodeResource(r,
1091                                         R.drawable.albumart_mp_unknown_list);
1092                         mDefaultAlbumIcon = new BitmapDrawable(context.getResources(), b);
1093                         // no filter or dither, it's a lot faster and we can't tell the
1094                         // difference
1095                         mDefaultAlbumIcon.setFilterBitmap(false);
1096                         mDefaultAlbumIcon.setDither(false);
1097                         getColumnIndices(cursor);
1098                         mResources = context.getResources();
1099                 }
1100
1101                 private void getColumnIndices(Cursor cursor) {
1102                         if (cursor != null) {
1103                                 mAlbumIdx = cursor.getColumnIndexOrThrow(AlbumColumns.ALBUM);
1104                                 mArtistIdx = cursor.getColumnIndexOrThrow(AlbumColumns.ARTIST);
1105                                 mAlbumArtIndex = cursor
1106                                                 .getColumnIndexOrThrow(AlbumColumns.ALBUM_ART);
1107
1108                                 if (mIndexer != null) {
1109                                         mIndexer.setCursor(cursor);
1110                                 } else {
1111                                         mIndexer = new MusicAlphabetIndexer(cursor, mAlbumIdx,
1112                                                         mResources.getString(R.string.fast_scroll_alphabet));
1113                                 }
1114                         }
1115                 }
1116
1117                 public void setActivity(AlbumBrowserActivity newactivity) {
1118                         mActivity = newactivity;
1119                 }
1120
1121                 public AsyncQueryHandler getQueryHandler() {
1122                         return mQueryHandler;
1123                 }
1124
1125                 private View.OnClickListener mCML = new View.OnClickListener() {
1126                         public void onClick(View v) {
1127                                 v.showContextMenu();
1128
1129                         }
1130                 };
1131
1132                 @Override
1133                 public View newView(Context context, Cursor cursor, ViewGroup parent) {
1134                         View v = super.newView(context, cursor, parent);
1135                         ViewHolder vh = new ViewHolder();
1136                         vh.line1 = (TextView) v.findViewById(R.id.line1);
1137                         vh.line2 = (TextView) v.findViewById(R.id.line2);
1138                         vh.play_indicator = (ImageView) v.findViewById(R.id.play_indicator);
1139                         vh.icon = (ImageView) v.findViewById(R.id.icon);
1140                         vh.icon.setBackgroundDrawable(mDefaultAlbumIcon);
1141                         vh.icon.setPadding(0, 0, 1, 0);
1142                         v.setTag(vh);
1143                         vh.mCM = (ImageView) v.findViewById(R.id.CM);
1144                         vh.mContextMenu = (FrameLayout) v
1145                                         .findViewById(R.id.second_column_icon);
1146                         vh.mContextMenu.setOnClickListener(mCML);
1147                         // ADW: Load the specified theme
1148                         String themePackage = MusicUtils.getThemePackageName(context,
1149                                         MusicSettingsActivity.THEME_DEFAULT);
1150                         PackageManager pm = context.getPackageManager();
1151                         Resources themeResources = null;
1152                         if (!themePackage.equals(MusicSettingsActivity.THEME_DEFAULT)) {
1153                                 try {
1154                                         themeResources = pm
1155                                                         .getResourcesForApplication(themePackage);
1156                                 } catch (NameNotFoundException e) {
1157                                         // ADW The saved theme was uninstalled so we save the
1158                                         // default one
1159                                         MusicUtils.setThemePackageName(context,
1160                                                         MusicSettingsActivity.THEME_DEFAULT);
1161                                 }
1162                         }
1163                         if (themeResources != null) {
1164                                 int line1 = themeResources.getIdentifier(
1165                                                 "album_tab_artist_name_color", "color", themePackage);
1166                                 if (line1 != 0) {
1167                                         vh.line1.setTextColor(themeResources.getColor(line1));
1168                                 }
1169                                 int line2 = themeResources.getIdentifier(
1170                                                 "album_tab_album_name_color", "color", themePackage);
1171                                 if (line2 != 0) {
1172                                         vh.line2.setTextColor(themeResources.getColor(line2));
1173                                 }
1174                                 ArtistAlbumBrowserActivity.loadThemeResource(themeResources,
1175                                                 themePackage, "bt_context_menu", vh.mCM,
1176                                                 THEME_ITEM_FOREGROUND);
1177                         }
1178                         return v;
1179                 }
1180
1181                 @Override
1182                 public void bindView(View view, Context context, Cursor cursor) {
1183
1184                         // ADW: Load the specified theme
1185                         String themePackage = MusicUtils.getThemePackageName(context,
1186                                         MusicSettingsActivity.THEME_DEFAULT);
1187                         PackageManager pm = context.getPackageManager();
1188                         Resources themeResources = null;
1189                         if (!themePackage.equals(MusicSettingsActivity.THEME_DEFAULT)) {
1190                                 try {
1191                                         themeResources = pm
1192                                                         .getResourcesForApplication(themePackage);
1193                                 } catch (NameNotFoundException e) {
1194                                         // ADW The saved theme was uninstalled so we save the
1195                                         // default one
1196                                         MusicUtils.setThemePackageName(context,
1197                                                         MusicSettingsActivity.THEME_DEFAULT);
1198                                 }
1199                         }
1200
1201                         ViewHolder vh = (ViewHolder) view.getTag();
1202
1203                         String name = cursor.getString(mAlbumIdx);
1204                         String displayname = name;
1205                         boolean unknown = name == null
1206                                         || name.equals(MediaStore.UNKNOWN_STRING);
1207                         if (unknown) {
1208                                 displayname = mUnknownAlbum;
1209                         }
1210                         vh.line1.setText(displayname);
1211                         name = cursor.getString(mArtistIdx);
1212                         displayname = name;
1213                         if (name == null || name.equals(MediaStore.UNKNOWN_STRING)) {
1214                                 displayname = mUnknownAlbum;
1215                         }
1216                         vh.line2.setText(displayname);
1217                         ImageView iv = vh.icon;
1218                         // We don't actually need the path to the thumbnail file,
1219                         // we just use it to see if there is album art or not
1220                         String art = cursor.getString(mAlbumArtIndex);
1221                         long aid = cursor.getLong(0);
1222                         if (unknown || art == null || art.length() == 0) {
1223                                 iv.setImageDrawable(null);
1224                         } else {
1225                                 Drawable d = MusicUtils.getCachedArtwork(context, aid,
1226                                                 mDefaultAlbumIcon);
1227                                 iv.setImageDrawable(d);
1228                         }
1229
1230                         long currentalbumid = MusicUtils.getCurrentAlbumId();
1231                         iv = vh.play_indicator;
1232                         if (currentalbumid == aid) {
1233                                 iv.setBackgroundResource(R.anim.peak_meter);
1234                                 AnimationDrawable frameAnimation = (AnimationDrawable) iv
1235                                                 .getBackground();
1236                                 if (themeResources != null) {
1237                                         int peak = themeResources.getIdentifier("peak_meter",
1238                                                         "anim", themePackage);
1239                                         if (peak != 0) {
1240                                                 iv.setBackgroundDrawable(themeResources
1241                                                                 .getDrawable(peak));
1242                                         }
1243                                 }
1244                                 // Start the animation (looped playback by default).
1245                                 frameAnimation.start();
1246                                 iv.setVisibility(View.VISIBLE);
1247                         } else {
1248                                 iv.setVisibility(View.GONE);
1249                         }
1250                 }
1251
1252                 @Override
1253                 public void changeCursor(Cursor cursor) {
1254                         if (mActivity.isFinishing() && cursor != null) {
1255                                 cursor.close();
1256                                 cursor = null;
1257                         }
1258                         if (cursor != mActivity.mAlbumCursor) {
1259                                 mActivity.mAlbumCursor = cursor;
1260                                 getColumnIndices(cursor);
1261                                 super.changeCursor(cursor);
1262                         }
1263                 }
1264
1265                 @Override
1266                 public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
1267                         String s = constraint.toString();
1268                         if (mConstraintIsValid
1269                                         && ((s == null && mConstraint == null) || (s != null && s
1270                                                         .equals(mConstraint)))) {
1271                                 return getCursor();
1272                         }
1273                         Cursor c = mActivity.getAlbumCursor(null, s);
1274                         mConstraint = s;
1275                         mConstraintIsValid = true;
1276                         return c;
1277                 }
1278
1279                 public Object[] getSections() {
1280                         return mIndexer.getSections();
1281                 }
1282
1283                 public int getPositionForSection(int section) {
1284                         return mIndexer.getPositionForSection(section);
1285                 }
1286
1287                 public int getSectionForPosition(int position) {
1288                         return 0;
1289                 }
1290         }
1291
1292         private Cursor mAlbumCursor;
1293         private String mArtistId;
1294
1295         public void onServiceConnected(ComponentName name, IBinder service) {
1296                 MusicUtils.updateNowPlaying(this);
1297         }
1298
1299         public void onServiceDisconnected(ComponentName name) {
1300                 finish();
1301         }
1302
1303         // Methods for media control
1304         private void doPauseResume() {
1305                 try {
1306                         if (mService != null) {
1307                                 if (mService.isPlaying()) {
1308                                         mService.pause();
1309                                 } else {
1310                                         mService.play();
1311                                 }
1312                                 if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
1313                                         setPauseButtonImage();
1314                                 }
1315                         }
1316                 } catch (RemoteException ex) {
1317                 }
1318         }
1319
1320         private void setPauseButtonImage() {
1321                 // ADW: Load the specified theme
1322                 String themePackage = MusicUtils.getThemePackageName(this,
1323                                 MusicSettingsActivity.THEME_DEFAULT);
1324                 PackageManager pm = getPackageManager();
1325                 Resources themeResources = null;
1326                 if (!themePackage.equals(MusicSettingsActivity.THEME_DEFAULT)) {
1327                         try {
1328                                 themeResources = pm.getResourcesForApplication(themePackage);
1329                         } catch (NameNotFoundException e) {
1330                                 // ADW The saved theme was uninstalled so we save the
1331                                 // default one
1332                                 MusicUtils.setThemePackageName(this,
1333                                                 MusicSettingsActivity.THEME_DEFAULT);
1334                         }
1335                 }
1336                 try {
1337                         if (mService != null && mService.isPlaying()) {
1338                                 mPlay.setImageResource(R.drawable.ic_media_pause);
1339                                 if (themeResources != null) {
1340                                         ArtistAlbumBrowserActivity.loadThemeResource(
1341                                                         themeResources, themePackage, "snp_pause", mPlay,
1342                                                         THEME_ITEM_FOREGROUND);
1343                                 }
1344                         } else {
1345                                 mPlay.setImageResource(R.drawable.ic_appwidget_music_play);
1346                                 if (themeResources != null) {
1347                                         ArtistAlbumBrowserActivity.loadThemeResource(
1348                                                         themeResources, themePackage, "snp_play", mPlay,
1349                                                         THEME_ITEM_FOREGROUND);
1350                                 }
1351                         }
1352                 } catch (RemoteException ex) {
1353                 }
1354         }
1355
1356         private void refreshProgress() {
1357                 ProgressBar mProgress = (ProgressBar) findViewById(R.id.progress);
1358                 mProgress.setMax(1000);
1359                 try {
1360                         if ((MusicUtils.sService.position() >= 0)
1361                                         && (MusicUtils.sService.duration() > 0)) {
1362                                 mProgress.setProgress((int) (1000 * MusicUtils.sService
1363                                                 .position() / MusicUtils.sService.duration()));
1364                         } else {
1365                                 mProgress.setProgress(1000);
1366                         }
1367                 } catch (Exception e) {
1368                         // TODO Auto-generated catch block
1369                         e.printStackTrace();
1370                 }
1371
1372         }
1373
1374         private void doPrev() {
1375                 if (mService == null)
1376                         return;
1377                 try {
1378                         if (mService.position() < 2000) {
1379                                 mService.prev();
1380                         } else {
1381                                 mService.seek(0);
1382                                 mService.play();
1383                         }
1384                         setPauseButtonImage();
1385                 } catch (RemoteException ex) {
1386                 }
1387         }
1388
1389         private void doNext() {
1390                 if (mService == null)
1391                         return;
1392                 try {
1393                         mService.next();
1394                         setPauseButtonImage();
1395                 } catch (RemoteException ex) {
1396                 }
1397         }
1398
1399         private void playRecentlyAdded() {
1400                 // do a query for all songs added in the last X weeks
1401                 int X = MusicUtils.getIntPref(this, "numweeks", 2) * (3600 * 24 * 7);
1402                 final String[] ccols = new String[] { MediaStore.Audio.Media._ID };
1403                 String where = MediaStore.MediaColumns.DATE_ADDED + ">"
1404                                 + (System.currentTimeMillis() / 1000 - X);
1405                 Cursor cursor = MusicUtils.query(this,
1406                                 MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, ccols, where,
1407                                 null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
1408
1409                 if (cursor == null) {
1410                         // Todo: show a message
1411                         return;
1412                 }
1413                 try {
1414                         int len = cursor.getCount();
1415                         long[] list = new long[len];
1416                         for (int i = 0; i < len; i++) {
1417                                 cursor.moveToNext();
1418                                 list[i] = cursor.getLong(0);
1419                         }
1420                         MusicUtils.playAll(this, list, 0);
1421                 } catch (SQLiteException ex) {
1422                 } finally {
1423                         cursor.close();
1424                 }
1425         }
1426
1427         @Override
1428         public boolean onKeyLongPress(int keyCode, KeyEvent event) {
1429                 if (keyCode == KeyEvent.KEYCODE_BACK) {
1430                         back_button_db = mPreferences.getString("back_button_db", "0");
1431                         if (back_button_db.equals("0")) {
1432                                 MusicUtils.togglePartyShuffle();
1433                                 return true;
1434                         }
1435                         if (keyCode == KeyEvent.KEYCODE_BACK) {
1436                                 back_button_db = mPreferences.getString("back_button_db", "1");
1437                                 if (back_button_db.equals("1")) {
1438                                         playRecentlyAdded();
1439                                         return true;
1440                                 }
1441
1442                         }
1443                         if (keyCode == KeyEvent.KEYCODE_BACK) {
1444                                 back_button_db = mPreferences.getString("back_button_db", "2");
1445                                 if (back_button_db.equals("2")) {
1446                                         Cursor cursor;
1447                                         cursor = MusicUtils.query(this,
1448                                                         MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
1449                                                         new String[] { BaseColumns._ID },
1450                                                         AudioColumns.IS_MUSIC + "=1", null,
1451                                                         MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
1452                                         if (cursor != null) {
1453                                                 MusicUtils.shuffleAll(this, cursor);
1454                                                 cursor.close();
1455                                                 return true;
1456                                         }
1457                                 }
1458                         }
1459                 }
1460                 return super.onKeyLongPress(keyCode, event);
1461
1462         }
1463 }