Implemented recursion fix for movies and tv shows (#283)

This applies the fix for issue #219 Incomplete libraries for movies and
TV shows.
For music items this was already fixed in PR #236
See commit 7330f85241
This commit is contained in:
Martijn Brekhof 2016-09-26 19:31:22 +02:00 committed by Synced Synapse
parent 080b5809f3
commit dadabd09c5
8 changed files with 53 additions and 52 deletions

View File

@ -23,6 +23,7 @@ import android.content.Context;
import org.xbmc.kore.host.HostInfo;
import org.xbmc.kore.host.HostManager;
import org.xbmc.kore.jsonrpc.ApiException;
import org.xbmc.kore.jsonrpc.ApiList;
import org.xbmc.kore.jsonrpc.method.AudioLibrary;
import org.xbmc.kore.jsonrpc.method.VideoLibrary;
import org.xbmc.kore.jsonrpc.type.AudioType;
@ -68,15 +69,15 @@ public class Database {
private static void insertMovies(Context context, int hostId) throws ApiException, IOException {
VideoLibrary.GetMovies getMovies = new VideoLibrary.GetMovies();
String result = Utils.readFile(context, "Video.Details.Movie.json");
ArrayList<VideoType.DetailsMovie> movieList = (ArrayList) getMovies.resultFromJson(result);
ApiList<VideoType.DetailsMovie> movieList = getMovies.resultFromJson(result);
ContentValues movieValuesBatch[] = new ContentValues[movieList.size()];
ContentValues movieValuesBatch[] = new ContentValues[movieList.items.size()];
int castCount = 0;
// Iterate on each movie
for (int i = 0; i < movieList.size(); i++) {
VideoType.DetailsMovie movie = movieList.get(i);
for (int i = 0; i < movieList.items.size(); i++) {
VideoType.DetailsMovie movie = movieList.items.get(i);
movieValuesBatch[i] = SyncUtils.contentValuesFromMovie(hostId, movie);
castCount += movie.cast.size();
}
@ -86,7 +87,7 @@ public class Database {
ContentValues movieCastValuesBatch[] = new ContentValues[castCount];
int count = 0;
// Iterate on each movie/cast
for (VideoType.DetailsMovie movie : movieList) {
for (VideoType.DetailsMovie movie : movieList.items) {
for (VideoType.Cast cast : movie.cast) {
movieCastValuesBatch[count] = SyncUtils.contentValuesFromCast(hostId, cast);
movieCastValuesBatch[count].put(MediaContract.MovieCastColumns.MOVIEID, movie.movieid);

View File

@ -18,13 +18,9 @@ package org.xbmc.kore.testhelpers;
import android.database.Cursor;
import org.xbmc.kore.ui.SongsListFragment;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public class TestUtils {

View File

@ -19,18 +19,6 @@ package org.xbmc.kore.tests.mediaprovider;
import android.database.Cursor;
import org.xbmc.kore.provider.MediaContract;
import org.xbmc.kore.provider.MediaDatabase;
import org.xbmc.kore.provider.MediaProvider;
import org.xbmc.kore.ui.AlbumListFragment;
import org.xbmc.kore.ui.ArtistListFragment;
import org.xbmc.kore.ui.ArtistOverviewFragment;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import static org.junit.Assert.assertEquals;

View File

@ -19,6 +19,7 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.xbmc.kore.jsonrpc.ApiException;
import org.xbmc.kore.jsonrpc.ApiList;
import org.xbmc.kore.jsonrpc.ApiMethod;
import org.xbmc.kore.jsonrpc.type.ListType;
import org.xbmc.kore.jsonrpc.type.VideoType;
@ -82,7 +83,7 @@ public class VideoLibrary {
/**
* Retrieve all movies
*/
public static class GetMovies extends ApiMethod<List<VideoType.DetailsMovie>> {
public static class GetMovies extends ApiMethod<ApiList<VideoType.DetailsMovie>> {
public final static String METHOD_NAME = "VideoLibrary.GetMovies";
private final static String LIST_NODE = "movies";
@ -118,13 +119,15 @@ public class VideoLibrary {
}
@Override
public List<VideoType.DetailsMovie> resultFromJson(ObjectNode jsonObject)
public ApiList<VideoType.DetailsMovie> resultFromJson(ObjectNode jsonObject)
throws ApiException {
ListType.LimitsReturned limits = new ListType.LimitsReturned(jsonObject);
JsonNode resultNode = jsonObject.get(RESULT_NODE);
ArrayNode items = resultNode.has(LIST_NODE) ?
(ArrayNode)resultNode.get(LIST_NODE) : null;
if (items == null) {
return new ArrayList<VideoType.DetailsMovie>(0);
return new ApiList<>(new ArrayList<VideoType.DetailsMovie>(0), limits);
}
ArrayList<VideoType.DetailsMovie> result = new ArrayList<VideoType.DetailsMovie>(items.size());
@ -132,7 +135,7 @@ public class VideoLibrary {
result.add(new VideoType.DetailsMovie(item));
}
return result;
return new ApiList<>(result, limits);
}
}
@ -200,7 +203,7 @@ public class VideoLibrary {
/**
* Retrieve all TV Shows
*/
public static class GetTVShows extends ApiMethod<List<VideoType.DetailsTVShow>> {
public static class GetTVShows extends ApiMethod<ApiList<VideoType.DetailsTVShow>> {
public final static String METHOD_NAME = "VideoLibrary.GetTVShows";
private final static String LIST_NODE = "tvshows";
@ -235,21 +238,22 @@ public class VideoLibrary {
}
@Override
public List<VideoType.DetailsTVShow> resultFromJson(ObjectNode jsonObject)
public ApiList<VideoType.DetailsTVShow> resultFromJson(ObjectNode jsonObject)
throws ApiException {
ListType.LimitsReturned limits = new ListType.LimitsReturned(jsonObject);
JsonNode resultNode = jsonObject.get(RESULT_NODE);
ArrayNode items = resultNode.has(LIST_NODE) ?
(ArrayNode)resultNode.get(LIST_NODE) : null;
if (items == null) {
return new ArrayList<VideoType.DetailsTVShow>(0);
return new ApiList<>(new ArrayList<VideoType.DetailsTVShow>(0), limits);
}
ArrayList<VideoType.DetailsTVShow> result = new ArrayList<VideoType.DetailsTVShow>(items.size());
ArrayList<VideoType.DetailsTVShow> result = new ArrayList<>(items.size());
for (JsonNode item : items) {
result.add(new VideoType.DetailsTVShow(item));
}
return result;
return new ApiList<>(result, limits);
}
}

View File

@ -22,6 +22,7 @@ import android.os.Bundle;
import android.os.Handler;
import org.xbmc.kore.jsonrpc.ApiCallback;
import org.xbmc.kore.jsonrpc.ApiList;
import org.xbmc.kore.jsonrpc.HostConnection;
import org.xbmc.kore.jsonrpc.method.VideoLibrary;
import org.xbmc.kore.jsonrpc.type.ListType;
@ -146,19 +147,24 @@ public class SyncMovies extends SyncItem {
// Call GetMovies with the current limits set
ListType.Limits limits = new ListType.Limits(startIdx, startIdx + LIMIT_SYNC_MOVIES);
VideoLibrary.GetMovies action = new VideoLibrary.GetMovies(limits, properties);
action.execute(hostConnection, new ApiCallback<List<VideoType.DetailsMovie>>() {
action.execute(hostConnection, new ApiCallback<ApiList<VideoType.DetailsMovie>>() {
@Override
public void onSuccess(List<VideoType.DetailsMovie> result) {
public void onSuccess(ApiList<VideoType.DetailsMovie> result) {
ListType.LimitsReturned limitsReturned = null;
if (result != null) {
limitsReturned = result.limits;
}
if (startIdx == 0) {
// First call, delete movies from DB
deleteMovies(contentResolver, hostId, -1);
}
if (!result.isEmpty()) {
insertMovies(orchestrator, contentResolver, result);
if (!result.items.isEmpty()) {
insertMovies(orchestrator, contentResolver, result.items);
}
LogUtils.LOGD(TAG, "syncAllMovies, movies gotten: " + result.size());
if (result.size() == LIMIT_SYNC_MOVIES) {
LogUtils.LOGD(TAG, "syncAllMovies, movies gotten: " + result.items.size());
if (SyncUtils.moreItemsAvailable(limitsReturned)) {
// Max limit returned, there may be some more movies
// As we're going to recurse, these result objects can add up, so
// let's help the GC and indicate that we don't need this memory
@ -176,7 +182,7 @@ public class SyncMovies extends SyncItem {
@Override
public void onError(int errorCode, String description) {
// Ok, something bad happend, just quit
// Ok, something bad happened, just quit
orchestrator.syncItemFailed(errorCode, description);
}
}, callbackHandler);

View File

@ -118,7 +118,7 @@ public class SyncMusic extends SyncItem {
insertArtists(items, contentResolver);
if (moreItemsAvailable(limitsReturned)) {
if (SyncUtils.moreItemsAvailable(limitsReturned)) {
LogUtils.LOGD(TAG, "chainCallSyncArtists: More results on media center, recursing.");
result = null; // Help the GC?
chainCallSyncArtists(orchestrator, hostConnection, callbackHandler, contentResolver,
@ -235,7 +235,7 @@ public class SyncMusic extends SyncItem {
LogUtils.LOGD(TAG, "Finished inserting artists and genres in: " +
(System.currentTimeMillis() - albumSyncStartTime));
if (moreItemsAvailable(limitsReturned)) {
if (SyncUtils.moreItemsAvailable(limitsReturned)) {
LogUtils.LOGD(TAG, "chainCallSyncAlbums: More results on media center, recursing.");
result = null; // Help the GC?
chainCallSyncAlbums(orchestrator, hostConnection, callbackHandler, contentResolver,
@ -302,7 +302,7 @@ public class SyncMusic extends SyncItem {
// Save partial results to DB
insertSongsItems(items, contentResolver);
if (moreItemsAvailable(limitsReturned)) {
if (SyncUtils.moreItemsAvailable(limitsReturned)) {
LogUtils.LOGD(TAG, "chainCallSyncSongs: More results on media center, recursing.");
result = null; // Help the GC?
chainCallSyncSongs(orchestrator, hostConnection, callbackHandler, contentResolver,
@ -407,12 +407,4 @@ public class SyncMusic extends SyncItem {
contentResolver.bulkInsert(MediaContract.SongArtists.CONTENT_URI, songArtistsValuesBatch);
}
private boolean moreItemsAvailable(ListType.LimitsReturned limitsReturned) {
boolean moreItemsAvailable = false;
if (limitsReturned != null) {
moreItemsAvailable = ( limitsReturned.total - limitsReturned.end ) > 0;
}
return moreItemsAvailable;
}
}

View File

@ -23,6 +23,7 @@ import android.os.Bundle;
import android.os.Handler;
import org.xbmc.kore.jsonrpc.ApiCallback;
import org.xbmc.kore.jsonrpc.ApiList;
import org.xbmc.kore.jsonrpc.HostConnection;
import org.xbmc.kore.jsonrpc.method.VideoLibrary;
import org.xbmc.kore.jsonrpc.type.ListType;
@ -143,11 +144,11 @@ public class SyncTVShows extends SyncItem {
// Call GetTVShows with the current limits set
ListType.Limits limits = new ListType.Limits(startIdx, startIdx + LIMIT_SYNC_TVSHOWS);
VideoLibrary.GetTVShows action = new VideoLibrary.GetTVShows(limits, getTVShowsProperties);
action.execute(hostConnection, new ApiCallback<List<VideoType.DetailsTVShow>>() {
action.execute(hostConnection, new ApiCallback<ApiList<VideoType.DetailsTVShow>>() {
@Override
public void onSuccess(List<VideoType.DetailsTVShow> result) {
allResults.addAll(result);
if (result.size() == LIMIT_SYNC_TVSHOWS) {
public void onSuccess(ApiList<VideoType.DetailsTVShow> result) {
allResults.addAll(result.items);
if (SyncUtils.moreItemsAvailable(result.limits)) {
// Max limit returned, there may be some more movies
LogUtils.LOGD(TAG, "syncAllTVShows: More tv shows on media center, recursing.");
syncAllTVShows(orchestrator, hostConnection, callbackHandler, contentResolver,

View File

@ -23,6 +23,7 @@ import android.content.ServiceConnection;
import android.os.IBinder;
import org.xbmc.kore.host.HostInfo;
import org.xbmc.kore.jsonrpc.type.ListType;
import org.xbmc.kore.jsonrpc.type.VideoType;
import org.xbmc.kore.jsonrpc.type.AudioType;
import org.xbmc.kore.jsonrpc.type.LibraryType;
@ -476,4 +477,16 @@ public class SyncUtils {
return false;
}
/**
* Checks if there are more items available according to the limits returned
* @param limitsReturned
* @return true if there are more items available, false otherwise
*/
public static boolean moreItemsAvailable(ListType.LimitsReturned limitsReturned) {
if (limitsReturned != null) {
return ( limitsReturned.total - limitsReturned.end ) > 0;
}
return false;
}
}