diff --git a/src/org/kreed/vanilla/MediaAdapter.java b/src/org/kreed/vanilla/MediaAdapter.java index 7809657b..96f41642 100644 --- a/src/org/kreed/vanilla/MediaAdapter.java +++ b/src/org/kreed/vanilla/MediaAdapter.java @@ -42,14 +42,28 @@ import android.widget.CursorAdapter; import android.widget.Filter; import android.widget.FilterQueryProvider; +/** + * MediaAdapter provides an adapter backed by a MediaStore content provider. + * It generates simple one- or two-line text views to display each media + * element. + * + * Filtering is supported, as is a more specific type of filtering referred to + * as limiting. Limiting is separate from filtering; a new filter will not + * erase an active filter. Limiting is intended to allow only media belonging + * to a specific group to be displayed, e.g. only songs from a certain artist. + * See MediaView.getLimiter and setLimiter for details. + */ 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 }; + /** + * Type indicating that MediaStore.Audio.Artists should be used as the + * provider backing this adapter. + */ + public static final int TYPE_ARTIST = 1; + /** + * Type indicating that MediaStore.Audio.Albums should be used as the + * adapter backing this adapter. + */ + public static final int TYPE_ALBUM = 2; Uri mStore; String[] mFields; @@ -58,17 +72,18 @@ public class MediaAdapter extends CursorAdapter implements FilterQueryProvider { private String[] mLimiter; private CharSequence mConstraint; - public MediaAdapter(Context context, Uri store, String[] fields, String[] fieldKeys, boolean expandable) + /** + * Perform required setup during construction. See constructors for + * details. + */ + private void init(Context context, Uri store, String[] fields, String[] fieldKeys, boolean expandable) { - super(context, null, true); - mStore = store; mFields = fields; mFieldKeys = fieldKeys; mExpandable = expandable; setFilterQueryProvider(this); - requery(); if (mPaint == null) { @@ -82,6 +97,65 @@ public class MediaAdapter extends CursorAdapter implements FilterQueryProvider { } } + /** + * Construct a MediaAdapter representing an arbitrary media content + * provider. + * + * @param context A Context to use + * @param store The external content uri of the provider + * @param fields The fields to use in the provider. The last field will be + * displayed as the first line in views. If more than one field is given, + * the first field will be displayed as the bottom line. + * @param fieldKeys The sorting keys corresponding to each field from + * fields. Used for filtering. + * @param expandable Whether an expand arrow should be shown to the right + * of the views' text + * @param requery If true, automatically update the adapter when the + * provider backing it changes + */ + protected MediaAdapter(Context context, Uri store, String[] fields, String[] fieldKeys, boolean expandable, boolean requery) + { + super(context, null, requery); + init(context, store, fields, fieldKeys, expandable); + } + + /** + * Construct a MediaAdapter representing the given type of + * media. + * + * @param context A Context to use + * @param type The type of media; one of TYPE_ALBUM or TYPE_ARTIST + * @param expandable Whether an expand arrow should be shown to the right + * of the views' text + * @param requery If true, automatically update the adapter when the + * provider backing it changes + */ + public MediaAdapter(Context context, int type, boolean expandable, boolean requery) + { + super(context, null, requery); + + Uri store; + String[] fields; + String[] fieldKeys; + switch (type) { + case TYPE_ARTIST: + store = MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI; + fields = new String[] { MediaStore.Audio.Artists.ARTIST }; + fieldKeys = new String[] { MediaStore.Audio.Artists.ARTIST_KEY }; + break; + case TYPE_ALBUM: + store = MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI; + fields = new String[] { 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. + fieldKeys = new String[] { "artist_key", MediaStore.Audio.Albums.ALBUM_KEY }; + break; + default: + throw new IllegalArgumentException("Invalid value for type: " + type); + } + + init(context, store, fields, fieldKeys, expandable); + } + public final void requery() { changeCursor(runQuery(mConstraint)); @@ -195,12 +269,6 @@ public class MediaAdapter extends CursorAdapter implements FilterQueryProvider { return mLimiter.length; } - @Override - protected void onContentChanged() - { - // do nothing; we implement this in SongSelector - } - @Override public void bindView(View view, Context context, Cursor cursor) { diff --git a/src/org/kreed/vanilla/SongMediaAdapter.java b/src/org/kreed/vanilla/SongMediaAdapter.java index 3bf3b23d..f61bf959 100644 --- a/src/org/kreed/vanilla/SongMediaAdapter.java +++ b/src/org/kreed/vanilla/SongMediaAdapter.java @@ -21,10 +21,28 @@ package org.kreed.vanilla; import android.content.Context; import android.provider.MediaStore; +/** + * Subclasses MediaAdapter to represent songs. Providers some song-specific + * logic over plain MediaAdapter: exclusion of non-music media files and + * better sorting inside albums. + */ public class SongMediaAdapter extends MediaAdapter { - public SongMediaAdapter(Context context) + /** + * Construct a MediaAdapter backed by MediaStore.Audio.Media. + * + * @param context A Context to use + * @param expandable Whether an expander arrow should by shown to the right + * of views + * @param requery If true, automatically update the adapter when the + * provider changes + */ + public SongMediaAdapter(Context context, boolean expandable, boolean requery) { - super(context, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, SONG_FIELDS, SONG_FIELD_KEYS, false); + super(context, + MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, + new String[] { MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.ALBUM, MediaStore.Audio.Media.TITLE }, + new String[] { MediaStore.Audio.Media.ARTIST_KEY, MediaStore.Audio.Media.ALBUM_KEY, MediaStore.Audio.Media.TITLE_KEY }, + expandable, requery); } @Override diff --git a/src/org/kreed/vanilla/SongSelector.java b/src/org/kreed/vanilla/SongSelector.java index a21aa72d..9817fbbc 100644 --- a/src/org/kreed/vanilla/SongSelector.java +++ b/src/org/kreed/vanilla/SongSelector.java @@ -413,9 +413,9 @@ public class SongSelector extends PlaybackActivity implements AdapterView.OnItem { switch (message.what) { case MSG_INIT: - setupView(R.id.artist_list, new MediaAdapter(this, MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI, MediaAdapter.ARTIST_FIELDS, MediaAdapter.ARTIST_FIELD_KEYS, true)); - setupView(R.id.album_list, new MediaAdapter(this, MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, MediaAdapter.ALBUM_FIELDS, MediaAdapter.ALBUM_FIELD_KEYS, true)); - setupView(R.id.song_list, new SongMediaAdapter(this)); + setupView(R.id.artist_list, new MediaAdapter(this, MediaAdapter.TYPE_ARTIST, true, false)); + setupView(R.id.album_list, new MediaAdapter(this, MediaAdapter.TYPE_ALBUM, true, false)); + setupView(R.id.song_list, new SongMediaAdapter(this, false, false)); ContentResolver resolver = getContentResolver(); Observer observer = new Observer(mHandler);