Fixed issue showing songs without an album or artist

This commit is contained in:
Martijn Brekhof 2016-06-09 21:57:29 +02:00
parent e326da03d7
commit 21389b1e9e
8 changed files with 202 additions and 114 deletions

View File

@ -41,6 +41,7 @@ public class MediaContract {
public static final String PATH_ALBUMS = "albums"; public static final String PATH_ALBUMS = "albums";
public static final String PATH_AUDIO_GENRES = "audio_genres"; public static final String PATH_AUDIO_GENRES = "audio_genres";
public static final String PATH_SONGS = "songs"; public static final String PATH_SONGS = "songs";
public static final String PATH_SONG_ARTISTS = "song_artists";
public static final String PATH_ALBUM_ARTISTS = "album_artists"; public static final String PATH_ALBUM_ARTISTS = "album_artists";
public static final String PATH_ALBUM_GENRES = "album_genres"; public static final String PATH_ALBUM_GENRES = "album_genres";
public static final String PATH_MUSIC_VIDEOS = "music_videos"; public static final String PATH_MUSIC_VIDEOS = "music_videos";
@ -701,6 +702,36 @@ public class MediaContract {
}; };
} }
/**
* Columns for SongArtists table
* All Other IDs refer to XBMC Ids, not Internal ones
*/
public interface SongArtistsColumns {
String HOST_ID = "host_id";
String SONGID = "songid";
String ARTISTID = "artistid";
}
public static class SongArtists implements BaseColumns, SongArtistsColumns {
public static final Uri CONTENT_URI =
BASE_CONTENT_URI.buildUpon().appendPath(PATH_SONG_ARTISTS).build();
public static final String CONTENT_TYPE =
"vnd.android.cursor.dir/vnd.org.xbmc." + PATH_SONG_ARTISTS;
/** Build {@link Uri} for requested {@link #_ID}. */
public static Uri buildSongsForArtistListUri(long hostId, long artistId) {
return Hosts.buildHostUri(hostId).buildUpon()
.appendPath(PATH_ARTISTS)
.appendPath(String.valueOf(artistId))
.appendPath(PATH_SONGS)
.build();
}
public final static String[] ALL_COLUMNS = {
_ID, HOST_ID, SONGID, ARTISTID,
};
}
/** /**
* Columns for AlbumGenres table * Columns for AlbumGenres table
* All Other IDs refer to XBMC Ids, not Internal ones * All Other IDs refer to XBMC Ids, not Internal ones

View File

@ -32,7 +32,7 @@ public class MediaDatabase extends SQLiteOpenHelper {
private static final String DB_NAME = "xbmc.sqlite"; private static final String DB_NAME = "xbmc.sqlite";
private static final int DB_VERSION_PRE_EVENT_SERVER = 4, private static final int DB_VERSION_PRE_EVENT_SERVER = 4,
DB_VERSION = 5; DB_VERSION_PRE_SONG_ARTISTS = 5, DB_VERSION = 6;
/** /**
* Tables exposed * Tables exposed
@ -48,6 +48,7 @@ public class MediaDatabase extends SQLiteOpenHelper {
String ARTISTS = "artists"; String ARTISTS = "artists";
String ALBUMS = "albums"; String ALBUMS = "albums";
String SONGS = "songs"; String SONGS = "songs";
String SONG_ARTISTS = "song_artists";
String AUDIO_GENRES = "audio_genres"; String AUDIO_GENRES = "audio_genres";
String ALBUM_ARTISTS = "album_artists"; String ALBUM_ARTISTS = "album_artists";
String ALBUM_GENRES = "album_genres"; String ALBUM_GENRES = "album_genres";
@ -90,25 +91,25 @@ public class MediaDatabase extends SQLiteOpenHelper {
ALBUM_GENRES + "." + MediaContract.AlbumGenres.GENREID + "=" + AUDIO_GENRES + "." + MediaContract.AudioGenres.GENREID; ALBUM_GENRES + "." + MediaContract.AlbumGenres.GENREID + "=" + AUDIO_GENRES + "." + MediaContract.AudioGenres.GENREID;
/** /**
* Join to get Songs for an Artist * Join to get Songs for an Artist or Album with artist info and album info only if available
*/ */
String SONGS_FOR_ARTIST_JOIN = String SONGS_FOR_ARTIST_AND_OR_ALBUM_JOIN =
SONGS + " JOIN " + ALBUM_ARTISTS + " ON " + SONG_ARTISTS + " JOIN " + SONGS + " ON " +
SONGS + "." + MediaContract.Songs.HOST_ID + "=" + ALBUM_ARTISTS + "." + MediaContract.AlbumArtists.HOST_ID + SONG_ARTISTS + "." + MediaContract.SongArtists.HOST_ID + "=" + SONGS + "." + MediaContract.Songs.HOST_ID +
" AND " + " AND " +
SONGS + "." + MediaContract.Songs.ALBUMID + "=" + ALBUM_ARTISTS + "." + MediaContract.AlbumArtists.ALBUMID + SONG_ARTISTS + "." + MediaContract.SongArtists.SONGID + "=" + SONGS + "." + MediaContract.Songs.SONGID +
" JOIN " + ALBUMS + " ON " + " LEFT JOIN " + ARTISTS + " ON " +
SONGS + "." + MediaContract.Songs.HOST_ID + "=" + ALBUMS + "." + MediaContract.Albums.HOST_ID + SONG_ARTISTS + "." + MediaContract.SongArtists.HOST_ID + "=" + ARTISTS + "." + MediaContract.Artists.HOST_ID +
" AND " + " AND " +
SONGS + "." + MediaContract.Songs.ALBUMID + "=" + ALBUMS + "." + MediaContract.Albums.ALBUMID; SONG_ARTISTS + "." + MediaContract.SongArtists.ARTISTID + "=" + ARTISTS + "." + MediaContract.Artists.ARTISTID +
" LEFT JOIN " + ALBUMS + " ON " +
String SONGS_AND_ALBUM_JOIN = SONG_ARTISTS + "." + MediaContract.SongArtists.HOST_ID + "=" + ALBUMS + "." + MediaContract.Albums.HOST_ID +
SONGS + " JOIN " + ALBUMS + " ON " +
SONGS + "." + MediaContract.Songs.HOST_ID + "=" + ALBUMS + "." + MediaContract.Albums.HOST_ID +
" AND " + " AND " +
SONGS + "." + MediaContract.Songs.ALBUMID + "=" + ALBUMS + "." + MediaContract.Albums.ALBUMID; SONGS + "." + MediaContract.Songs.ALBUMID + "=" + ALBUMS + "." + MediaContract.Albums.ALBUMID;
} }
private interface References { private interface References {
String HOST_ID = String HOST_ID =
"REFERENCES " + Tables.HOSTS + "(" + BaseColumns._ID + ")"; "REFERENCES " + Tables.HOSTS + "(" + BaseColumns._ID + ")";
@ -118,6 +119,8 @@ public class MediaDatabase extends SQLiteOpenHelper {
"REFERENCES " + Tables.ARTISTS + "(" + MediaContract.ArtistsColumns.ARTISTID + ")"; "REFERENCES " + Tables.ARTISTS + "(" + MediaContract.ArtistsColumns.ARTISTID + ")";
String GENREID = String GENREID =
"REFERENCES " + Tables.AUDIO_GENRES + "(" + MediaContract.AudioGenresColumns.GENREID + ")"; "REFERENCES " + Tables.AUDIO_GENRES + "(" + MediaContract.AudioGenresColumns.GENREID + ")";
String SONGID =
"REFERENCES " + Tables.SONGS + "(" + MediaContract.Songs.SONGID + ")";
} }
public MediaDatabase(Context context) { public MediaDatabase(Context context) {
@ -359,6 +362,8 @@ public class MediaDatabase extends SQLiteOpenHelper {
") ON CONFLICT REPLACE)" ") ON CONFLICT REPLACE)"
); );
createSongArtistsTable(db);
// AudioGenres // AudioGenres
db.execSQL("CREATE TABLE " + Tables.AUDIO_GENRES + "(" + db.execSQL("CREATE TABLE " + Tables.AUDIO_GENRES + "(" +
BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
@ -378,7 +383,7 @@ public class MediaDatabase extends SQLiteOpenHelper {
BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
MediaContract.AlbumArtistsColumns.HOST_ID + " INTEGER NOT NULL " + References.HOST_ID + ", " + MediaContract.AlbumArtistsColumns.HOST_ID + " INTEGER NOT NULL " + References.HOST_ID + ", " +
MediaContract.AlbumArtistsColumns.ALBUMID + " INTEGER NOT NULL " + References.ALBUMID + ", " + MediaContract.AlbumArtistsColumns.ALBUMID + " INTEGER NOT NULL " + References.ALBUMID + ", " +
MediaContract.AlbumArtistsColumns.ARTISTID + " INTEGER NOT NULL " + References .ARTISTID + ", " + MediaContract.AlbumArtistsColumns.ARTISTID + " INTEGER NOT NULL " + References.ARTISTID + ", " +
"UNIQUE (" + "UNIQUE (" +
MediaContract.AlbumArtistsColumns.HOST_ID + ", " + MediaContract.AlbumArtistsColumns.HOST_ID + ", " +
MediaContract.AlbumArtistsColumns.ALBUMID + ", " + MediaContract.AlbumArtistsColumns.ALBUMID + ", " +
@ -471,6 +476,8 @@ public class MediaDatabase extends SQLiteOpenHelper {
db.execSQL("ALTER TABLE " + Tables.HOSTS + db.execSQL("ALTER TABLE " + Tables.HOSTS +
" ADD COLUMN " + MediaContract.HostsColumns.EVENT_SERVER_PORT + " ADD COLUMN " + MediaContract.HostsColumns.EVENT_SERVER_PORT +
" INTEGER DEFAULT " + HostInfo.DEFAULT_EVENT_SERVER_PORT + ";"); " INTEGER DEFAULT " + HostInfo.DEFAULT_EVENT_SERVER_PORT + ";");
case DB_VERSION_PRE_SONG_ARTISTS:
createSongArtistsTable(db);
} }
} }
@ -515,5 +522,19 @@ public class MediaDatabase extends SQLiteOpenHelper {
return order.toString(); return order.toString();
} }
private void createSongArtistsTable(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + Tables.SONG_ARTISTS + "(" +
BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
MediaContract.SongArtistsColumns.HOST_ID + " INTEGER NOT NULL " + References.HOST_ID + ", " +
MediaContract.SongArtistsColumns.SONGID + " INTEGER NOT NULL " + References.SONGID + ", " +
MediaContract.SongArtistsColumns.ARTISTID + " INTEGER NOT NULL " + References .ARTISTID + ", " +
"UNIQUE (" +
MediaContract.SongArtistsColumns.HOST_ID + ", " +
MediaContract.SongArtistsColumns.SONGID + ", " +
MediaContract.SongArtistsColumns.ARTISTID +
") ON CONFLICT REPLACE)"
);
}
} }

View File

@ -73,6 +73,7 @@ public class MediaProvider extends ContentProvider {
private static final int ARTISTS_LIST = 601; private static final int ARTISTS_LIST = 601;
private static final int ARTISTS_ID = 602; private static final int ARTISTS_ID = 602;
private static final int ARTIST_ALBUMS_LIST = 610; private static final int ARTIST_ALBUMS_LIST = 610;
private static final int ARTIST_SONGS_LIST = 611;
private static final int ALBUMS_ALL = 700; private static final int ALBUMS_ALL = 700;
private static final int ALBUMS_LIST = 701; private static final int ALBUMS_LIST = 701;
@ -81,7 +82,6 @@ public class MediaProvider extends ContentProvider {
private static final int ALBUM_GENRES_LIST = 711; private static final int ALBUM_GENRES_LIST = 711;
private static final int SONGS_ALL = 800; private static final int SONGS_ALL = 800;
private static final int SONGS_ARTIST = 801;
private static final int SONGS_ALBUM = 802; private static final int SONGS_ALBUM = 802;
private static final int SONGS_ID = 803; private static final int SONGS_ID = 803;
private static final int SONGS_LIST = 804; private static final int SONGS_LIST = 804;
@ -93,6 +93,7 @@ public class MediaProvider extends ContentProvider {
private static final int ALBUM_ARTISTS_ALL = 1000; private static final int ALBUM_ARTISTS_ALL = 1000;
private static final int ALBUM_GENRES_ALL = 1001; private static final int ALBUM_GENRES_ALL = 1001;
private static final int SONG_ARTISTS_ALL = 1002;
private static final int MUSIC_VIDEOS_ALL = 1100; private static final int MUSIC_VIDEOS_ALL = 1100;
private static final int MUSIC_VIDEOS_LIST = 1101; private static final int MUSIC_VIDEOS_LIST = 1101;
@ -169,6 +170,9 @@ public class MediaProvider extends ContentProvider {
matcher.addURI(authority, MediaContract.PATH_HOSTS + "/*/" + matcher.addURI(authority, MediaContract.PATH_HOSTS + "/*/" +
MediaContract.PATH_ARTISTS + "/*/" + MediaContract.PATH_ARTISTS + "/*/" +
MediaContract.PATH_ALBUMS, ARTIST_ALBUMS_LIST); MediaContract.PATH_ALBUMS, ARTIST_ALBUMS_LIST);
matcher.addURI(authority, MediaContract.PATH_HOSTS + "/*/" +
MediaContract.PATH_ARTISTS + "/*/" +
MediaContract.PATH_SONGS, ARTIST_SONGS_LIST);
// Albums // Albums
matcher.addURI(authority, MediaContract.PATH_ALBUMS, ALBUMS_ALL); matcher.addURI(authority, MediaContract.PATH_ALBUMS, ALBUMS_ALL);
@ -193,9 +197,6 @@ public class MediaProvider extends ContentProvider {
matcher.addURI(authority, MediaContract.PATH_HOSTS + "/*/" + matcher.addURI(authority, MediaContract.PATH_HOSTS + "/*/" +
MediaContract.PATH_ALBUMS + "/*/" + MediaContract.PATH_ALBUMS + "/*/" +
MediaContract.PATH_SONGS + "/*", SONGS_ID); MediaContract.PATH_SONGS + "/*", SONGS_ID);
matcher.addURI(authority, MediaContract.PATH_HOSTS + "/*/" +
MediaContract.PATH_ARTISTS + "/*/" +
MediaContract.PATH_SONGS, SONGS_ARTIST);
// Genres // Genres
matcher.addURI(authority, MediaContract.PATH_AUDIO_GENRES, AUDIO_GENRES_ALL); matcher.addURI(authority, MediaContract.PATH_AUDIO_GENRES, AUDIO_GENRES_ALL);
@ -211,6 +212,8 @@ public class MediaProvider extends ContentProvider {
matcher.addURI(authority, MediaContract.PATH_ALBUM_ARTISTS, ALBUM_ARTISTS_ALL); matcher.addURI(authority, MediaContract.PATH_ALBUM_ARTISTS, ALBUM_ARTISTS_ALL);
// AlbumGenres // AlbumGenres
matcher.addURI(authority, MediaContract.PATH_ALBUM_GENRES, ALBUM_GENRES_ALL); matcher.addURI(authority, MediaContract.PATH_ALBUM_GENRES, ALBUM_GENRES_ALL);
// SongArtists
matcher.addURI(authority, MediaContract.PATH_SONG_ARTISTS, SONG_ARTISTS_ALL);
// Music Videos // Music Videos
matcher.addURI(authority, MediaContract.PATH_MUSIC_VIDEOS, MUSIC_VIDEOS_ALL); matcher.addURI(authority, MediaContract.PATH_MUSIC_VIDEOS, MUSIC_VIDEOS_ALL);
@ -288,7 +291,7 @@ public class MediaProvider extends ContentProvider {
return MediaContract.Albums.CONTENT_ITEM_TYPE; return MediaContract.Albums.CONTENT_ITEM_TYPE;
case SONGS_ALL: case SONGS_ALL:
case SONGS_LIST: case SONGS_LIST:
case SONGS_ARTIST: case ARTIST_SONGS_LIST:
case SONGS_ALBUM: case SONGS_ALBUM:
return MediaContract.Songs.CONTENT_TYPE; return MediaContract.Songs.CONTENT_TYPE;
case SONGS_ID: case SONGS_ID:
@ -303,6 +306,8 @@ public class MediaProvider extends ContentProvider {
return MediaContract.AlbumArtists.CONTENT_TYPE; return MediaContract.AlbumArtists.CONTENT_TYPE;
case ALBUM_GENRES_ALL: case ALBUM_GENRES_ALL:
return MediaContract.AlbumGenres.CONTENT_TYPE; return MediaContract.AlbumGenres.CONTENT_TYPE;
case SONG_ARTISTS_ALL:
return MediaContract.SongArtists.CONTENT_TYPE;
case MUSIC_VIDEOS_ALL: case MUSIC_VIDEOS_ALL:
case MUSIC_VIDEOS_LIST: case MUSIC_VIDEOS_LIST:
return MediaContract.MusicVideos.CONTENT_TYPE; return MediaContract.MusicVideos.CONTENT_TYPE;
@ -326,7 +331,6 @@ public class MediaProvider extends ContentProvider {
default: { default: {
// Most cases are handled with simple SelectionBuilder // Most cases are handled with simple SelectionBuilder
final SelectionBuilder builder = buildQuerySelection(uri, match); final SelectionBuilder builder = buildQuerySelection(uri, match);
cursor = builder.where(selection, selectionArgs) cursor = builder.where(selection, selectionArgs)
.query(db, projection, sortOrder); .query(db, projection, sortOrder);
} }
@ -413,6 +417,10 @@ public class MediaProvider extends ContentProvider {
table = MediaDatabase.Tables.ALBUM_ARTISTS; table = MediaDatabase.Tables.ALBUM_ARTISTS;
break; break;
} }
case SONG_ARTISTS_ALL: {
table = MediaDatabase.Tables.SONG_ARTISTS;
break;
}
case MUSIC_VIDEOS_ALL: { case MUSIC_VIDEOS_ALL: {
table = MediaDatabase.Tables.MUSIC_VIDEOS; table = MediaDatabase.Tables.MUSIC_VIDEOS;
break; break;
@ -430,6 +438,7 @@ public class MediaProvider extends ContentProvider {
switch (match) { switch (match) {
case ALBUM_GENRES_ALL: case ALBUM_GENRES_ALL:
case ALBUM_ARTISTS_ALL: case ALBUM_ARTISTS_ALL:
case SONG_ARTISTS_ALL:
// Nothing to add to these tables // Nothing to add to these tables
break; break;
default: default:
@ -658,8 +667,15 @@ public class MediaProvider extends ContentProvider {
} }
case SONGS_LIST: { case SONGS_LIST: {
final String hostId = MediaContract.Hosts.getHostId(uri); final String hostId = MediaContract.Hosts.getHostId(uri);
return builder.table(MediaDatabase.Tables.SONGS_AND_ALBUM_JOIN) return builder.table(MediaDatabase.Tables.SONGS_FOR_ARTIST_AND_OR_ALBUM_JOIN)
.where(Qualified.SONGS_HOST_ID + "=?", hostId); .mapToTable(MediaContract.Songs.SONGID, MediaDatabase.Tables.SONGS)
.mapToTable(MediaContract.Songs.TITLE, MediaDatabase.Tables.SONGS)
.mapToTable(MediaContract.Songs.ALBUMID, MediaDatabase.Tables.SONGS)
.mapToTable(MediaContract.Songs.UPDATED, MediaDatabase.Tables.SONGS)
.mapToTable(MediaContract.Songs.THUMBNAIL, MediaDatabase.Tables.SONGS)
.mapToTable(MediaContract.SongArtists.ARTISTID, MediaDatabase.Tables.SONG_ARTISTS)
.where(Qualified.SONGS_HOST_ID + "=?", hostId)
.groupBy(Qualified.SONGS_SONGID);
} }
case SONGS_ALBUM: { case SONGS_ALBUM: {
final String hostId = MediaContract.Hosts.getHostId(uri); final String hostId = MediaContract.Hosts.getHostId(uri);
@ -668,14 +684,6 @@ public class MediaProvider extends ContentProvider {
.where(MediaContract.Songs.HOST_ID + "=?", hostId) .where(MediaContract.Songs.HOST_ID + "=?", hostId)
.where(MediaContract.Songs.ALBUMID + "=?", albumId); .where(MediaContract.Songs.ALBUMID + "=?", albumId);
} }
case SONGS_ARTIST: {
final String hostId = MediaContract.Hosts.getHostId(uri);
final String artistId = MediaContract.Artists.getArtistId(uri);
LogUtils.LOGD(TAG, "buildQuerySelection: SONGS_ARTIST: "+MediaDatabase.Tables.SONGS_FOR_ARTIST_JOIN);
return builder.table(MediaDatabase.Tables.SONGS_FOR_ARTIST_JOIN)
.where(Qualified.SONGS_HOST_ID + "=?", hostId)
.where(Qualified.ALBUM_ARTISTS_ARTISTID + "=?", artistId);
}
case SONGS_ID: { case SONGS_ID: {
final String hostId = MediaContract.Hosts.getHostId(uri); final String hostId = MediaContract.Hosts.getHostId(uri);
final String albumId = MediaContract.Albums.getAlbumId(uri); final String albumId = MediaContract.Albums.getAlbumId(uri);
@ -703,6 +711,9 @@ public class MediaProvider extends ContentProvider {
case ALBUM_ARTISTS_ALL: { case ALBUM_ARTISTS_ALL: {
return builder.table(MediaDatabase.Tables.ALBUM_ARTISTS); return builder.table(MediaDatabase.Tables.ALBUM_ARTISTS);
} }
case SONG_ARTISTS_ALL: {
return builder.table(MediaDatabase.Tables.SONG_ARTISTS);
}
case ALBUM_GENRES_ALL: { case ALBUM_GENRES_ALL: {
return builder.table(MediaDatabase.Tables.ALBUM_GENRES); return builder.table(MediaDatabase.Tables.ALBUM_GENRES);
} }
@ -718,6 +729,20 @@ public class MediaProvider extends ContentProvider {
.where(Qualified.ALBUM_ARTISTS_HOST_ID + "=?", hostId) .where(Qualified.ALBUM_ARTISTS_HOST_ID + "=?", hostId)
.where(Qualified.ALBUM_ARTISTS_ARTISTID + "=?", artistId); .where(Qualified.ALBUM_ARTISTS_ARTISTID + "=?", artistId);
} }
case ARTIST_SONGS_LIST: {
// Songs for Artists
final String hostId = MediaContract.Hosts.getHostId(uri);
final String artistId = MediaContract.Artists.getArtistId(uri);
return builder.table(MediaDatabase.Tables.SONGS_FOR_ARTIST_AND_OR_ALBUM_JOIN)
.mapToTable(MediaContract.Songs.SONGID, MediaDatabase.Tables.SONGS)
.mapToTable(MediaContract.Songs.TITLE, MediaDatabase.Tables.SONGS)
.mapToTable(MediaContract.Songs.ALBUMID, MediaDatabase.Tables.SONGS)
.mapToTable(MediaContract.Songs.UPDATED, MediaDatabase.Tables.SONGS)
.mapToTable(MediaContract.Songs.THUMBNAIL, MediaDatabase.Tables.SONGS)
.mapToTable(MediaContract.SongArtists.ARTISTID, MediaDatabase.Tables.SONG_ARTISTS)
.where(Qualified.SONG_ARTISTS_HOST_ID + "=?", hostId)
.where(Qualified.SONG_ARTISTS_ARTISTID + "=?", artistId);
}
case ALBUM_ARTISTS_LIST: { case ALBUM_ARTISTS_LIST: {
// Artists for Album // Artists for Album
final String hostId = MediaContract.Hosts.getHostId(uri); final String hostId = MediaContract.Hosts.getHostId(uri);
@ -795,5 +820,11 @@ public class MediaProvider extends ContentProvider {
MediaDatabase.Tables.ALBUM_GENRES + "." + MediaContract.AlbumGenres.ALBUMID; MediaDatabase.Tables.ALBUM_GENRES + "." + MediaContract.AlbumGenres.ALBUMID;
String SONGS_HOST_ID = String SONGS_HOST_ID =
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.HOST_ID; MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.HOST_ID;
String SONGS_SONGID =
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.SONGID;
String SONG_ARTISTS_HOST_ID =
MediaDatabase.Tables.SONG_ARTISTS + "." + MediaContract.SongArtists.HOST_ID;
String SONG_ARTISTS_ARTISTID =
MediaDatabase.Tables.SONG_ARTISTS + "." + MediaContract.SongArtists.ARTISTID;
} }
} }

View File

@ -317,7 +317,8 @@ public class SyncMusic extends SyncItem {
AudioType.FieldsSong.THUMBNAIL, AudioType.FieldsSong.FILE, AudioType.FieldsSong.THUMBNAIL, AudioType.FieldsSong.FILE,
AudioType.FieldsSong.ALBUMID, AudioType.FieldsSong.ALBUMID,
//AudioType.FieldsSong.LASTPLAYED, AudioType.FieldsSong.DISC, //AudioType.FieldsSong.LASTPLAYED, AudioType.FieldsSong.DISC,
//AudioType.FieldsSong.GENREID, AudioType.FieldsSong.ARTISTID, //AudioType.FieldsSong.GENREID,
AudioType.FieldsSong.ARTISTID,
//AudioType.FieldsSong.DISPLAYARTIST, AudioType.FieldsSong.ALBUMARTISTID //AudioType.FieldsSong.DISPLAYARTIST, AudioType.FieldsSong.ALBUMARTISTID
}; };
@ -345,14 +346,30 @@ public class SyncMusic extends SyncItem {
limitsReturned = result.limits; limitsReturned = result.limits;
} }
int totalArtistsCount = 0;
// Save partial results to DB // Save partial results to DB
ContentValues songValuesBatch[] = new ContentValues[items.size()]; ContentValues songValuesBatch[] = new ContentValues[items.size()];
for (int i = 0; i < items.size(); i++) { for (int i = 0; i < items.size(); i++) {
AudioType.DetailsSong song = items.get(i); AudioType.DetailsSong song = items.get(i);
songValuesBatch[i] = SyncUtils.contentValuesFromSong(hostId, song); songValuesBatch[i] = SyncUtils.contentValuesFromSong(hostId, song);
totalArtistsCount += song.artistid.size();
} }
contentResolver.bulkInsert(MediaContract.Songs.CONTENT_URI, songValuesBatch); contentResolver.bulkInsert(MediaContract.Songs.CONTENT_URI, songValuesBatch);
// Iterate on each song, collect the artists and insert them
ContentValues songArtistsValuesBatch[] = new ContentValues[totalArtistsCount];
int artistCount = 0;
for (AudioType.DetailsSong song : items) {
for (int artistId : song.artistid) {
songArtistsValuesBatch[artistCount] = new ContentValues();
songArtistsValuesBatch[artistCount].put(MediaContract.SongArtists.HOST_ID, hostId);
songArtistsValuesBatch[artistCount].put(MediaContract.SongArtists.SONGID, song.songid);
songArtistsValuesBatch[artistCount].put(MediaContract.SongArtists.ARTISTID, artistId);
artistCount++;
}
}
contentResolver.bulkInsert(MediaContract.SongArtists.CONTENT_URI, songArtistsValuesBatch);
if (moreItemsAvailable(limitsReturned)) { if (moreItemsAvailable(limitsReturned)) {
LogUtils.LOGD(TAG, "chainCallSyncSongs: More results on media center, recursing."); LogUtils.LOGD(TAG, "chainCallSyncSongs: More results on media center, recursing.");
result = null; // Help the GC? result = null; // Help the GC?

View File

@ -27,7 +27,6 @@ import org.xbmc.kore.jsonrpc.type.VideoType;
import org.xbmc.kore.jsonrpc.type.AudioType; import org.xbmc.kore.jsonrpc.type.AudioType;
import org.xbmc.kore.jsonrpc.type.LibraryType; import org.xbmc.kore.jsonrpc.type.LibraryType;
import org.xbmc.kore.provider.MediaContract; import org.xbmc.kore.provider.MediaContract;
import org.xbmc.kore.service.library.LibrarySyncService;
import org.xbmc.kore.utils.Utils; import org.xbmc.kore.utils.Utils;
import java.util.ArrayList; import java.util.ArrayList;
@ -42,7 +41,7 @@ public class SyncUtils {
void onServiceConnected(LibrarySyncService librarySyncService); void onServiceConnected(LibrarySyncService librarySyncService);
} }
public static final String LIST_DELIMETER = ", "; public static final String LIST_DELIMITER = ", ";
/** /**
* Returns {@link android.content.ContentValues} from a {@link org.xbmc.kore.jsonrpc.type.VideoType.DetailsMovie} movie * Returns {@link android.content.ContentValues} from a {@link org.xbmc.kore.jsonrpc.type.VideoType.DetailsMovie} movie
@ -61,7 +60,7 @@ public class SyncUtils {
movieValues.put(MediaContract.MoviesColumns.TITLE, movie.title); movieValues.put(MediaContract.MoviesColumns.TITLE, movie.title);
movieValues.put(MediaContract.MoviesColumns.FILE, movie.file); movieValues.put(MediaContract.MoviesColumns.FILE, movie.file);
movieValues.put(MediaContract.MoviesColumns.PLOT, movie.plot); movieValues.put(MediaContract.MoviesColumns.PLOT, movie.plot);
movieValues.put(MediaContract.MoviesColumns.DIRECTOR, Utils.listStringConcat(movie.director, LIST_DELIMETER)); movieValues.put(MediaContract.MoviesColumns.DIRECTOR, Utils.listStringConcat(movie.director, LIST_DELIMITER));
movieValues.put(MediaContract.MoviesColumns.RUNTIME, movie.runtime); movieValues.put(MediaContract.MoviesColumns.RUNTIME, movie.runtime);
if (movie.streamdetails != null) { if (movie.streamdetails != null) {
if (movie.streamdetails.audio.size() > 0) { if (movie.streamdetails.audio.size() > 0) {
@ -78,7 +77,7 @@ public class SyncUtils {
movieValues.put(MediaContract.MoviesColumns.AUDIO_CHANNELS, selectedStream.channels); movieValues.put(MediaContract.MoviesColumns.AUDIO_CHANNELS, selectedStream.channels);
movieValues.put(MediaContract.MoviesColumns.AUDIO_CODEC, selectedStream.codec); movieValues.put(MediaContract.MoviesColumns.AUDIO_CODEC, selectedStream.codec);
movieValues.put(MediaContract.MoviesColumns.AUDIO_LANGUAGE, movieValues.put(MediaContract.MoviesColumns.AUDIO_LANGUAGE,
Utils.listStringConcat(languages, LIST_DELIMETER)); Utils.listStringConcat(languages, LIST_DELIMITER));
} }
if (movie.streamdetails.subtitle.size() > 0) { if (movie.streamdetails.subtitle.size() > 0) {
// Concat all subtitle languages // Concat all subtitle languages
@ -87,7 +86,7 @@ public class SyncUtils {
subtitles.add(movie.streamdetails.subtitle.get(j).language); subtitles.add(movie.streamdetails.subtitle.get(j).language);
} }
movieValues.put(MediaContract.MoviesColumns.SUBTITLES_LANGUAGES, movieValues.put(MediaContract.MoviesColumns.SUBTITLES_LANGUAGES,
Utils.listStringConcat(subtitles, LIST_DELIMETER)); Utils.listStringConcat(subtitles, LIST_DELIMITER));
} }
if (movie.streamdetails.video.size() > 0) { if (movie.streamdetails.video.size() > 0) {
// We're only getting the first video channel... // We're only getting the first video channel...
@ -102,22 +101,22 @@ public class SyncUtils {
} }
} }
movieValues.put(MediaContract.MoviesColumns.COUNTRIES, movieValues.put(MediaContract.MoviesColumns.COUNTRIES,
Utils.listStringConcat(movie.country, LIST_DELIMETER)); Utils.listStringConcat(movie.country, LIST_DELIMITER));
movieValues.put(MediaContract.MoviesColumns.GENRES, movieValues.put(MediaContract.MoviesColumns.GENRES,
Utils.listStringConcat(movie.genre, LIST_DELIMETER)); Utils.listStringConcat(movie.genre, LIST_DELIMITER));
movieValues.put(MediaContract.MoviesColumns.IMDBNUMBER, movie.imdbnumber); movieValues.put(MediaContract.MoviesColumns.IMDBNUMBER, movie.imdbnumber);
movieValues.put(MediaContract.MoviesColumns.MPAA, movie.mpaa); movieValues.put(MediaContract.MoviesColumns.MPAA, movie.mpaa);
movieValues.put(MediaContract.MoviesColumns.RATING, movie.rating); movieValues.put(MediaContract.MoviesColumns.RATING, movie.rating);
movieValues.put(MediaContract.MoviesColumns.SET, movie.set); movieValues.put(MediaContract.MoviesColumns.SET, movie.set);
movieValues.put(MediaContract.MoviesColumns.SETID, movie.setid); movieValues.put(MediaContract.MoviesColumns.SETID, movie.setid);
movieValues.put(MediaContract.MoviesColumns.STUDIOS, movieValues.put(MediaContract.MoviesColumns.STUDIOS,
Utils.listStringConcat(movie.studio, LIST_DELIMETER)); Utils.listStringConcat(movie.studio, LIST_DELIMITER));
movieValues.put(MediaContract.MoviesColumns.TAGLINE, movie.tagline); movieValues.put(MediaContract.MoviesColumns.TAGLINE, movie.tagline);
movieValues.put(MediaContract.MoviesColumns.TOP250, movie.top250); movieValues.put(MediaContract.MoviesColumns.TOP250, movie.top250);
movieValues.put(MediaContract.MoviesColumns.TRAILER, movie.trailer); movieValues.put(MediaContract.MoviesColumns.TRAILER, movie.trailer);
movieValues.put(MediaContract.MoviesColumns.VOTES, movie.votes); movieValues.put(MediaContract.MoviesColumns.VOTES, movie.votes);
movieValues.put(MediaContract.MoviesColumns.WRITERS, movieValues.put(MediaContract.MoviesColumns.WRITERS,
Utils.listStringConcat(movie.writer, LIST_DELIMETER)); Utils.listStringConcat(movie.writer, LIST_DELIMITER));
movieValues.put(MediaContract.MoviesColumns.YEAR, movie.year); movieValues.put(MediaContract.MoviesColumns.YEAR, movie.year);
return movieValues; return movieValues;
@ -164,10 +163,10 @@ public class SyncUtils {
tvshowValues.put(MediaContract.TVShowsColumns.PREMIERED, tvshow.premiered); tvshowValues.put(MediaContract.TVShowsColumns.PREMIERED, tvshow.premiered);
tvshowValues.put(MediaContract.TVShowsColumns.RATING, tvshow.rating); tvshowValues.put(MediaContract.TVShowsColumns.RATING, tvshow.rating);
tvshowValues.put(MediaContract.TVShowsColumns.STUDIO, tvshowValues.put(MediaContract.TVShowsColumns.STUDIO,
Utils.listStringConcat(tvshow.studio, LIST_DELIMETER)); Utils.listStringConcat(tvshow.studio, LIST_DELIMITER));
tvshowValues.put(MediaContract.TVShowsColumns.WATCHEDEPISODES, tvshow.watchedepisodes); tvshowValues.put(MediaContract.TVShowsColumns.WATCHEDEPISODES, tvshow.watchedepisodes);
tvshowValues.put(MediaContract.TVShowsColumns.GENRES, tvshowValues.put(MediaContract.TVShowsColumns.GENRES,
Utils.listStringConcat(tvshow.genre, LIST_DELIMETER)); Utils.listStringConcat(tvshow.genre, LIST_DELIMITER));
return tvshowValues; return tvshowValues;
} }
@ -215,12 +214,12 @@ public class SyncUtils {
episodeValues.put(MediaContract.EpisodesColumns.TITLE, episode.title); episodeValues.put(MediaContract.EpisodesColumns.TITLE, episode.title);
episodeValues.put(MediaContract.EpisodesColumns.FILE, episode.file); episodeValues.put(MediaContract.EpisodesColumns.FILE, episode.file);
episodeValues.put(MediaContract.EpisodesColumns.PLOT, episode.plot); episodeValues.put(MediaContract.EpisodesColumns.PLOT, episode.plot);
episodeValues.put(MediaContract.EpisodesColumns.DIRECTOR, Utils.listStringConcat(episode.director, LIST_DELIMETER)); episodeValues.put(MediaContract.EpisodesColumns.DIRECTOR, Utils.listStringConcat(episode.director, LIST_DELIMITER));
episodeValues.put(MediaContract.EpisodesColumns.RUNTIME, episode.runtime); episodeValues.put(MediaContract.EpisodesColumns.RUNTIME, episode.runtime);
episodeValues.put(MediaContract.EpisodesColumns.FIRSTAIRED, episode.firstaired); episodeValues.put(MediaContract.EpisodesColumns.FIRSTAIRED, episode.firstaired);
episodeValues.put(MediaContract.EpisodesColumns.RATING, episode.rating); episodeValues.put(MediaContract.EpisodesColumns.RATING, episode.rating);
episodeValues.put(MediaContract.EpisodesColumns.SHOWTITLE, episode.showtitle); episodeValues.put(MediaContract.EpisodesColumns.SHOWTITLE, episode.showtitle);
episodeValues.put(MediaContract.EpisodesColumns.WRITER, Utils.listStringConcat(episode.writer, LIST_DELIMETER)); episodeValues.put(MediaContract.EpisodesColumns.WRITER, Utils.listStringConcat(episode.writer, LIST_DELIMITER));
if (episode.streamdetails.audio.size() > 0) { if (episode.streamdetails.audio.size() > 0) {
// Get the stream with the most channels and concat all the languages // Get the stream with the most channels and concat all the languages
@ -235,7 +234,7 @@ public class SyncUtils {
} }
episodeValues.put(MediaContract.EpisodesColumns.AUDIO_CHANNELS, selectedStream.channels); episodeValues.put(MediaContract.EpisodesColumns.AUDIO_CHANNELS, selectedStream.channels);
episodeValues.put(MediaContract.EpisodesColumns.AUDIO_CODEC, selectedStream.codec); episodeValues.put(MediaContract.EpisodesColumns.AUDIO_CODEC, selectedStream.codec);
episodeValues.put(MediaContract.EpisodesColumns.AUDIO_LANGUAGE, Utils.listStringConcat(languages, LIST_DELIMETER)); episodeValues.put(MediaContract.EpisodesColumns.AUDIO_LANGUAGE, Utils.listStringConcat(languages, LIST_DELIMITER));
} }
if (episode.streamdetails.subtitle.size() > 0) { if (episode.streamdetails.subtitle.size() > 0) {
// Concat all subtitle languages // Concat all subtitle languages
@ -243,7 +242,7 @@ public class SyncUtils {
for (int j = 0; j < episode.streamdetails.subtitle.size(); j++) { for (int j = 0; j < episode.streamdetails.subtitle.size(); j++) {
subtitles.add(episode.streamdetails.subtitle.get(j).language); subtitles.add(episode.streamdetails.subtitle.get(j).language);
} }
episodeValues.put(MediaContract.EpisodesColumns.SUBTITLES_LANGUAGES, Utils.listStringConcat(subtitles, LIST_DELIMETER)); episodeValues.put(MediaContract.EpisodesColumns.SUBTITLES_LANGUAGES, Utils.listStringConcat(subtitles, LIST_DELIMITER));
} }
if (episode.streamdetails.video.size() > 0) { if (episode.streamdetails.video.size() > 0) {
// We're only getting the first video channel... // We're only getting the first video channel...
@ -273,7 +272,7 @@ public class SyncUtils {
castValues.put(MediaContract.ArtistsColumns.ARTIST, artist.artist); castValues.put(MediaContract.ArtistsColumns.ARTIST, artist.artist);
castValues.put(MediaContract.ArtistsColumns.DESCRIPTION, artist.description); castValues.put(MediaContract.ArtistsColumns.DESCRIPTION, artist.description);
castValues.put(MediaContract.ArtistsColumns.GENRE, castValues.put(MediaContract.ArtistsColumns.GENRE,
Utils.listStringConcat(artist.genre, LIST_DELIMETER)); Utils.listStringConcat(artist.genre, LIST_DELIMITER));
castValues.put(MediaContract.ArtistsColumns.FANART, artist.fanart); castValues.put(MediaContract.ArtistsColumns.FANART, artist.fanart);
castValues.put(MediaContract.ArtistsColumns.THUMBNAIL, artist.thumbnail); castValues.put(MediaContract.ArtistsColumns.THUMBNAIL, artist.thumbnail);
@ -315,7 +314,7 @@ public class SyncUtils {
castValues.put(MediaContract.Albums.ALBUMLABEL, album.albumlabel); castValues.put(MediaContract.Albums.ALBUMLABEL, album.albumlabel);
castValues.put(MediaContract.Albums.DESCRIPTION, album.description); castValues.put(MediaContract.Albums.DESCRIPTION, album.description);
castValues.put(MediaContract.Albums.PLAYCOUNT, album.playcount); castValues.put(MediaContract.Albums.PLAYCOUNT, album.playcount);
castValues.put(MediaContract.Albums.GENRE, Utils.listStringConcat(album.genre, LIST_DELIMETER)); castValues.put(MediaContract.Albums.GENRE, Utils.listStringConcat(album.genre, LIST_DELIMITER));
return castValues; return castValues;
} }
@ -357,7 +356,7 @@ public class SyncUtils {
musicVideoValues.put(MediaContract.MusicVideosColumns.TITLE, musicVideo.title); musicVideoValues.put(MediaContract.MusicVideosColumns.TITLE, musicVideo.title);
musicVideoValues.put(MediaContract.MusicVideosColumns.FILE, musicVideo.file); musicVideoValues.put(MediaContract.MusicVideosColumns.FILE, musicVideo.file);
musicVideoValues.put(MediaContract.MusicVideosColumns.PLOT, musicVideo.plot); musicVideoValues.put(MediaContract.MusicVideosColumns.PLOT, musicVideo.plot);
musicVideoValues.put(MediaContract.MusicVideosColumns.DIRECTOR, Utils.listStringConcat(musicVideo.director, LIST_DELIMETER)); musicVideoValues.put(MediaContract.MusicVideosColumns.DIRECTOR, Utils.listStringConcat(musicVideo.director, LIST_DELIMITER));
musicVideoValues.put(MediaContract.MusicVideosColumns.RUNTIME, musicVideo.runtime); musicVideoValues.put(MediaContract.MusicVideosColumns.RUNTIME, musicVideo.runtime);
if (musicVideo.streamdetails != null) { if (musicVideo.streamdetails != null) {
if (musicVideo.streamdetails.audio.size() > 0) { if (musicVideo.streamdetails.audio.size() > 0) {
@ -374,7 +373,7 @@ public class SyncUtils {
musicVideoValues.put(MediaContract.MusicVideosColumns.AUDIO_CHANNELS, selectedStream.channels); musicVideoValues.put(MediaContract.MusicVideosColumns.AUDIO_CHANNELS, selectedStream.channels);
musicVideoValues.put(MediaContract.MusicVideosColumns.AUDIO_CODEC, selectedStream.codec); musicVideoValues.put(MediaContract.MusicVideosColumns.AUDIO_CODEC, selectedStream.codec);
musicVideoValues.put(MediaContract.MusicVideosColumns.AUDIO_LANGUAGE, musicVideoValues.put(MediaContract.MusicVideosColumns.AUDIO_LANGUAGE,
Utils.listStringConcat(languages, LIST_DELIMETER)); Utils.listStringConcat(languages, LIST_DELIMITER));
} }
if (musicVideo.streamdetails.subtitle.size() > 0) { if (musicVideo.streamdetails.subtitle.size() > 0) {
// Concat all subtitle languages // Concat all subtitle languages
@ -383,7 +382,7 @@ public class SyncUtils {
subtitles.add(musicVideo.streamdetails.subtitle.get(j).language); subtitles.add(musicVideo.streamdetails.subtitle.get(j).language);
} }
musicVideoValues.put(MediaContract.MusicVideosColumns.SUBTITLES_LANGUAGES, musicVideoValues.put(MediaContract.MusicVideosColumns.SUBTITLES_LANGUAGES,
Utils.listStringConcat(subtitles, LIST_DELIMETER)); Utils.listStringConcat(subtitles, LIST_DELIMITER));
} }
if (musicVideo.streamdetails.video.size() > 0) { if (musicVideo.streamdetails.video.size() > 0) {
// We're only getting the first video channel... // We're only getting the first video channel...
@ -399,13 +398,13 @@ public class SyncUtils {
} }
musicVideoValues.put(MediaContract.MusicVideosColumns.ALBUM, musicVideo.album); musicVideoValues.put(MediaContract.MusicVideosColumns.ALBUM, musicVideo.album);
musicVideoValues.put(MediaContract.MusicVideosColumns.ARTIST, musicVideoValues.put(MediaContract.MusicVideosColumns.ARTIST,
Utils.listStringConcat(musicVideo.artist, LIST_DELIMETER)); Utils.listStringConcat(musicVideo.artist, LIST_DELIMITER));
musicVideoValues.put(MediaContract.MusicVideosColumns.GENRES, musicVideoValues.put(MediaContract.MusicVideosColumns.GENRES,
Utils.listStringConcat(musicVideo.genre, LIST_DELIMETER)); Utils.listStringConcat(musicVideo.genre, LIST_DELIMITER));
musicVideoValues.put(MediaContract.MusicVideosColumns.STUDIOS, musicVideoValues.put(MediaContract.MusicVideosColumns.STUDIOS,
Utils.listStringConcat(musicVideo.studio, LIST_DELIMETER)); Utils.listStringConcat(musicVideo.studio, LIST_DELIMITER));
musicVideoValues.put(MediaContract.MusicVideosColumns.TAG, musicVideoValues.put(MediaContract.MusicVideosColumns.TAG,
Utils.listStringConcat(musicVideo.tag, LIST_DELIMETER)); Utils.listStringConcat(musicVideo.tag, LIST_DELIMITER));
musicVideoValues.put(MediaContract.MusicVideosColumns.TRACK, musicVideo.track); musicVideoValues.put(MediaContract.MusicVideosColumns.TRACK, musicVideo.track);
musicVideoValues.put(MediaContract.MusicVideosColumns.YEAR, musicVideo.year); musicVideoValues.put(MediaContract.MusicVideosColumns.YEAR, musicVideo.year);

View File

@ -229,7 +229,7 @@ public class ArtistOverviewFragment extends AbstractDetailsFragment
case LOADER_SONGS: case LOADER_SONGS:
uri = MediaContract.Songs.buildArtistSongsListUri(hostInfo.getId(), artistId); uri = MediaContract.Songs.buildArtistSongsListUri(hostInfo.getId(), artistId);
return new CursorLoader(getActivity(), uri, return new CursorLoader(getActivity(), uri,
AlbumSongsListQuery.PROJECTION, null, null, AlbumSongsListQuery.SORT); SongsListQuery.PROJECTION, null, null, SongsListQuery.SORT);
default: default:
return null; return null;
} }
@ -299,16 +299,16 @@ public class ArtistOverviewFragment extends AbstractDetailsFragment
private FileDownloadHelper.SongInfo createSongInfo(Cursor cursor) { private FileDownloadHelper.SongInfo createSongInfo(Cursor cursor) {
FileDownloadHelper.SongInfo songInfo = null; FileDownloadHelper.SongInfo songInfo = null;
String albumTitle = albumTitles.get(cursor.getInt(AlbumSongsListQuery.ALBUMID)); String albumTitle = albumTitles.get(cursor.getInt(SongsListQuery.ALBUMID));
if (albumTitle != null) { if (albumTitle != null) {
// Add this song to the list // Add this song to the list
songInfo = new FileDownloadHelper.SongInfo( songInfo = new FileDownloadHelper.SongInfo(
artistTitle, artistTitle,
albumTitle, albumTitle,
cursor.getInt(AlbumSongsListQuery.SONGID), cursor.getInt(SongsListQuery.SONGID),
cursor.getInt(AlbumSongsListQuery.TRACK), cursor.getInt(SongsListQuery.TRACK),
cursor.getString(AlbumSongsListQuery.TITLE), cursor.getString(SongsListQuery.TITLE),
cursor.getString(AlbumSongsListQuery.FILE)); cursor.getString(SongsListQuery.FILE));
} }
return songInfo; return songInfo;
} }
@ -457,7 +457,7 @@ public class ArtistOverviewFragment extends AbstractDetailsFragment
/** /**
* Song list query parameters. * Song list query parameters.
*/ */
private interface AlbumSongsListQuery { private interface SongsListQuery {
String[] PROJECTION = { String[] PROJECTION = {
MediaDatabase.Tables.SONGS + "." + BaseColumns._ID, MediaDatabase.Tables.SONGS + "." + BaseColumns._ID,
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.TITLE, MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.TITLE,

View File

@ -49,6 +49,8 @@ import org.xbmc.kore.utils.LogUtils;
import org.xbmc.kore.utils.MediaPlayerUtils; import org.xbmc.kore.utils.MediaPlayerUtils;
import org.xbmc.kore.utils.UIUtils; import org.xbmc.kore.utils.UIUtils;
import java.util.ArrayList;
/** /**
* Fragment that presents the songs list * Fragment that presents the songs list
*/ */
@ -94,7 +96,7 @@ public class SongsListFragment extends AbstractCursorListFragment {
} }
return new CursorLoader(getActivity(), uri, return new CursorLoader(getActivity(), uri,
SongsAlbumsListQuery.PROJECTION, selection, selectionArgs, SongsAlbumsListQuery.SORT); SongsListQuery.PROJECTION, selection, selectionArgs, SongsListQuery.SORT);
} }
@Override @Override
@ -129,35 +131,10 @@ public class SongsListFragment extends AbstractCursorListFragment {
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);
} }
/**
* Song list query parameters.
*/
private interface SongsListQuery {
String[] PROJECTION = {
MediaDatabase.Tables.SONGS + "." + BaseColumns._ID,
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.TITLE,
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.TRACK,
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.DURATION,
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.FILE,
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.SONGID,
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.ALBUMID,
};
String SORT = MediaContract.Songs.TRACK + " ASC";
int ID = 0;
int TITLE = 1;
int TRACK = 2;
int DURATION = 3;
int FILE = 4;
int SONGID = 5;
int ALBUMID = 6;
}
/** /**
* Album songs list query parameters. * Album songs list query parameters.
*/ */
private interface SongsAlbumsListQuery { private interface SongsListQuery {
String[] PROJECTION = { String[] PROJECTION = {
MediaDatabase.Tables.SONGS + "." + BaseColumns._ID, MediaDatabase.Tables.SONGS + "." + BaseColumns._ID,
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.TITLE, MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.TITLE,
@ -170,6 +147,7 @@ public class SongsListFragment extends AbstractCursorListFragment {
MediaDatabase.Tables.ALBUMS + "." + MediaContract.Albums.GENRE, MediaDatabase.Tables.ALBUMS + "." + MediaContract.Albums.GENRE,
MediaDatabase.Tables.ALBUMS + "." + MediaContract.Albums.YEAR, MediaDatabase.Tables.ALBUMS + "." + MediaContract.Albums.YEAR,
MediaDatabase.Tables.ALBUMS + "." + MediaContract.Albums.THUMBNAIL, MediaDatabase.Tables.ALBUMS + "." + MediaContract.Albums.THUMBNAIL,
MediaDatabase.Tables.ARTISTS + "." + MediaContract.Artists.ARTIST
}; };
String SORT = MediaDatabase.sortCommonTokens(MediaDatabase.Tables.SONGS String SORT = MediaDatabase.sortCommonTokens(MediaDatabase.Tables.SONGS
@ -187,6 +165,7 @@ public class SongsListFragment extends AbstractCursorListFragment {
int GENRE = 8; int GENRE = 8;
int YEAR = 9; int YEAR = 9;
int THUMBNAIL = 10; int THUMBNAIL = 10;
int ARTIST = 11;
} }
private class SongsAdapter extends CursorAdapter { private class SongsAdapter extends CursorAdapter {
@ -229,25 +208,30 @@ public class SongsListFragment extends AbstractCursorListFragment {
public void bindView(View view, Context context, Cursor cursor) { public void bindView(View view, Context context, Cursor cursor) {
final ViewHolder viewHolder = (ViewHolder)view.getTag(); final ViewHolder viewHolder = (ViewHolder)view.getTag();
String title = cursor.getString(SongsAlbumsListQuery.TITLE); String title = cursor.getString(SongsListQuery.TITLE);
viewHolder.songId = cursor.getInt(SongsAlbumsListQuery.SONGID); viewHolder.songId = cursor.getInt(SongsListQuery.SONGID);
viewHolder.title.setText(title); viewHolder.title.setText(title);
viewHolder.artist.setText(String.valueOf(cursor.getString(SongsAlbumsListQuery.ALBUMARTIST)));
int year = cursor.getInt(SongsAlbumsListQuery.YEAR); String artist = cursor.getString(SongsListQuery.ALBUMARTIST);
if (TextUtils.isEmpty(artist))
artist = cursor.getString(SongsListQuery.ARTIST);
viewHolder.artist.setText(artist);
int year = cursor.getInt(SongsListQuery.YEAR);
if (year > 0) { if (year > 0) {
setDetails(viewHolder.details, setDetails(viewHolder.details,
cursor.getString(SongsAlbumsListQuery.ALBUMTITLE), cursor.getString(SongsListQuery.ALBUMTITLE),
String.valueOf(year), String.valueOf(year),
cursor.getString(SongsAlbumsListQuery.GENRE)); cursor.getString(SongsListQuery.GENRE));
} else { } else {
setDetails(viewHolder.details, setDetails(viewHolder.details,
cursor.getString(SongsAlbumsListQuery.ALBUMTITLE), cursor.getString(SongsListQuery.ALBUMTITLE),
cursor.getString(SongsAlbumsListQuery.GENRE)); cursor.getString(SongsListQuery.GENRE));
} }
String thumbnail = cursor.getString(SongsAlbumsListQuery.THUMBNAIL); String thumbnail = cursor.getString(SongsListQuery.THUMBNAIL);
UIUtils.loadImageWithCharacterAvatar(context, hostManager, UIUtils.loadImageWithCharacterAvatar(context, hostManager,
thumbnail, title, thumbnail, title,
viewHolder.art, artWidth, artHeight); viewHolder.art, artWidth, artHeight);
@ -306,21 +290,12 @@ public class SongsListFragment extends AbstractCursorListFragment {
return; return;
} }
StringBuilder stringBuilder = new StringBuilder(); ArrayList<String> details = new ArrayList<>();
for (int i = 0; i < elements.length; i++) {
int i = 0; if (!TextUtils.isEmpty(elements[i]))
int size = elements.length - 1; details.add(elements[i]);
for (; i < size; i++) {
if (!TextUtils.isEmpty(elements[i])) {
stringBuilder.append(elements[i]);
stringBuilder.append(" | ");
}
} }
if (elements.length > 0) { textView.setText(TextUtils.join(" | ", details.toArray()));
stringBuilder.append(elements[i]);
}
textView.setText(stringBuilder.toString());
} }
} }

View File

@ -45,7 +45,7 @@ public class SelectionBuilder {
private Map<String, String> mProjectionMap = new HashMap<String, String>(); private Map<String, String> mProjectionMap = new HashMap<String, String>();
private StringBuilder mSelection = new StringBuilder(); private StringBuilder mSelection = new StringBuilder();
private ArrayList<String> mSelectionArgs = new ArrayList<String>(); private ArrayList<String> mSelectionArgs = new ArrayList<String>();
private StringBuilder mGroupBy = new StringBuilder();
/** /**
* Reset any internal state, allowing this builder to be recycled. * Reset any internal state, allowing this builder to be recycled.
*/ */
@ -56,6 +56,20 @@ public class SelectionBuilder {
return this; return this;
} }
public SelectionBuilder groupBy(String... groupByArgs) {
if (groupByArgs != null) {
if (mGroupBy.length() > 0)
mGroupBy.append(", ");
int size = groupByArgs.length - 1;
for (int i = 0; i < size; i++) {
mGroupBy.append(groupByArgs[i] + ", ");
}
mGroupBy.append(groupByArgs[size]);
}
return this;
}
/** /**
* Append the given selection clause to the internal state. Each clause is * Append the given selection clause to the internal state. Each clause is
* surrounded with parenthesis and combined using {@code AND}. * surrounded with parenthesis and combined using {@code AND}.
@ -141,7 +155,7 @@ public class SelectionBuilder {
* Execute query using the current internal state as {@code WHERE} clause. * Execute query using the current internal state as {@code WHERE} clause.
*/ */
public Cursor query(SQLiteDatabase db, String[] columns, String orderBy) { public Cursor query(SQLiteDatabase db, String[] columns, String orderBy) {
return query(db, columns, null, null, orderBy, null); return query(db, columns, mGroupBy.toString(), null, orderBy, null);
} }
/** /**