expose support for albumartist and composer tags
This commit is contained in:
parent
f4d0028176
commit
798400d713
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user