expose support for albumartist and composer tags

This commit is contained in:
Adrian Ulrich 2017-03-04 18:29:20 +01:00
parent f4d0028176
commit 798400d713
8 changed files with 327 additions and 70 deletions

View File

@ -109,6 +109,8 @@ THE SOFTWARE.
<string name="artists">Artists</string>
<string name="albums">Albums</string>
<string name="albumartists">Album Artists</string>
<string name="composers">Composers</string>
<string name="songs">Tracks</string>
<string name="playlists">Playlists</string>
<string name="genres">Genres</string>

View File

@ -29,19 +29,22 @@ import java.io.File;
public class MediaLibrary {
public static final String TABLE_SONGS = "songs";
public static final String TABLE_ALBUMS = "albums";
public static final String TABLE_CONTRIBUTORS = "contributors";
public static final String TABLE_CONTRIBUTORS_SONGS = "contributors_songs";
public static final String TABLE_GENRES = "genres";
public static final String TABLE_GENRES_SONGS = "genres_songs";
public static final String TABLE_PLAYLISTS = "playlists";
public static final String TABLE_PLAYLISTS_SONGS = "playlists_songs";
public static final String TABLE_PREFERENCES = "preferences";
public static final String VIEW_ARTISTS = "_artists";
public static final String VIEW_ALBUMS_ARTISTS = "_albums_artists";
public static final String VIEW_SONGS_ALBUMS_ARTISTS = "_songs_albums_artists";
public static final String VIEW_PLAYLIST_SONGS = "_playlists_songs";
public static final String TABLE_SONGS = "songs";
public static final String TABLE_ALBUMS = "albums";
public static final String TABLE_CONTRIBUTORS = "contributors";
public static final String TABLE_CONTRIBUTORS_SONGS = "contributors_songs";
public static final String TABLE_GENRES = "genres";
public static final String TABLE_GENRES_SONGS = "genres_songs";
public static final String TABLE_PLAYLISTS = "playlists";
public static final String TABLE_PLAYLISTS_SONGS = "playlists_songs";
public static final String TABLE_PREFERENCES = "preferences";
public static final String VIEW_ARTISTS = "_artists";
public static final String VIEW_ALBUMARTISTS = "_albumartists";
public static final String VIEW_COMPOSERS = "_composers";
public static final String VIEW_ALBUMS_ARTISTS = "_albums_artists";
public static final String VIEW_SONGS_ALBUMS_ARTISTS = "_songs_albums_artists";
public static final String VIEW_SONGS_ALBUMS_ARTISTS_HUGE = "_songs_albums_artists_huge";
public static final String VIEW_PLAYLIST_SONGS = "_playlists_songs";
public static final int ROLE_ARTIST = 0;
public static final int ROLE_COMPOSER = 1;
@ -561,6 +564,7 @@ public class MediaLibrary {
* The mtime of this item
*/
String MTIME = "mtime";
/**
* ONLY IN VIEWS - the artist
*/
@ -573,6 +577,33 @@ public class MediaLibrary {
* ONLY IN VIEWS - the artist id
*/
String ARTIST_ID = "artist_id";
/**
* ONLY IN VIEWS - the albumartist
*/
String ALBUMARTIST = "albumartist";
/**
* ONLY IN VIEWS - the albumartist_sort key
*/
String ALBUMARTIST_SORT = "albumartist_sort";
/**
* ONLY IN VIEWS - the albumartist id
*/
String ALBUMARTIST_ID = "albumartist_id";
/**
* ONLY IN VIEWS - the composer
*/
String COMPOSER = "composer";
/**
* ONLY IN VIEWS - the composer_sort key
*/
String COMPOSER_SORT = "composer_sort";
/**
* ONLY IN VIEWS - the composer id
*/
String COMPOSER_ID = "composer_id";
}
// Songs <-> Contributor mapping

View File

@ -35,7 +35,7 @@ public class MediaLibraryBackend extends SQLiteOpenHelper {
/**
* The database version we are using
*/
private static final int DATABASE_VERSION = 20170211;
private static final int DATABASE_VERSION = 20170217;
/**
* on-disk file to store the database
*/
@ -48,6 +48,14 @@ public class MediaLibraryBackend extends SQLiteOpenHelper {
* Regexp to detect costy artist_id queries which we can optimize
*/
private static final Pattern sQueryMatchArtistSearch = Pattern.compile("(^|.+ )"+MediaLibrary.ContributorColumns.ARTIST_ID+"=(\\d+)$");
/**
* Regexp to detect costy albumartist_id queries which we can optimize
*/
private static final Pattern sQueryMatchAlbArtistSearch = Pattern.compile("(^|.+ )"+MediaLibrary.ContributorColumns.ALBUMARTIST_ID+"=(\\d+)$");
/**
* Regexp to detect costy composer_id queries which we can optimize
*/
private static final Pattern sQueryMatchComposerSearch = Pattern.compile("(^|.+ )"+MediaLibrary.ContributorColumns.COMPOSER_ID+"=(\\d+)$");
/**
* Constructor for the MediaLibraryBackend helper
@ -232,29 +240,36 @@ public class MediaLibraryBackend extends SQLiteOpenHelper {
*/
Cursor query (boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) {
if (MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS_HUGE.equals(table)) {
Log.v("VanillaMusic", "+++ warning : using HUGE table in genquery!");
}
if (selection != null) {
if (MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS.equals(table)) {
// artist matches in the song-view are costy: try to give sqlite a hint
Matcher artistMatch = sQueryMatchArtistSearch.matcher(selection);
if (artistMatch.matches()) {
selection = artistMatch.group(1);
final String artistId = artistMatch.group(2);
String[] contributorMatch = extractVirtualColumn(selection);
if (contributorMatch != null) {
selection = contributorMatch[0];
final String contributorId = contributorMatch[1];
final String contributorRole = contributorMatch[2];
selection += MediaLibrary.SongColumns._ID+" IN (SELECT "+MediaLibrary.ContributorSongColumns.SONG_ID+" FROM "+MediaLibrary.TABLE_CONTRIBUTORS_SONGS+" WHERE "
+ MediaLibrary.ContributorSongColumns.ROLE+"=0 AND "+MediaLibrary.ContributorSongColumns._CONTRIBUTOR_ID+"="+artistId+")";
+ MediaLibrary.ContributorSongColumns.ROLE+"="+contributorRole+" AND "+MediaLibrary.ContributorSongColumns._CONTRIBUTOR_ID+"="+contributorId+")";
}
}
if (MediaLibrary.VIEW_ALBUMS_ARTISTS.equals(table)) {
// looking up artists by albums will magically return every album where this
// artist has at least one item (while still using the primary_artist_id as the artist key)
Matcher artistMatch = sQueryMatchArtistSearch.matcher(selection);
if (artistMatch.matches()) {
selection = artistMatch.group(1);
final String artistId = artistMatch.group(2);
String[] contributorMatch = extractVirtualColumn(selection);
if (contributorMatch != null) {
selection = contributorMatch[0];
final String contributorId = contributorMatch[1];
final String contributorRole = contributorMatch[2];
selection += MediaLibrary.SongColumns._ID+" IN (SELECT DISTINCT "+MediaLibrary.SongColumns.ALBUM_ID+" FROM "+MediaLibrary.TABLE_SONGS+" WHERE "
+ MediaLibrary.SongColumns._ID+" IN (SELECT "+MediaLibrary.ContributorSongColumns.SONG_ID+" FROM "+MediaLibrary.TABLE_CONTRIBUTORS_SONGS+" WHERE "
+ MediaLibrary.ContributorSongColumns.ROLE+"=0 AND "+MediaLibrary.ContributorSongColumns._CONTRIBUTOR_ID+"="+artistId+"))";
+ MediaLibrary.ContributorSongColumns.ROLE+"="+contributorRole+" AND "+MediaLibrary.ContributorSongColumns._CONTRIBUTOR_ID+"="+contributorId+"))";
}
}
@ -265,17 +280,33 @@ public class MediaLibraryBackend extends SQLiteOpenHelper {
final String genreId = genreMatch.group(2); // and extract the searched genre id
final String songsQuery = buildSongIdFromGenreSelect(genreId);
if(table.equals(MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS)) {
if(table.equals(MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS) ||
table.equals(MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS_HUGE) ) {
selection += MediaLibrary.SongColumns._ID+" IN ("+songsQuery+") ";
}
if (table.equals(MediaLibrary.VIEW_ARTISTS)) {
selection += MediaLibrary.ContributorColumns.ARTIST_ID+" IN ("+ buildSongIdFromGenreSelect(MediaLibrary.ContributorColumns.ARTIST_ID, songsQuery)+") ";
if (table.equals(MediaLibrary.VIEW_ALBUMS_ARTISTS)) {
selection += MediaLibrary.AlbumColumns._ID+" IN ("+
buildSongIdFromGenreSelect(MediaLibrary.SongColumns.ALBUM_ID, MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS, songsQuery)+") ";
}
if (table.equals(MediaLibrary.VIEW_ALBUMS_ARTISTS)) {
selection += MediaLibrary.AlbumColumns._ID+" IN ("+ buildSongIdFromGenreSelect(MediaLibrary.SongColumns.ALBUM_ID, songsQuery)+") ";
if (table.equals(MediaLibrary.VIEW_ARTISTS)) {
selection += MediaLibrary.ContributorColumns.ARTIST_ID+" IN ("+
buildSongIdFromGenreSelect(MediaLibrary.ContributorColumns.ARTIST_ID, MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS, songsQuery)+") ";
}
if (table.equals(MediaLibrary.VIEW_ALBUMARTISTS)) {
selection += MediaLibrary.ContributorColumns.ALBUMARTIST_ID+" IN ("+
buildSongIdFromGenreSelect(MediaLibrary.ContributorColumns.ALBUMARTIST_ID, MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS_HUGE, songsQuery)+") ";
Log.v("VanillaMusic", "+++ warning: huge genrequery for albumartist!");
}
if (table.equals(MediaLibrary.VIEW_COMPOSERS)) {
selection += MediaLibrary.ContributorColumns.COMPOSER_ID+" IN ("+
buildSongIdFromGenreSelect(MediaLibrary.ContributorColumns.COMPOSER_ID, MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS_HUGE, songsQuery)+") ";
Log.v("VanillaMusic", "+++ warning: huge genrequery composer!");
}
}
}
@ -294,6 +325,26 @@ public class MediaLibraryBackend extends SQLiteOpenHelper {
return cursor;
}
/**
* Detects queries for artists, composers and albumartists and returns the
* role of the contributor.
*
* @param sql the raw sql query
* @return String[]{ sql-part, contributor-id, contributor-role }
*/
private String[] extractVirtualColumn(String sql) {
final Pattern[] pattern = new Pattern[]{ sQueryMatchArtistSearch, sQueryMatchComposerSearch, sQueryMatchAlbArtistSearch };
final int[] roles = { MediaLibrary.ROLE_ARTIST, MediaLibrary.ROLE_COMPOSER, MediaLibrary.ROLE_ALBUMARTIST };
for (int i=0; i < roles.length; i++) {
Matcher matcher = pattern[i].matcher(sql);
if (matcher.matches()) {
return new String[]{ matcher.group(1), matcher.group(2), String.format("%d", roles[i]) };
}
}
return null;
}
/**
* Returns a select query to get all songs from a genre
*
@ -309,11 +360,12 @@ public class MediaLibraryBackend extends SQLiteOpenHelper {
* Returns a select query to get artists or albums from a genre
*
* @param target the target to query
* @param table the table to query
* @param genreSelect the select string generated by buildSongIdFromGenreSelect
* @return an SQL string
*/
private String buildSongIdFromGenreSelect(String target, String genreSelect) {
return "SELECT "+target+" FROM "+MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS+" WHERE "
private String buildSongIdFromGenreSelect(String target, String table, String genreSelect) {
return "SELECT "+target+" FROM "+ table +" WHERE "
+MediaLibrary.SongColumns._ID+" IN ("+genreSelect+") GROUP BY "+target;
}

View File

@ -145,7 +145,22 @@ public class MediaSchema {
+",_artist."+MediaLibrary.ContributorColumns._ID+" AS "+MediaLibrary.ContributorColumns.ARTIST_ID;
/**
* View which includes song, album and artist information
* Additional columns to select for albumartist info
*/
private static final String VIEW_ALBUMARTIST_SELECT = "_albumartist."+MediaLibrary.ContributorColumns._CONTRIBUTOR+" AS "+MediaLibrary.ContributorColumns.ALBUMARTIST
+",_albumartist."+MediaLibrary.ContributorColumns._CONTRIBUTOR_SORT+" AS "+MediaLibrary.ContributorColumns.ALBUMARTIST_SORT
+",_albumartist."+MediaLibrary.ContributorColumns._ID+" AS "+MediaLibrary.ContributorColumns.ALBUMARTIST_ID;
/**
* Additional columns to select for composer info
*/
private static final String VIEW_COMPOSER_SELECT = "_composer."+MediaLibrary.ContributorColumns._CONTRIBUTOR+" AS "+MediaLibrary.ContributorColumns.COMPOSER
+",_composer."+MediaLibrary.ContributorColumns._CONTRIBUTOR_SORT+" AS "+MediaLibrary.ContributorColumns.COMPOSER_SORT
+",_composer."+MediaLibrary.ContributorColumns._ID+" AS "+MediaLibrary.ContributorColumns.COMPOSER_ID;
/**
* View which includes song, album and artist information, enough for a filled song projection
*/
private static final String VIEW_CREATE_SONGS_ALBUMS_ARTISTS = "CREATE VIEW "+ MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS+ " AS "
+ "SELECT *, " + VIEW_ARTIST_SELECT + " FROM " + MediaLibrary.TABLE_SONGS
@ -155,6 +170,26 @@ public class MediaSchema {
+" LEFT JOIN "+MediaLibrary.TABLE_CONTRIBUTORS+" AS _artist ON _artist."+MediaLibrary.ContributorColumns._ID+" = "+MediaLibrary.TABLE_CONTRIBUTORS_SONGS+"."+MediaLibrary.ContributorSongColumns._CONTRIBUTOR_ID
+" ;";
/**
* View wich includes SONGS_ALBUMS_ARTISTS and any other contributors
* This view should only be used if needed as the SQL query is pretty expensive
*/
private static final String VIEW_CREATE_SONGS_ALBUMS_ARTISTS_HUGE = "CREATE VIEW "+ MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS_HUGE+" AS "
+ "SELECT *, "+ VIEW_ALBUMARTIST_SELECT +", "+ VIEW_COMPOSER_SELECT +" FROM "+MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS
// albumartists
+" LEFT JOIN "+MediaLibrary.TABLE_CONTRIBUTORS_SONGS+" as __albumartists"
+" ON __albumartists."+MediaLibrary.ContributorSongColumns.ROLE+"="+MediaLibrary.ROLE_ALBUMARTIST
+" AND __albumartists."+MediaLibrary.ContributorSongColumns.SONG_ID+" = "+MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS+"."+MediaLibrary.SongColumns._ID
+" LEFT JOIN "+MediaLibrary.TABLE_CONTRIBUTORS+" AS _albumartist ON"
+" _albumartist."+MediaLibrary.ContributorColumns._ID+" = __albumartists."+MediaLibrary.ContributorSongColumns._CONTRIBUTOR_ID
// composers
+" LEFT JOIN "+MediaLibrary.TABLE_CONTRIBUTORS_SONGS+" as __composers"
+" ON __composers."+MediaLibrary.ContributorSongColumns.ROLE+"="+MediaLibrary.ROLE_COMPOSER
+" AND __composers."+MediaLibrary.ContributorSongColumns.SONG_ID+" = "+MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS+"."+MediaLibrary.SongColumns._ID
+" LEFT JOIN "+MediaLibrary.TABLE_CONTRIBUTORS+" AS _composer ON"
+" _composer."+MediaLibrary.ContributorColumns._ID+" = __composers."+MediaLibrary.ContributorSongColumns._CONTRIBUTOR_ID
+" ;";
/**
* View which includes album and artist information
*/
@ -173,6 +208,24 @@ public class MediaSchema {
+" WHERE "+MediaLibrary.ContributorSongColumns.ROLE+"="+MediaLibrary.ROLE_ARTIST+" GROUP BY "+MediaLibrary.ContributorSongColumns._CONTRIBUTOR_ID+")"
+" ;";
/**
* View which includes albumArtists information
*/
private static final String VIEW_CREATE_ALBUMARTISTS = "CREATE VIEW "+ MediaLibrary.VIEW_ALBUMARTISTS+ " AS "
+ "SELECT *, " + VIEW_ALBUMARTIST_SELECT + " FROM "+MediaLibrary.TABLE_CONTRIBUTORS+" AS _albumartist WHERE "+MediaLibrary.ContributorColumns._ID+" IN "
+" (SELECT "+MediaLibrary.ContributorSongColumns._CONTRIBUTOR_ID+" FROM "+MediaLibrary.TABLE_CONTRIBUTORS_SONGS
+" WHERE "+MediaLibrary.ContributorSongColumns.ROLE+"="+MediaLibrary.ROLE_ALBUMARTIST+" GROUP BY "+MediaLibrary.ContributorSongColumns._CONTRIBUTOR_ID+")"
+" ;";
/**
* View which includes composer information
*/
private static final String VIEW_CREATE_COMPOSERS = "CREATE VIEW "+ MediaLibrary.VIEW_COMPOSERS+ " AS "
+ "SELECT *, " + VIEW_COMPOSER_SELECT + " FROM "+MediaLibrary.TABLE_CONTRIBUTORS+" AS _composer WHERE "+MediaLibrary.ContributorColumns._ID+" IN "
+" (SELECT "+MediaLibrary.ContributorSongColumns._CONTRIBUTOR_ID+" FROM "+MediaLibrary.TABLE_CONTRIBUTORS_SONGS
+" WHERE "+MediaLibrary.ContributorSongColumns.ROLE+"="+MediaLibrary.ROLE_COMPOSER+" GROUP BY "+MediaLibrary.ContributorSongColumns._CONTRIBUTOR_ID+")"
+" ;";
/**
* View like VIEW_CREATE_ARTISTS but includes playlist information
*/
@ -204,8 +257,11 @@ public class MediaSchema {
dbh.execSQL(INDEX_IDX_PLAYLIST_ID);
dbh.execSQL(INDEX_IDX_PLAYLIST_ID_SONG);
dbh.execSQL(VIEW_CREATE_SONGS_ALBUMS_ARTISTS);
dbh.execSQL(VIEW_CREATE_SONGS_ALBUMS_ARTISTS_HUGE);
dbh.execSQL(VIEW_CREATE_ALBUMS_ARTISTS);
dbh.execSQL(VIEW_CREATE_ARTISTS);
dbh.execSQL(VIEW_CREATE_ALBUMARTISTS);
dbh.execSQL(VIEW_CREATE_COMPOSERS);
dbh.execSQL(VIEW_CREATE_PLAYLIST_SONGS);
dbh.execSQL(DATABASE_CREATE_PREFERENCES);
}
@ -240,6 +296,12 @@ public class MediaSchema {
dbh.execSQL("UPDATE songs SET mtime=1 WHERE mtime=0");
}
if (oldVersion < 20170217) {
dbh.execSQL(VIEW_CREATE_ALBUMARTISTS);
dbh.execSQL(VIEW_CREATE_COMPOSERS);
dbh.execSQL(VIEW_CREATE_SONGS_ALBUMS_ARTISTS_HUGE);
}
}
/**

View File

@ -47,6 +47,7 @@ import android.widget.ListView;
import android.widget.TextView;
import android.widget.LinearLayout;
import java.util.Arrays;
import java.util.ArrayList;
/**
* PagerAdapter that manages the library media ListViews.
@ -62,18 +63,25 @@ public class LibraryPagerAdapter
* The number of unique list types. The number of visible lists may be
* smaller.
*/
public static final int MAX_ADAPTER_COUNT = 6;
public static final int MAX_ADAPTER_COUNT = MediaUtils.TYPE_COUNT;
/**
* The human-readable title for each list. The positions correspond to the
* MediaUtils ids, so e.g. TITLES[MediaUtils.TYPE_SONG] = R.string.songs
*/
public static final int[] TITLES = { R.string.artists, R.string.albums, R.string.songs,
R.string.playlists, R.string.genres, R.string.files };
public static final int[] TITLES = { R.string.artists, R.string.albumartists, R.string.composers,
R.string.albums, R.string.songs, R.string.playlists,
R.string.genres, R.string.files };
/**
* Default tab order.
*/
public static final int[] DEFAULT_ORDER = { MediaUtils.TYPE_ARTIST, MediaUtils.TYPE_ALBUM, MediaUtils.TYPE_SONG,
MediaUtils.TYPE_PLAYLIST, MediaUtils.TYPE_GENRE, MediaUtils.TYPE_FILE };
public static final int[] DEFAULT_TAB_ORDER = { MediaUtils.TYPE_ARTIST, MediaUtils.TYPE_ALBARTIST, MediaUtils.TYPE_COMPOSER,
MediaUtils.TYPE_ALBUM, MediaUtils.TYPE_SONG, MediaUtils.TYPE_PLAYLIST,
MediaUtils.TYPE_GENRE, MediaUtils.TYPE_FILE };
/**
* The default visibility of tabs
*/
public static final boolean[] DEFAULT_TAB_VISIBILITY = { true, false, false, true, true, true, true, true };
/**
* The user-chosen tab order.
*/
@ -99,6 +107,14 @@ public class LibraryPagerAdapter
* The artist adapter instance, also stored at mAdapters[MediaUtils.TYPE_ARTIST].
*/
private MediaAdapter mArtistAdapter;
/**
* The albumartist adapter instance, also stored at mAdapters[MediaUtils.TYPE_ALBART].
*/
private MediaAdapter mAlbArtAdapter;
/**
* The composer adapter instance, also stored at mAdapters[MediaUtils.TYPE_COMPOSER].
*/
private MediaAdapter mComposerAdapter;
/**
* The album adapter instance, also stored at mAdapters[MediaUtils.TYPE_ALBUM].
*/
@ -135,6 +151,14 @@ public class LibraryPagerAdapter
* A limiter that should be set when the album adapter is created.
*/
private Limiter mPendingArtistLimiter;
/**
* A limiter that should be set when the albumartist adapter is created.
*/
private Limiter mPendingAlbArtLimiter;
/**
* A limiter that should be set when the composer adapter is created.
*/
private Limiter mPendingComposerLimiter;
/**
* A limiter that should be set when the album adapter is created.
*/
@ -165,9 +189,10 @@ public class LibraryPagerAdapter
* song limiters.
*/
private String mHeaderText;
private DraggableRow mArtistHeader;
private DraggableRow mAlbumHeader;
private DraggableRow mSongHeader;
/**
* A list of header rows which require test updates
*/
private ArrayList<DraggableRow> mHeaderViews = new ArrayList();
/**
* The current filter text, or null if none.
*/
@ -224,23 +249,18 @@ public class LibraryPagerAdapter
public boolean loadTabOrder()
{
String in = PlaybackService.getSettings(mActivity).getString(PrefKeys.TAB_ORDER, PrefDefaults.TAB_ORDER);
int[] order;
int count;
if (in == null || in.length() != MAX_ADAPTER_COUNT) {
order = DEFAULT_ORDER;
count = MAX_ADAPTER_COUNT;
} else {
int[] order = new int[MAX_ADAPTER_COUNT];
int count = 0;
if (in != null && in.length() == MAX_ADAPTER_COUNT) {
char[] chars = in.toCharArray();
order = new int[MAX_ADAPTER_COUNT];
count = 0;
for (int i = 0; i != MAX_ADAPTER_COUNT; ++i) {
char v = chars[i];
if (v >= 128) {
v -= 128;
if (v >= MediaUtils.TYPE_COUNT) {
// invalid media type; use default order
order = DEFAULT_ORDER;
count = MAX_ADAPTER_COUNT;
// invalid media type, ignore all data
count = 0;
break;
}
order[count++] = v;
@ -248,6 +268,14 @@ public class LibraryPagerAdapter
}
}
// set default tabs if none were loaded
if (count == 0) {
for (int i=0; i != MAX_ADAPTER_COUNT; i++) {
if (DEFAULT_TAB_VISIBILITY[i])
order[count++] = DEFAULT_TAB_ORDER[i];
}
}
if (count != mTabCount || !Arrays.equals(order, mTabOrder)) {
mTabOrder = order;
mTabCount = count;
@ -316,18 +344,28 @@ public class LibraryPagerAdapter
case MediaUtils.TYPE_ARTIST:
adapter = mArtistAdapter = new MediaAdapter(activity, MediaUtils.TYPE_ARTIST, mPendingArtistLimiter, activity);
mArtistAdapter.setExpandable(mSongsPosition != -1 || mAlbumsPosition != -1);
mArtistHeader = header = (DraggableRow)inflater.inflate(R.layout.draggable_row, null);
header = (DraggableRow)inflater.inflate(R.layout.draggable_row, null);
break;
case MediaUtils.TYPE_ALBARTIST:
adapter = mAlbArtAdapter = new MediaAdapter(activity, MediaUtils.TYPE_ALBARTIST, mPendingAlbArtLimiter, activity);
mAlbArtAdapter.setExpandable(mSongsPosition != -1 || mAlbumsPosition != -1);
header = (DraggableRow)inflater.inflate(R.layout.draggable_row, null);
break;
case MediaUtils.TYPE_COMPOSER:
adapter = mComposerAdapter = new MediaAdapter(activity, MediaUtils.TYPE_COMPOSER, mPendingComposerLimiter, activity);
mComposerAdapter.setExpandable(mSongsPosition != -1 || mAlbumsPosition != -1);
header = (DraggableRow)inflater.inflate(R.layout.draggable_row, null);
break;
case MediaUtils.TYPE_ALBUM:
adapter = mAlbumAdapter = new MediaAdapter(activity, MediaUtils.TYPE_ALBUM, mPendingAlbumLimiter, activity);
mAlbumAdapter.setExpandable(mSongsPosition != -1);
mPendingAlbumLimiter = null;
mAlbumHeader = header = (DraggableRow)inflater.inflate(R.layout.draggable_row, null);
header = (DraggableRow)inflater.inflate(R.layout.draggable_row, null);
break;
case MediaUtils.TYPE_SONG:
adapter = mSongAdapter = new MediaAdapter(activity, MediaUtils.TYPE_SONG, mPendingSongLimiter, activity);
mPendingSongLimiter = null;
mSongHeader = header = (DraggableRow)inflater.inflate(R.layout.draggable_row, null);
header = (DraggableRow)inflater.inflate(R.layout.draggable_row, null);
break;
case MediaUtils.TYPE_PLAYLIST:
adapter = mPlaylistAdapter = new MediaAdapter(activity, MediaUtils.TYPE_PLAYLIST, null, activity);
@ -353,6 +391,7 @@ public class LibraryPagerAdapter
header.getTextView().setText(mHeaderText);
header.setTag(new ViewHolder()); // behave like a normal library row
view.addHeaderView(header);
mHeaderViews.add(header);
}
view.setAdapter(adapter);
if (type != MediaUtils.TYPE_FILE)
@ -424,6 +463,8 @@ public class LibraryPagerAdapter
{
Bundle in = (Bundle)state;
mPendingArtistLimiter = (Limiter)in.getSerializable("limiter_artists");
mPendingAlbArtLimiter = (Limiter)in.getSerializable("limiter_albumartists");
mPendingComposerLimiter = (Limiter)in.getSerializable("limiter_composer");
mPendingAlbumLimiter = (Limiter)in.getSerializable("limiter_albums");
mPendingSongLimiter = (Limiter)in.getSerializable("limiter_songs");
mPendingFileLimiter = (Limiter)in.getSerializable("limiter_files");
@ -435,6 +476,10 @@ public class LibraryPagerAdapter
Bundle out = new Bundle(10);
if (mArtistAdapter != null)
out.putSerializable("limiter_artists", mArtistAdapter.getLimiter());
if (mAlbArtAdapter != null)
out.putSerializable("limiter_albumartists", mAlbArtAdapter.getLimiter());
if (mComposerAdapter != null)
out.putSerializable("limiter_composer", mComposerAdapter.getLimiter());
if (mAlbumAdapter != null)
out.putSerializable("limiter_albums", mAlbumAdapter.getLimiter());
if (mSongAdapter != null)
@ -452,12 +497,9 @@ public class LibraryPagerAdapter
*/
public void setHeaderText(String text)
{
if (mArtistHeader != null)
mArtistHeader.getTextView().setText(text);
if (mAlbumHeader != null)
mAlbumHeader.getTextView().setText(text);
if (mSongHeader != null)
mSongHeader.getTextView().setText(text);
for(DraggableRow row : mHeaderViews) {
row.getTextView().setText(text);
}
mHeaderText = text;
}
@ -485,6 +527,20 @@ public class LibraryPagerAdapter
loadSortOrder(mArtistAdapter);
requestRequery(mArtistAdapter);
}
if (mAlbArtAdapter == null) {
mPendingAlbArtLimiter = null;
} else {
mAlbArtAdapter.setLimiter(null);
loadSortOrder(mAlbArtAdapter);
requestRequery(mAlbArtAdapter);
}
if (mComposerAdapter == null) {
mPendingComposerLimiter = null;
} else {
mComposerAdapter.setLimiter(null);
loadSortOrder(mComposerAdapter);
requestRequery(mComposerAdapter);
}
if (mAlbumAdapter == null) {
mPendingAlbumLimiter = null;
} else {
@ -526,6 +582,8 @@ public class LibraryPagerAdapter
tab = mSongsPosition;
break;
case MediaUtils.TYPE_ARTIST:
case MediaUtils.TYPE_ALBARTIST:
case MediaUtils.TYPE_COMPOSER:
if (mAlbumAdapter == null) {
mPendingAlbumLimiter = limiter;
} else {
@ -552,6 +610,20 @@ public class LibraryPagerAdapter
loadSortOrder(mArtistAdapter);
requestRequery(mArtistAdapter);
}
if (mAlbArtAdapter == null) {
mPendingAlbArtLimiter = limiter;
} else {
mAlbArtAdapter.setLimiter(limiter);
loadSortOrder(mAlbArtAdapter);
requestRequery(mAlbArtAdapter);
}
if (mComposerAdapter == null) {
mPendingComposerLimiter = limiter;
} else {
mComposerAdapter.setLimiter(limiter);
loadSortOrder(mComposerAdapter);
requestRequery(mComposerAdapter);
}
if (mAlbumAdapter == null) {
mPendingAlbumLimiter = limiter;
} else {

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015-2016 Adrian Ulrich <adrian@blinkenlights.ch>
* Copyright (C) 2015-2017 Adrian Ulrich <adrian@blinkenlights.ch>
* Copyright (C) 2010, 2011 Christopher Eby <kreed@kreed.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@ -189,6 +189,20 @@ public class MediaAdapter
mSortEntries = new int[] { R.string.title, R.string.date_added };
mAdapterSortValues = new String[] { MediaLibrary.ContributorColumns.ARTIST_SORT+" %1$s", MediaLibrary.ContributorColumns.MTIME+" %1$s" };
break;
case MediaUtils.TYPE_ALBARTIST:
mSource = MediaLibrary.VIEW_ALBUMARTISTS;
mFields = new String[] { MediaLibrary.ContributorColumns.ALBUMARTIST };
mFieldKeys = new String[] { MediaLibrary.ContributorColumns.ALBUMARTIST_SORT };
mSortEntries = new int[] { R.string.title, R.string.date_added };
mAdapterSortValues = new String[] { MediaLibrary.ContributorColumns.ALBUMARTIST_SORT+" %1$s", MediaLibrary.ContributorColumns.MTIME+" %1$s" };
break;
case MediaUtils.TYPE_COMPOSER:
mSource = MediaLibrary.VIEW_COMPOSERS;
mFields = new String[] { MediaLibrary.ContributorColumns.COMPOSER };
mFieldKeys = new String[] { MediaLibrary.ContributorColumns.COMPOSER_SORT };
mSortEntries = new int[] { R.string.title, R.string.date_added };
mAdapterSortValues = new String[] { MediaLibrary.ContributorColumns.COMPOSER_SORT+" %1$s", MediaLibrary.ContributorColumns.MTIME+" %1$s" };
break;
case MediaUtils.TYPE_ALBUM:
mSource = MediaLibrary.VIEW_ALBUMS_ARTISTS;
mFields = new String[] { MediaLibrary.AlbumColumns.ALBUM, MediaLibrary.ContributorColumns.ARTIST };
@ -308,7 +322,7 @@ public class MediaAdapter
String sortRaw = mAdapterSortValues[mode];
if (returnSongs) {
// songs returned from the artist tab should also sort by album
if (mType == MediaUtils.TYPE_ARTIST)
if (mType == MediaUtils.TYPE_ARTIST) // fixme: composer?
sortRaw += ", "+MediaLibrary.AlbumColumns.ALBUM_SORT+" %1$s";
// and this is for all types:
sortRaw += ", "+MediaLibrary.SongColumns.DISC_NUMBER+", "+MediaLibrary.SongColumns.SONG_NUMBER;
@ -364,7 +378,7 @@ public class MediaAdapter
}
if (returnSongs == true) {
source = MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS;
source = MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS_HUGE;
} else {
enrichedProjection = Arrays.copyOf(projection, projection.length + 1);
enrichedProjection[projection.length] = getFirstSortColumn();
@ -443,6 +457,14 @@ public class MediaAdapter
fields = new String[] { cursor.getString(2) };
data = String.format("%s=%d", MediaLibrary.ContributorColumns.ARTIST_ID, id);
break;
case MediaUtils.TYPE_ALBARTIST:
fields = new String[] { cursor.getString(2) };
data = String.format("%s=%d", MediaLibrary.ContributorColumns.ALBUMARTIST_ID, id);
break;
case MediaUtils.TYPE_COMPOSER:
fields = new String[] { cursor.getString(2) };
data = String.format("%s=%d", MediaLibrary.ContributorColumns.COMPOSER_ID, id);
break;
case MediaUtils.TYPE_ALBUM:
fields = new String[] { cursor.getString(3), cursor.getString(2) };
data = String.format("%s=%d", MediaLibrary.SongColumns.ALBUM_ID, id);

View File

@ -62,31 +62,39 @@ public class MediaUtils {
* Type indicating an id represents an artist.
*/
public static final int TYPE_ARTIST = 0;
/**
* Type indicating an id represents an albumartist
*/
public static final int TYPE_ALBARTIST = 1;
/**
* Type indicating an id represents a composer
*/
public static final int TYPE_COMPOSER = 2;
/**
* Type indicating an id represents an album.
*/
public static final int TYPE_ALBUM = 1;
public static final int TYPE_ALBUM = 3;
/**
* Type indicating an id represents a song.
*/
public static final int TYPE_SONG = 2;
public static final int TYPE_SONG = 4;
/**
* Type indicating an id represents a playlist.
*/
public static final int TYPE_PLAYLIST = 3;
public static final int TYPE_PLAYLIST = 5;
/**
* Type indicating ids represent genres.
*/
public static final int TYPE_GENRE = 4;
public static final int TYPE_GENRE = 6;
/**
* Special type for files and folders. Most methods do not accept this type
* since files have no MediaStore id and require special handling.
*/
public static final int TYPE_FILE = 5;
public static final int TYPE_FILE = 7;
/**
* The number of different valid media types.
*/
public static final int TYPE_COUNT = 6;
public static final int TYPE_COUNT = 8;
/**
* The default sort order for media queries. First artist, then album, then
@ -157,6 +165,12 @@ public class MediaUtils {
case TYPE_ARTIST:
selection.append(MediaLibrary.ContributorColumns.ARTIST_ID);
break;
case TYPE_ALBARTIST:
selection.append(MediaLibrary.ContributorColumns.ALBUMARTIST_ID);
break;
case TYPE_COMPOSER:
selection.append(MediaLibrary.ContributorColumns.COMPOSER_ID);
break;
case TYPE_ALBUM:
selection.append(MediaLibrary.SongColumns.ALBUM_ID);
sort = ALBUM_SORT;
@ -206,6 +220,8 @@ public class MediaUtils {
{
switch (type) {
case TYPE_ARTIST:
case TYPE_ALBARTIST:
case TYPE_COMPOSER:
case TYPE_ALBUM:
case TYPE_SONG:
case TYPE_GENRE:

View File

@ -95,10 +95,10 @@ public class TabOrderActivity extends Activity
*/
public void restoreDefault()
{
mAdapter.setTabIds(LibraryPagerAdapter.DEFAULT_ORDER.clone());
mAdapter.setTabIds(LibraryPagerAdapter.DEFAULT_TAB_ORDER.clone());
DragSortListView list = mList;
for (int i = 0; i != LibraryPagerAdapter.MAX_ADAPTER_COUNT; ++i) {
list.setItemChecked(i, true);
list.setItemChecked(i, LibraryPagerAdapter.DEFAULT_TAB_VISIBILITY[i]);
}
save();
}