Skip to content

Commit

Permalink
Change the source of AlbumGenres table to support Kodi v18
Browse files Browse the repository at this point in the history
As detailed in xbmc/xbmc#13051, Kodi v18 changes the way album genres are handled, as the genre (by which i mean `genreId`) ceases to be available at the album level, being only available at the songs level.
This impacts Kore because `GetAlbums` and `GetAlbumDetails` won't return the `genreId` tag, from which the local AlbumGenres table was populated.

This PR changes the source of the local AlbumGenres table to be the `genreId` returned at the song level (by `GetSongs`), to make it somewhat more consistent with the way Kodi will handle things from now on.
  • Loading branch information
SyncedSynapse authored and poisdeux committed Feb 22, 2018
1 parent 1b329e2 commit 246693a
Show file tree
Hide file tree
Showing 10 changed files with 12,680 additions and 58 deletions.
20 changes: 18 additions & 2 deletions app/src/main/java/org/xbmc/kore/host/HostInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package org.xbmc.kore.host;

import org.xbmc.kore.jsonrpc.HostConnection;
import org.xbmc.kore.jsonrpc.method.System;
import org.xbmc.kore.utils.LogUtils;

import java.io.UnsupportedEncodingException;
Expand Down Expand Up @@ -55,11 +54,20 @@ public class HostInfo {
*/
public static final int DEFAULT_EVENT_SERVER_PORT = 9777;

public static final int DEFAULT_KODI_VERSION_MAJOR = 16;
public static final int KODI_V12_FRODO = 12;
public static final int KODI_V13_GOTHAM = 13;
public static final int KODI_V14_HELIX = 14;
public static final int KODI_V15_ISENGARD = 15;
public static final int KODI_V16_JARVIS = 16;
public static final int KODI_V17_KRYPTON = 17;
public static final int KODI_V18_LEIA = 18;

public static final int DEFAULT_KODI_VERSION_MAJOR = KODI_V16_JARVIS;
public static final int DEFAULT_KODI_VERSION_MINOR = 1;
public static final String DEFAULT_KODI_VERSION_REVISION = "Unknown";
public static final String DEFAULT_KODI_VERSION_TAG = "stable";


/**
* Internal id of the host
*/
Expand Down Expand Up @@ -291,6 +299,14 @@ public void setKodiVersionTag(String kodiVersionTag) {
this.kodiVersionTag = kodiVersionTag;
}

public boolean isGothamOrLater() {
return kodiVersionMajor > KODI_V13_GOTHAM;
}

public boolean isKryptonOrLater() {
return kodiVersionMajor > KODI_V17_KRYPTON;
}

/**
* Returns the URL of the host
* @return HTTP URL eg. http://192.168.1.1:8080
Expand Down
10 changes: 9 additions & 1 deletion app/src/main/java/org/xbmc/kore/jsonrpc/HostConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
package org.xbmc.kore.jsonrpc;

import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Process;
import android.text.TextUtils;
Expand Down Expand Up @@ -213,6 +212,14 @@ public static boolean isValidProtocol(int protocol) {
return ((protocol == PROTOCOL_TCP) || (protocol == PROTOCOL_HTTP));
}

/**
* Returns this connection {@link HostInfo}
* @return This connection {@link HostInfo}
*/
public HostInfo getHostInfo() {
return hostInfo;
}

/**
* Registers an observer for player notifications
* @param observer The {@link PlayerNotificationsObserver}
Expand Down Expand Up @@ -421,6 +428,7 @@ private <T> void executeThroughOkHttp(final ApiMethod<T> method, final ApiCallba
final Handler handler) {
OkHttpClient client = getOkHttpClient();
String jsonRequest = method.toJsonString();
LogUtils.LOGD(TAG, "Sending request via HTTP: " + jsonRequest);

try {
Request request = new Request.Builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ public void onSyncFinished(SyncOrchestrator syncOrchestrator) {
// Sync all music
boolean syncAllMusic = intent.getBooleanExtra(SYNC_ALL_MUSIC, false);
if (syncAllMusic) {
syncOrchestrator.addSyncItem(new SyncMusic(hostInfo.getId(), syncExtras));
syncOrchestrator.addSyncItem(new SyncMusic(syncExtras));
}

// Sync all music videos
Expand Down
73 changes: 39 additions & 34 deletions app/src/main/java/org/xbmc/kore/service/library/SyncMusic.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,18 @@ public class SyncMusic extends SyncItem {
private static final int LIMIT_SYNC_ALBUMS = 300;
private static final int LIMIT_SYNC_SONGS = 600;

private final int hostId;
private final Bundle syncExtras;

/**
* Syncs all the music on selected XBMC to the local database
* @param hostId XBMC host id
* Syncs all the music to the local database
*/
public SyncMusic(final int hostId, Bundle syncExtras) {
this.hostId = hostId;
public SyncMusic(Bundle syncExtras) {
this.syncExtras = syncExtras;
}

/** {@inheritDoc} */
public String getDescription() {
return "Sync music for host: " + hostId;
return "Sync music";
}

/** {@inheritDoc} */
Expand Down Expand Up @@ -91,11 +88,13 @@ public void sync(final SyncOrchestrator orchestrator,
* Gets all artists recursively and forwards the call to Genres
* Genres->Albums->Songs
*/
public void chainCallSyncArtists(final SyncOrchestrator orchestrator,
private void chainCallSyncArtists(final SyncOrchestrator orchestrator,
final HostConnection hostConnection,
final Handler callbackHandler,
final ContentResolver contentResolver,
final int startIdx) {
final int hostId = hostConnection.getHostInfo().getId();

// Artists->Genres->Albums->Songs
// Only gets album artists (first parameter)
ListType.Limits limits = new ListType.Limits(startIdx, startIdx + LIMIT_SYNC_ARTISTS);
Expand All @@ -116,7 +115,7 @@ public void onSuccess(ApiList<AudioType.DetailsArtist> result) {
// First delete all music info
if (startIdx == 0) deleteMusicInfo(contentResolver, hostId);

insertArtists(items, contentResolver);
insertArtists(hostId, items, contentResolver);

if (SyncUtils.moreItemsAvailable(limitsReturned)) {
LogUtils.LOGD(TAG, "chainCallSyncArtists: More results on media center, recursing.");
Expand Down Expand Up @@ -170,13 +169,15 @@ private void chainCallSyncGenres(final SyncOrchestrator orchestrator,
final HostConnection hostConnection,
final Handler callbackHandler,
final ContentResolver contentResolver) {
final int hostId = hostConnection.getHostInfo().getId();

// Genres->Albums->Songs
AudioLibrary.GetGenres action = new AudioLibrary.GetGenres(getGenresProperties);
action.execute(hostConnection, new ApiCallback<List<LibraryType.DetailsGenre>>() {
@Override
public void onSuccess(List<LibraryType.DetailsGenre> result) {
if (result != null)
insertGenresItems(result, contentResolver);
insertGenresItems(hostId, result, contentResolver);

chainCallSyncAlbums(orchestrator, hostConnection, callbackHandler, contentResolver, 0);
}
Expand All @@ -199,7 +200,7 @@ public void onError(int errorCode, String description) {
//AudioType.FieldsAlbum.MUSICBRAINZALBUMID,
//AudioType.FieldsAlbum.MUSICBRAINZALBUMARTISTID,
AudioType.FieldsAlbum.FANART, AudioType.FieldsAlbum.THUMBNAIL,
AudioType.FieldsAlbum.PLAYCOUNT, AudioType.FieldsAlbum.GENREID,
AudioType.FieldsAlbum.PLAYCOUNT, // AudioType.FieldsAlbum.GENREID,
AudioType.FieldsAlbum.ARTISTID, AudioType.FieldsAlbum.DISPLAYARTIST
};

Expand All @@ -212,10 +213,13 @@ private void chainCallSyncAlbums(final SyncOrchestrator orchestrator,
final Handler callbackHandler,
final ContentResolver contentResolver,
final int startIdx) {
final int hostId = hostConnection.getHostInfo().getId();
final long albumSyncStartTime = System.currentTimeMillis();
// Albums->Songs
ListType.Limits limits = new ListType.Limits(startIdx, startIdx + LIMIT_SYNC_ALBUMS);

AudioLibrary.GetAlbums action = new AudioLibrary.GetAlbums(limits, getAlbumsProperties);

action.execute(hostConnection, new ApiCallback<ApiList<AudioType.DetailsAlbum>>() {
@Override
public void onSuccess(ApiList<AudioType.DetailsAlbum> result) {
Expand All @@ -230,7 +234,7 @@ public void onSuccess(ApiList<AudioType.DetailsAlbum> result) {
}

// Insert the partial results
insertAlbumsItems(items, contentResolver);
insertAlbumsItems(hostId, items, contentResolver);

LogUtils.LOGD(TAG, "Finished inserting artists and genres in: " +
(System.currentTimeMillis() - albumSyncStartTime));
Expand Down Expand Up @@ -271,7 +275,7 @@ public void onError(int errorCode, String description) {
AudioType.FieldsSong.ALBUMID,
//AudioType.FieldsSong.LASTPLAYED,
AudioType.FieldsSong.DISC,
//AudioType.FieldsSong.GENREID,
AudioType.FieldsSong.GENREID,
AudioType.FieldsSong.ARTISTID,
// AudioType.FieldsSong.ALBUMARTISTID,
AudioType.FieldsSong.DISPLAYARTIST,
Expand All @@ -285,6 +289,7 @@ private void chainCallSyncSongs(final SyncOrchestrator orchestrator,
final Handler callbackHandler,
final ContentResolver contentResolver,
final int startIdx) {
final int hostId = hostConnection.getHostInfo().getId();
// Songs
ListType.Limits limits = new ListType.Limits(startIdx, startIdx + LIMIT_SYNC_SONGS);
AudioLibrary.GetSongs action = new AudioLibrary.GetSongs(limits, getSongsProperties);
Expand All @@ -302,7 +307,7 @@ public void onSuccess(ApiList<AudioType.DetailsSong> result) {
}

// Save partial results to DB
insertSongsItems(items, contentResolver);
insertSongsItems(hostId, items, contentResolver);

if (SyncUtils.moreItemsAvailable(limitsReturned)) {
LogUtils.LOGD(TAG, "chainCallSyncSongs: More results on media center, recursing.");
Expand All @@ -324,7 +329,7 @@ public void onError(int errorCode, String description) {
}, callbackHandler);
}

public void insertArtists(List<AudioType.DetailsArtist> items, ContentResolver contentResolver) {
public void insertArtists(int hostId, List<AudioType.DetailsArtist> items, ContentResolver contentResolver) {
ContentValues artistValuesBatch[] = new ContentValues[items.size()];
for (int i = 0; i < items.size(); i++) {
AudioType.DetailsArtist artist = items.get(i);
Expand All @@ -333,7 +338,7 @@ public void insertArtists(List<AudioType.DetailsArtist> items, ContentResolver c
contentResolver.bulkInsert(MediaContract.Artists.CONTENT_URI, artistValuesBatch);
}

public void insertGenresItems(List<LibraryType.DetailsGenre> items, ContentResolver contentResolver) {
public void insertGenresItems(int hostId, List<LibraryType.DetailsGenre> items, ContentResolver contentResolver) {
ContentValues genresValuesBatch[] = new ContentValues[items.size()];

for (int i = 0; i < items.size(); i++) {
Expand All @@ -345,22 +350,20 @@ public void insertGenresItems(List<LibraryType.DetailsGenre> items, ContentResol
contentResolver.bulkInsert(MediaContract.AudioGenres.CONTENT_URI, genresValuesBatch);
}

public void insertAlbumsItems(List<AudioType.DetailsAlbum> items, ContentResolver contentResolver) {
public void insertAlbumsItems(int hostId, List<AudioType.DetailsAlbum> items, ContentResolver contentResolver) {
ContentValues albumValuesBatch[] = new ContentValues[items.size()];
int artistsCount = 0, genresCount = 0;
int artistsCount = 0;
for (int i = 0; i < items.size(); i++) {
AudioType.DetailsAlbum album = items.get(i);
albumValuesBatch[i] = SyncUtils.contentValuesFromAlbum(hostId, album);

artistsCount += album.artistid.size();
genresCount += album.genreid.size();
}
contentResolver.bulkInsert(MediaContract.Albums.CONTENT_URI, albumValuesBatch);

// Iterate on each album, collect the artists and the genres and insert them
// Iterate on each album, collect the artists and insert them
ContentValues albumArtistsValuesBatch[] = new ContentValues[artistsCount];
ContentValues albumGenresValuesBatch[] = new ContentValues[genresCount];
int artistCount = 0, genreCount = 0;
int artistCount = 0;
for (AudioType.DetailsAlbum album : items) {
for (int artistId : album.artistid) {
albumArtistsValuesBatch[artistCount] = new ContentValues();
Expand All @@ -369,34 +372,27 @@ public void insertAlbumsItems(List<AudioType.DetailsAlbum> items, ContentResolve
albumArtistsValuesBatch[artistCount].put(MediaContract.AlbumArtists.ARTISTID, artistId);
artistCount++;
}

for (int genreId : album.genreid) {
albumGenresValuesBatch[genreCount] = new ContentValues();
albumGenresValuesBatch[genreCount].put(MediaContract.AlbumGenres.HOST_ID, hostId);
albumGenresValuesBatch[genreCount].put(MediaContract.AlbumGenres.ALBUMID, album.albumid);
albumGenresValuesBatch[genreCount].put(MediaContract.AlbumGenres.GENREID, genreId);
genreCount++;
}
}

contentResolver.bulkInsert(MediaContract.AlbumArtists.CONTENT_URI, albumArtistsValuesBatch);
contentResolver.bulkInsert(MediaContract.AlbumGenres.CONTENT_URI, albumGenresValuesBatch);
}

public void insertSongsItems(List<AudioType.DetailsSong> items, ContentResolver contentResolver) {
public void insertSongsItems(int hostId, List<AudioType.DetailsSong> items, ContentResolver contentResolver) {
ContentValues songValuesBatch[] = new ContentValues[items.size()];
int totalArtistsCount = 0;
int totalArtistsCount = 0, totalGenresCount = 0;
for (int i = 0; i < items.size(); i++) {
AudioType.DetailsSong song = items.get(i);
songValuesBatch[i] = SyncUtils.contentValuesFromSong(hostId, song);

totalArtistsCount += song.artistid.size();
totalGenresCount += song.genreid.size();
}
contentResolver.bulkInsert(MediaContract.Songs.CONTENT_URI, songValuesBatch);

// Iterate on each song, collect the artists and insert them
// Iterate on each song, collect the artists and the genres and insert them
ContentValues songArtistsValuesBatch[] = new ContentValues[totalArtistsCount];
int artistCount = 0;
ContentValues songGenresValuesBatch[] = new ContentValues[totalGenresCount];
int artistCount = 0, genreCount = 0;
for (AudioType.DetailsSong song : items) {
for (int artistId : song.artistid) {
songArtistsValuesBatch[artistCount] = new ContentValues();
Expand All @@ -405,8 +401,17 @@ public void insertSongsItems(List<AudioType.DetailsSong> items, ContentResolver
songArtistsValuesBatch[artistCount].put(MediaContract.SongArtists.ARTISTID, artistId);
artistCount++;
}

for (int genreId : song.genreid) {
songGenresValuesBatch[genreCount] = new ContentValues();
songGenresValuesBatch[genreCount].put(MediaContract.AlbumGenres.HOST_ID, hostId);
songGenresValuesBatch[genreCount].put(MediaContract.AlbumGenres.ALBUMID, song.albumid);
songGenresValuesBatch[genreCount].put(MediaContract.AlbumGenres.GENREID, genreId);
genreCount++;
}
}

contentResolver.bulkInsert(MediaContract.SongArtists.CONTENT_URI, songArtistsValuesBatch);
contentResolver.bulkInsert(MediaContract.AlbumGenres.CONTENT_URI, songGenresValuesBatch);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.text.util.Linkify;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.MenuItem;
Expand Down Expand Up @@ -451,10 +450,10 @@ public void onError(int errorCode, String description) { }
case 0:
// Download subtitles. First check host version to see which method to call
HostInfo hostInfo = hostManager.getHostInfo();
if (hostInfo.getKodiVersionMajor() < 13) {
showDownloadSubtitlesPreGotham();
} else {
if (hostInfo.isGothamOrLater()) {
showDownloadSubtitlesPostGotham();
} else {
showDownloadSubtitlesPreGotham();
}
break;
case 1:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -629,10 +629,10 @@ public boolean infoButtonLongClicked() {
HostInfo hostInfo = hostManager.getHostInfo();

// Info button, v17 uses a different window to display codec info so check version number
if (hostInfo.getKodiVersionMajor() < 17) {
action = new Input.ExecuteAction(Input.ExecuteAction.CODECINFO);
} else {
if (hostInfo.isKryptonOrLater()) {
action = new Input.ExecuteAction(Input.ExecuteAction.PLAYERPROCESSINFO);
} else {
action = new Input.ExecuteAction(Input.ExecuteAction.CODECINFO);
}
action.execute(hostManager.getConnection(), defaultActionCallback, callbackHandler);

Expand Down
Loading

0 comments on commit 246693a

Please sign in to comment.