diff --git a/src/org/kreed/vanilla/MediaAdapter.java b/src/org/kreed/vanilla/MediaAdapter.java index 1fc68a90..5e99f685 100644 --- a/src/org/kreed/vanilla/MediaAdapter.java +++ b/src/org/kreed/vanilla/MediaAdapter.java @@ -18,50 +18,121 @@ package org.kreed.vanilla; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - +import android.content.ContentResolver; import android.content.Context; -import android.content.Intent; +import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; +import android.net.Uri; +import android.provider.BaseColumns; +import android.provider.MediaStore; import android.util.TypedValue; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.View.OnClickListener; -import android.widget.BaseAdapter; +import android.widget.CursorAdapter; import android.widget.Filter; -import android.widget.Filterable; +import android.widget.FilterQueryProvider; -public class MediaAdapter extends BaseAdapter implements Filterable { - private Context mContext; - private OnClickListener mExpanderListener; +public class MediaAdapter extends CursorAdapter implements FilterQueryProvider { + public static final String[] ARTIST_FIELDS = { MediaStore.Audio.Artists.ARTIST }; + public static final String[] ARTIST_FIELD_KEYS = { MediaStore.Audio.Artists.ARTIST_KEY }; + public static final String[] ALBUM_FIELDS = { MediaStore.Audio.Albums.ARTIST, MediaStore.Audio.Albums.ALBUM }; + // Why is there no artist_key column constant in the album MediaStore? The column does seem to exist. + public static final String[] ALBUM_FIELD_KEYS = { "artist_key", MediaStore.Audio.Albums.ALBUM_KEY }; + public static final String[] SONG_FIELDS = { MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.ALBUM, MediaStore.Audio.Media.TITLE }; + public static final String[] SONG_FIELD_KEYS = { MediaStore.Audio.Media.ARTIST_KEY, MediaStore.Audio.Media.ALBUM_KEY, MediaStore.Audio.Media.TITLE_KEY }; - private List mObjects; - private SongData[] mAllObjects; - private ArrayFilter mFilter; - private long mLimiter; - private SongData mLimiterData; - private CharSequence mPublishedFilter; - private long mPublishedLimiter; + private Uri mStore; + private String[] mFields; + private String[] mFieldKeys; + private View.OnClickListener mExpanderListener; + private String mSelection; + private String[] mLimiter; + private CharSequence mConstraint; - private int mPrimaryField; - private int mSecondaryField; - - public MediaAdapter(Context context, SongData[] allObjects, int primaryField, int secondaryField, View.OnClickListener expanderListener) + public MediaAdapter(Context context, Uri store, String[] fields, String[] fieldKeys, View.OnClickListener expanderListener, String selection) { - mContext = context; - mAllObjects = allObjects; - mPrimaryField = primaryField; - mSecondaryField = secondaryField; + super(context, null, true); + + mStore = store; + mFields = fields; + mFieldKeys = fieldKeys; mExpanderListener = expanderListener; + mSelection = selection; + + setFilterQueryProvider(this); + + changeCursor(runQuery(null)); + } + + public void filter(CharSequence constraint, Filter.FilterListener listener) + { + mConstraint = constraint; + getFilter().filter(constraint, listener); + } + + public Cursor runQuery(CharSequence constraint) + { + ContentResolver resolver = ContextApplication.getContext().getContentResolver(); + + StringBuilder selection = new StringBuilder(); + String[] selectionArgs; + String limiter; + + if (mSelection != null) + selection.append(mSelection); + + if (mLimiter != null) { + int i = Math.min(mLimiter.length, mFields.length) - 1; + if (selection.length() != 0) + selection.append(" AND "); + selection.append(mFields[i]); + selection.append(" = ?"); + limiter = mLimiter[i]; + } else { + limiter = null; + } + + if (constraint != null && constraint.length() != 0) { + String[] constraints = constraint.toString().split("\\s+"); + int size = constraints.length; + if (limiter != null) + ++size; + selectionArgs = new String[size]; + int i = 0; + if (limiter != null) { + selectionArgs[0] = limiter; + i = 1; + } + String keys = mFieldKeys[0]; + for (int j = 1; j != mFieldKeys.length; ++j) + keys += "||" + mFieldKeys[j]; + for (int j = 0; j != constraints.length; ++i, ++j) { + selectionArgs[i] = '%' + MediaStore.Audio.keyFor(constraints[j]) + '%'; + + if (j != 0 || selection.length() != 0) + selection.append(" AND "); + selection.append(keys); + selection.append(" LIKE ?"); + } + } else { + if (limiter != null) + selectionArgs = new String[] { limiter }; + else + selectionArgs = null; + } + + String[] projection; + if (mFields.length == 1) + projection = new String[] { BaseColumns._ID, mFields[0] }; + else + projection = new String[] { BaseColumns._ID, mFields[mFields.length - 1], mFields[0] }; + + return resolver.query(mStore, projection, selection.toString(), selectionArgs, mFieldKeys[mFieldKeys.length - 1]); } public final boolean hasExpanders() @@ -69,231 +140,34 @@ public class MediaAdapter extends BaseAdapter implements Filterable { return mExpanderListener != null; } - @Override - public boolean hasStableIds() - { - return true; - } - - public View getView(int position, View convertView, ViewGroup parent) - { - MediaView view = null; - try { - view = (MediaView)convertView; - } catch (ClassCastException e) { - } - - if (view == null) - view = new MediaView(mContext); - - view.updateMedia(get(position)); - - return view; - } - - public Filter getFilter() - { - if (mFilter == null) - mFilter = new ArrayFilter(); - return mFilter; - } - - private static final String[] mRanges = { ".", "[2abc]", "[3def]", "[4ghi]", "[5jkl]", "[6mno]", "[7pqrs]", "[8tuv]", "[9wxyz]"}; - private static Matcher createMatcher(String input) - { - String patternString = ""; - for (int i = 0, end = input.length(); i != end; ++i) { - char c = input.charAt(i); - int value = c - '1'; - if (value >= 0 && value < 9) - patternString += mRanges[value]; - else - patternString += c; - } - - return Pattern.compile(patternString, Pattern.CASE_INSENSITIVE).matcher(""); - } - - private class ArrayFilter extends Filter { - protected class ArrayFilterResults extends FilterResults { - public long limiter; - - public ArrayFilterResults(List list, long limiter) - { - values = list; - count = list.size(); - this.limiter = limiter; - } - } - - @Override - protected FilterResults performFiltering(CharSequence filter) - { - List list; - - if (filter != null && filter.length() == 0) - filter = null; - - if ((filter == null && mPublishedFilter == null || mPublishedFilter != null && mPublishedFilter.equals(filter)) && mLimiter == mPublishedLimiter) { - list = mObjects; - } else if (filter == null && mLimiter == -1) { - list = Arrays.asList(mAllObjects); - } else { - Matcher[] matchers = null; - if (filter != null) { - String[] words = filter.toString().split("\\s+"); - matchers = new Matcher[words.length]; - for (int i = words.length; --i != -1; ) - matchers[i] = createMatcher(words[i]); - } - - int limiterField = limiterField(mLimiter); - long limiterId = limiterId(mLimiter); - - int count = mAllObjects.length; - ArrayList newValues = new ArrayList(); - newValues.ensureCapacity(count); - - outer: - for (int i = 0; i != count; ++i) { - SongData song = mAllObjects[i]; - - if (mLimiter != -1 && song.getFieldId(limiterField) != limiterId) - continue; - - if (filter != null) { - for (int j = matchers.length; --j != -1; ) { - if (matchers[j].reset(song.artist).find()) - continue; - if (mPrimaryField > 1 && matchers[j].reset(song.album).find()) - continue; - if (mPrimaryField > 2 && matchers[j].reset(song.title).find()) - continue; - continue outer; - } - } - - newValues.add(song); - } - - newValues.trimToSize(); - - list = newValues; - } - - return new ArrayFilterResults(list, mLimiter); - } - - @SuppressWarnings("unchecked") - @Override - protected void publishResults(CharSequence filter, FilterResults results) - { - mObjects = (List)results.values; - mPublishedFilter = filter == null || filter.length() == 0 ? null : filter; - mPublishedLimiter = ((ArrayFilterResults)results).limiter; - - if (results.count == 0) - notifyDataSetInvalidated(); - else - notifyDataSetChanged(); - } - } - - public void hideAll() - { - mObjects = new ArrayList(); - notifyDataSetInvalidated(); - } - - public void setLimiter(long limiter, SongData data) + public final void setLimiter(String[] limiter) { mLimiter = limiter; - mLimiterData = data; - getFilter().filter(mPublishedFilter); + getFilter().filter(mConstraint); } - public final long getLimiter() + public final String[] getLimiter() { return mLimiter; } - public final int getLimiterField() + public final int getLimiterLength() { - if (mLimiter == -1) - return -1; - return limiterField(mLimiter); - } - - public final SongData getLimiterData() - { - return mLimiterData; - } - - private static final int ID_SHIFT = 2; - private static final int FIELD_MASK = ~(~0 << ID_SHIFT); - - public static long makeLimiter(int field, SongData data) - { - return (data.getFieldId(field) << ID_SHIFT) + (field & FIELD_MASK); - } - - public static int limiterField(long limiter) - { - return (int)(limiter & FIELD_MASK); - } - - public static long limiterId(long limiter) - { - return limiter >> ID_SHIFT; - } - - public int getCount() - { - if (mObjects == null) { - if (mAllObjects == null) - return 0; - return mAllObjects.length; - } - return mObjects.size(); - } - - public SongData get(int i) - { - if (mObjects == null) { - if (mAllObjects == null) - return null; - return mAllObjects[i]; - } - if (i >= mObjects.size()) - return null; - return mObjects.get(i); - } - - public Object getItem(int i) - { - return get(i); - } - - public long getItemId(int i) - { - SongData song = get(i); - if (song == null) + if (mLimiter == null) return 0; - return song.getFieldId(mPrimaryField); + return mLimiter.length; } - public Intent buildSongIntent(int action, int pos) + @Override + public void bindView(View view, Context context, Cursor cursor) { - SongData song = get(pos); - if (song == null) - return null; + ((MediaView)view).updateMedia(cursor); + } - Intent intent = new Intent(mContext, PlaybackService.class); - intent.putExtra("type", mPrimaryField); - intent.putExtra("action", action); - intent.putExtra("id", song.getFieldId(mPrimaryField)); - intent.putExtra("title", song.getField(mPrimaryField)); - return intent; + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) + { + return new MediaView(context); } private static float mTextSize = -1; @@ -302,7 +176,9 @@ public class MediaAdapter extends BaseAdapter implements Filterable { private int mViewHeight = -1; public class MediaView extends View { - private SongData mData; + private long mId; + private String mTitle; + private String mSubTitle; private boolean mExpanderPressed; public MediaView(Context context) @@ -327,7 +203,7 @@ public class MediaAdapter extends BaseAdapter implements Filterable { else expanderHeight = 0; - if (mSecondaryField != -1) + if (mFields.length > 1) textHeight = (int)(7 * mTextSize / 2); else textHeight = (int)(2 * mTextSize); @@ -344,7 +220,7 @@ public class MediaAdapter extends BaseAdapter implements Filterable { @Override public void onDraw(Canvas canvas) { - if (mData == null) + if (mTitle == null) return; int width = getWidth(); @@ -364,33 +240,32 @@ public class MediaAdapter extends BaseAdapter implements Filterable { float allocatedHeight; - if (mSecondaryField != -1) { + if (mSubTitle != null) { allocatedHeight = height / 2 - padding * 3 / 2; paint.setColor(Color.GRAY); - canvas.drawText(mData.getField(mSecondaryField), padding, height / 2 + padding / 2 + (allocatedHeight - mTextSize) / 2 - paint.ascent(), paint); + canvas.drawText(mSubTitle, padding, height / 2 + padding / 2 + (allocatedHeight - mTextSize) / 2 - paint.ascent(), paint); } else { allocatedHeight = height - padding * 2; } paint.setColor(Color.WHITE); - canvas.drawText(mData.getField(mPrimaryField), padding, padding + (allocatedHeight - mTextSize) / 2 - paint.ascent(), paint); + canvas.drawText(mTitle, padding, padding + (allocatedHeight - mTextSize) / 2 - paint.ascent(), paint); } - public final void updateMedia(SongData data) + public final int getFieldCount() { - mData = data; - invalidate(); + return mFields.length; } - public final int getPrimaryField() + public final long getMediaId() { - return mPrimaryField; + return mId; } - public final SongData getExpanderData() + public final String getTitle() { - return mData; + return mTitle; } public final boolean isExpanderPressed() @@ -398,6 +273,33 @@ public class MediaAdapter extends BaseAdapter implements Filterable { return mExpanderPressed; } + public final void updateMedia(Cursor cursor) + { + mId = cursor.getLong(0); + mTitle = cursor.getString(1); + if (mFields.length > 1) + mSubTitle = cursor.getString(2); + invalidate(); + } + + public final String[] getLimiter() + { + ContentResolver resolver = ContextApplication.getContext().getContentResolver(); + String selection = mFields[mFields.length - 1] + " = ?"; + String[] selectionArgs = { mTitle }; + String[] projection = new String[mFields.length + 1]; + projection[0] = BaseColumns._ID; + System.arraycopy(mFields, 0, projection, 1, mFields.length); + + Cursor cursor = resolver.query(mStore, projection, selection, selectionArgs, null); + cursor.moveToNext(); + String[] result = new String[cursor.getColumnCount() - 1]; + for (int i = result.length; --i != -1; ) + result[i] = cursor.getString(i + 1); + + return result; + } + @Override public boolean onTouchEvent(MotionEvent event) { diff --git a/src/org/kreed/vanilla/PlaybackService.java b/src/org/kreed/vanilla/PlaybackService.java index f7e16e15..6987b6e7 100644 --- a/src/org/kreed/vanilla/PlaybackService.java +++ b/src/org/kreed/vanilla/PlaybackService.java @@ -622,14 +622,14 @@ public class PlaybackService extends Service implements Runnable, MediaPlayer.On loadPreference((String)message.obj); break; case DO_ITEM: - long id = message.obj == null ? -1 : ((Intent)message.obj).getLongExtra("id", -1); + Intent intent = (Intent)message.obj; + long id = message.obj == null ? -1 : intent.getLongExtra("id", -1); if (id == -1) { mQueuePos = 0; } else { - Intent intent = (Intent)message.obj; boolean enqueue = intent.getIntExtra("action", ACTION_PLAY) == ACTION_ENQUEUE; - long[] songs = Song.getAllSongIdsWith(intent.getIntExtra("type", SongData.FIELD_TITLE), id); + long[] songs = Song.getAllSongIdsWith(intent.getIntExtra("type", 3), id); if (songs == null || songs.length == 0) break; diff --git a/src/org/kreed/vanilla/Song.java b/src/org/kreed/vanilla/Song.java index 80ff9997..6bd9e1d4 100644 --- a/src/org/kreed/vanilla/Song.java +++ b/src/org/kreed/vanilla/Song.java @@ -131,13 +131,16 @@ public class Song implements Parcelable { public static long[] getAllSongIdsWith(int type, long id) { - if (type == SongData.FIELD_TITLE) + switch (type) { + case 3: return new long[] { id }; - else if (type == SongData.FIELD_ALBUM) + case 2: return Song.getAllSongIds(MediaStore.Audio.Media.ALBUM_ID + '=' + id); - else if (type == SongData.FIELD_ARTIST) + case 1: return Song.getAllSongIds(MediaStore.Audio.Media.ARTIST_ID + '=' + id); - return null; + default: + return null; + } } public void randomize() diff --git a/src/org/kreed/vanilla/SongData.java b/src/org/kreed/vanilla/SongData.java deleted file mode 100644 index 91737162..00000000 --- a/src/org/kreed/vanilla/SongData.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2010 Christopher Eby - * - * This file is part of Vanilla Music Player. - * - * Vanilla Music Player is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Vanilla Music Player is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.kreed.vanilla; - -import java.util.Arrays; -import java.util.Comparator; - -import android.content.ContentResolver; -import android.database.Cursor; -import android.net.Uri; -import android.provider.MediaStore; -import android.util.SparseArray; - -public class SongData { - public static final int FIELD_ARTIST = 1; - public static final int FIELD_ALBUM = 2; - public static final int FIELD_TITLE = 3; - - public long id; - public long albumId; - public long artistId; - - public String title; - public String album; - public String artist; - - private SongData(Cursor cursor) - { - id = cursor.getLong(0); - title = cursor.getString(1); - albumId = cursor.getLong(2); - album = cursor.getString(3); - artistId = cursor.getLong(4); - artist = cursor.getString(5); - } - - public String getField(int field) - { - switch (field) { - case FIELD_TITLE: - return title; - case FIELD_ARTIST: - return artist; - case FIELD_ALBUM: - return album; - } - return null; - } - - public long getFieldId(int field) - { - switch (field) { - case FIELD_TITLE: - return id; - case FIELD_ARTIST: - return artistId; - case FIELD_ALBUM: - return albumId; - } - return 0; - } - - public static SongData[] getAllSongData() - { - Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; - String[] projection = { MediaStore.Audio.Media._ID, - MediaStore.Audio.Media.TITLE, - MediaStore.Audio.Media.ALBUM_ID, - MediaStore.Audio.Media.ALBUM, - MediaStore.Audio.Media.ARTIST_ID, - MediaStore.Audio.Media.ARTIST }; - String selection = MediaStore.Audio.Media.IS_MUSIC + "!=0"; - - ContentResolver resolver = ContextApplication.getContext().getContentResolver(); - Cursor cursor = resolver.query(media, projection, selection, null, null); - - if (cursor == null) - return null; - - int count = cursor.getCount(); - if (count == 0) - return null; - - SongData[] songs = new SongData[count]; - while (--count != -1) { - if (!cursor.moveToNext()) - return null; - songs[count] = new SongData(cursor); - } - - cursor.close(); - return songs; - } - - public static class TitleComparator implements Comparator { - public int compare(SongData a, SongData b) - { - return a.title.compareToIgnoreCase(b.title); - } - } - - public static class AlbumComparator implements IdComparator { - public int compare(SongData a, SongData b) - { - return a.album.compareToIgnoreCase(b.album); - } - - public long getId(SongData song) - { - return song.albumId; - } - } - - public static class ArtistComparator implements IdComparator { - public int compare(SongData a, SongData b) - { - return a.artist.compareToIgnoreCase(b.artist); - } - - public long getId(SongData song) - { - return song.artistId; - } - } - - public static interface IdComparator extends Comparator { - public long getId(SongData song); - } - - public static SongData[] filter(SongData[] songs, IdComparator comparator) - { - SparseArray albums = new SparseArray(songs.length); - for (int i = songs.length; --i != -1; ) { - SongData song = songs[i]; - int id = (int)comparator.getId(song); - if (albums.get(id) == null) - albums.put(id, song); - } - - SongData[] result = new SongData[albums.size()]; - for (int i = result.length; --i != -1; ) - result[i] = albums.valueAt(i); - - Arrays.sort(result, comparator); - return result; - } -} \ No newline at end of file diff --git a/src/org/kreed/vanilla/SongSelector.java b/src/org/kreed/vanilla/SongSelector.java index 12a8df80..3a68d103 100644 --- a/src/org/kreed/vanilla/SongSelector.java +++ b/src/org/kreed/vanilla/SongSelector.java @@ -18,8 +18,6 @@ package org.kreed.vanilla; -import java.util.Arrays; - import org.kreed.vanilla.R; import android.app.Dialog; @@ -29,9 +27,11 @@ import android.content.SharedPreferences; import android.content.res.Resources; import android.graphics.Color; import android.graphics.drawable.PaintDrawable; +import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; +import android.provider.MediaStore; import android.text.Editable; import android.text.InputType; import android.text.TextUtils; @@ -71,12 +71,12 @@ public class SongSelector extends Dialog implements AdapterView.OnItemClickListe return (MediaAdapter)getList(tab).getAdapter(); } - private void initializeList(int id, SongData[] songs, int lineA, int lineB, View.OnClickListener expanderListener) + private void initializeList(int id, Uri store, String[] fields, String[] fieldKeys, View.OnClickListener expanderListener, String selection) { ListView view = (ListView)findViewById(id); view.setOnItemClickListener(this); view.setOnCreateContextMenuListener(this); - view.setAdapter(new MediaAdapter(getContext(), songs, lineA, lineB, expanderListener)); + view.setAdapter(new MediaAdapter(getContext(), store, fields, fieldKeys, expanderListener, selection)); } public SongSelector(Context context) @@ -109,12 +109,9 @@ public class SongSelector extends Dialog implements AdapterView.OnItemClickListe new Handler().post(new Runnable() { public void run() { - SongData[] songs = SongData.getAllSongData(); - - initializeList(R.id.artist_list, SongData.filter(songs, new SongData.ArtistComparator()), SongData.FIELD_ARTIST, -1, SongSelector.this); - initializeList(R.id.album_list, SongData.filter(songs, new SongData.AlbumComparator()), SongData.FIELD_ALBUM, SongData.FIELD_ARTIST, SongSelector.this); - Arrays.sort(songs, new SongData.TitleComparator()); - initializeList(R.id.song_list, songs, SongData.FIELD_TITLE, SongData.FIELD_ARTIST, null); + initializeList(R.id.artist_list, MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI, MediaAdapter.ARTIST_FIELDS, MediaAdapter.ARTIST_FIELD_KEYS, SongSelector.this, null); + initializeList(R.id.album_list, MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, MediaAdapter.ALBUM_FIELDS, MediaAdapter.ALBUM_FIELD_KEYS,SongSelector.this, null); + initializeList(R.id.song_list, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, MediaAdapter.SONG_FIELDS, MediaAdapter.SONG_FIELD_KEYS, null, MediaStore.Audio.Media.IS_MUSIC + "!=0"); } }); } @@ -145,36 +142,32 @@ public class SongSelector extends Dialog implements AdapterView.OnItemClickListe return mTextFilter.onKeyDown(keyCode, event); } - private void sendSongIntent(Intent intent) + private void sendSongIntent(MediaAdapter.MediaView view, int action) { - int action = intent.getIntExtra("action", PlaybackService.ACTION_PLAY); - String title = intent.getStringExtra("title"); - intent.removeExtra("title"); - int res = action == PlaybackService.ACTION_PLAY ? R.string.playing : R.string.enqueued; - String text = getContext().getResources().getString(res, title); + String text = getContext().getResources().getString(res, view.getTitle()); Toast.makeText(getContext(), text, Toast.LENGTH_SHORT).show(); + long id = view.getMediaId(); + int field = view.getFieldCount(); + + Intent intent = new Intent(getContext(), PlaybackService.class); + intent.putExtra("type", field); + intent.putExtra("action", action); + intent.putExtra("id", id); getContext().startService(intent); - mLastActedId = intent.getIntExtra("id", -1); + mLastActedId = id; } private void expand(MediaAdapter.MediaView view) { - int field = view.getPrimaryField(); - SongData data = view.getExpanderData(); - long limiter = MediaAdapter.makeLimiter(field, data); + String[] limiter = view.getLimiter(); - for (int i = field; i != 3; ++i) { - MediaAdapter adapter = getAdapter(i); - if (adapter.getLimiter() != limiter) { - adapter.hideAll(); - adapter.setLimiter(limiter, data); - } - } + for (int i = limiter.length; i != 3; ++i) + getAdapter(i).setLimiter(limiter); - mTabHost.setCurrentTab(field); + mTabHost.setCurrentTab(limiter.length); } public void onItemClick(AdapterView list, View view, int pos, long id) @@ -185,7 +178,7 @@ public class SongSelector extends Dialog implements AdapterView.OnItemClickListe else if (id == mLastActedId) dismiss(); else - sendSongIntent(((MediaAdapter)list.getAdapter()).buildSongIntent(mDefaultAction, pos)); + sendSongIntent(mediaView, mDefaultAction); } public void afterTextChanged(Editable editable) @@ -200,7 +193,7 @@ public class SongSelector extends Dialog implements AdapterView.OnItemClickListe { MediaAdapter adapter = getAdapter(mTabHost.getCurrentTab()); if (adapter != null) - adapter.getFilter().filter(text, this); + adapter.filter(text, this); } private void updateLimiterViews() @@ -214,21 +207,20 @@ public class SongSelector extends Dialog implements AdapterView.OnItemClickListe if (adapter == null) return; - int field = adapter.getLimiterField(); - SongData data = adapter.getLimiterData(); - if (field == -1) + String[] limiter = adapter.getLimiter(); + if (limiter == null) return; LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); params.leftMargin = 5; - for (int i = SongData.FIELD_ARTIST; i <= field; ++i) { + for (int i = 0; i != limiter.length; ++i) { PaintDrawable background = new PaintDrawable(Color.GRAY); background.setCornerRadius(5); TextView view = new TextView(getContext()); view.setSingleLine(); view.setEllipsize(TextUtils.TruncateAt.MARQUEE); - view.setText(data.getField(i) + " | X"); + view.setText(limiter[i] + " | X"); view.setTextColor(Color.WHITE); view.setBackgroundDrawable(background); view.setLayoutParams(params); @@ -249,14 +241,20 @@ public class SongSelector extends Dialog implements AdapterView.OnItemClickListe if (view == mClearButton) { mTextFilter.setText(""); } else { - int field = (Integer)view.getTag() - 1; - SongData data = getAdapter(mTabHost.getCurrentTab()).getLimiterData(); - long limiter = field == 0 ? -1 : MediaAdapter.makeLimiter(field, data); + int i = (Integer)view.getTag(); + String[] limiter; + if (i == 0) { + limiter = null; + } else { + String[] oldLimiter = getAdapter(mTabHost.getCurrentTab()).getLimiter(); + limiter = new String[i]; + System.arraycopy(oldLimiter, 0, limiter, 0, i); + } - for (int i = 3; --i != -1; ) { - MediaAdapter adapter = getAdapter(i); - if (adapter.getLimiterField() > field) - adapter.setLimiter(limiter, data); + for (int j = 3; --j != -1; ) { + MediaAdapter adapter = getAdapter(j); + if (adapter.getLimiterLength() > i) + adapter.setLimiter(limiter); } updateLimiterViews(); @@ -268,29 +266,30 @@ public class SongSelector extends Dialog implements AdapterView.OnItemClickListe private static final int MENU_EXPAND = 2; @Override - public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo info) + public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo absInfo) { - MediaAdapter adapter = (MediaAdapter)((ListView)view).getAdapter(); - int pos = (int)((AdapterView.AdapterContextMenuInfo)info).position; - menu.add(0, MENU_PLAY, 0, R.string.play).setIntent(adapter.buildSongIntent(PlaybackService.ACTION_PLAY, pos)); - menu.add(0, MENU_ENQUEUE, 0, R.string.enqueue).setIntent(adapter.buildSongIntent(PlaybackService.ACTION_ENQUEUE, pos)); - if (adapter.hasExpanders()) + menu.add(0, MENU_PLAY, 0, R.string.play); + menu.add(0, MENU_ENQUEUE, 0, R.string.enqueue); + if (((MediaAdapter)((ListView)view).getAdapter()).hasExpanders()) menu.add(0, MENU_EXPAND, 0, R.string.expand); } @Override public boolean onContextItemSelected(MenuItem item) { + MediaAdapter.MediaView view = (MediaAdapter.MediaView)((AdapterView.AdapterContextMenuInfo)item.getMenuInfo()).targetView; + int action = PlaybackService.ACTION_PLAY; switch (item.getItemId()) { case MENU_EXPAND: - expand((MediaAdapter.MediaView)((AdapterView.AdapterContextMenuInfo)item.getMenuInfo()).targetView); + expand(view); break; - case MENU_PLAY: case MENU_ENQUEUE: - Intent intent = item.getIntent(); + action = PlaybackService.ACTION_ENQUEUE; + // fall through + case MENU_PLAY: if (mDefaultIsLastAction) - mDefaultAction = intent.getIntExtra("action", PlaybackService.ACTION_PLAY); - sendSongIntent(intent); + mDefaultAction = action; + sendSongIntent(view, action); break; default: return false; @@ -311,7 +310,7 @@ public class SongSelector extends Dialog implements AdapterView.OnItemClickListe { CharSequence text = mTextFilter.getText(); for (int i = 3; --i != -1; ) - getAdapter(i).getFilter().filter(text); + getAdapter(i).filter(text, null); } @Override