Changed library sync to include limits when getting media info from media center
This commit is contained in:
parent
850e9809e2
commit
56ef1a9497
|
@ -22,6 +22,7 @@ import com.syncedsynapse.kore2.jsonrpc.ApiException;
|
||||||
import com.syncedsynapse.kore2.jsonrpc.ApiMethod;
|
import com.syncedsynapse.kore2.jsonrpc.ApiMethod;
|
||||||
import com.syncedsynapse.kore2.jsonrpc.type.AudioType;
|
import com.syncedsynapse.kore2.jsonrpc.type.AudioType;
|
||||||
import com.syncedsynapse.kore2.jsonrpc.type.LibraryType;
|
import com.syncedsynapse.kore2.jsonrpc.type.LibraryType;
|
||||||
|
import com.syncedsynapse.kore2.jsonrpc.type.ListType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -102,6 +103,23 @@ public class AudioLibrary {
|
||||||
addParameterToRequest("properties", properties);
|
addParameterToRequest("properties", properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all artists with limits
|
||||||
|
*
|
||||||
|
* @param limits Limits to retrieve. See {@link ListType.Limits}
|
||||||
|
* @param albumartistsonly Whether or not to include artists only appearing in
|
||||||
|
* compilations. If the parameter is not passed or is passed as
|
||||||
|
* null the GUI setting will be used
|
||||||
|
* @param properties Properties to retrieve. See {@link AudioType.FieldsArtists} for a
|
||||||
|
* list of accepted values
|
||||||
|
*/
|
||||||
|
public GetArtists(ListType.Limits limits, boolean albumartistsonly, String... properties) {
|
||||||
|
super();
|
||||||
|
addParameterToRequest("limits", limits);
|
||||||
|
addParameterToRequest("albumartistsonly", albumartistsonly);
|
||||||
|
addParameterToRequest("properties", properties);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMethodName() {
|
public String getMethodName() {
|
||||||
return METHOD_NAME;
|
return METHOD_NAME;
|
||||||
|
@ -135,7 +153,7 @@ public class AudioLibrary {
|
||||||
private final static String LIST_NODE = "albums";
|
private final static String LIST_NODE = "albums";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve all albums from specified artist or genre
|
* Retrieve all albums
|
||||||
*
|
*
|
||||||
* @param properties Properties to retrieve. See {@link AudioType.FieldsAlbum} for a
|
* @param properties Properties to retrieve. See {@link AudioType.FieldsAlbum} for a
|
||||||
* list of accepted values
|
* list of accepted values
|
||||||
|
@ -145,6 +163,19 @@ public class AudioLibrary {
|
||||||
addParameterToRequest("properties", properties);
|
addParameterToRequest("properties", properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all albums with limits
|
||||||
|
*
|
||||||
|
* @param limits Limits to retrieve. See {@link ListType.Limits}
|
||||||
|
* @param properties Properties to retrieve. See {@link AudioType.FieldsAlbum} for a
|
||||||
|
* list of accepted values
|
||||||
|
*/
|
||||||
|
public GetAlbums(ListType.Limits limits, String... properties) {
|
||||||
|
super();
|
||||||
|
addParameterToRequest("limits", limits);
|
||||||
|
addParameterToRequest("properties", properties);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMethodName() {
|
public String getMethodName() {
|
||||||
return METHOD_NAME;
|
return METHOD_NAME;
|
||||||
|
@ -219,7 +250,7 @@ public class AudioLibrary {
|
||||||
private final static String LIST_NODE = "songs";
|
private final static String LIST_NODE = "songs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve all songs from specified album, artist or genre
|
* Retrieve all songs
|
||||||
*
|
*
|
||||||
* @param properties Properties to retrieve. See {@link AudioType.FieldsSong} for a
|
* @param properties Properties to retrieve. See {@link AudioType.FieldsSong} for a
|
||||||
* list of accepted values
|
* list of accepted values
|
||||||
|
@ -229,6 +260,19 @@ public class AudioLibrary {
|
||||||
addParameterToRequest("properties", properties);
|
addParameterToRequest("properties", properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all songs with limits
|
||||||
|
*
|
||||||
|
* @param limits Limits to retrieve. See {@link ListType.Limits}
|
||||||
|
* @param properties Properties to retrieve. See {@link AudioType.FieldsSong} for a
|
||||||
|
* list of accepted values
|
||||||
|
*/
|
||||||
|
public GetSongs(ListType.Limits limits, String... properties) {
|
||||||
|
super();
|
||||||
|
addParameterToRequest("limits", limits);
|
||||||
|
addParameterToRequest("properties", properties);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMethodName() {
|
public String getMethodName() {
|
||||||
return METHOD_NAME;
|
return METHOD_NAME;
|
||||||
|
|
|
@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.syncedsynapse.kore2.jsonrpc.ApiException;
|
import com.syncedsynapse.kore2.jsonrpc.ApiException;
|
||||||
import com.syncedsynapse.kore2.jsonrpc.ApiMethod;
|
import com.syncedsynapse.kore2.jsonrpc.ApiMethod;
|
||||||
|
import com.syncedsynapse.kore2.jsonrpc.type.ListType;
|
||||||
import com.syncedsynapse.kore2.jsonrpc.type.VideoType;
|
import com.syncedsynapse.kore2.jsonrpc.type.VideoType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -87,7 +88,8 @@ public class VideoLibrary {
|
||||||
private final static String LIST_NODE = "movies";
|
private final static String LIST_NODE = "movies";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve all movies
|
* Retrieve all movies, without limits
|
||||||
|
* Caution, this can break in large libraries
|
||||||
*
|
*
|
||||||
* @param properties Properties to retrieve. See {@link VideoType.FieldsMovie} for a list of
|
* @param properties Properties to retrieve. See {@link VideoType.FieldsMovie} for a list of
|
||||||
* accepted values
|
* accepted values
|
||||||
|
@ -97,6 +99,19 @@ public class VideoLibrary {
|
||||||
addParameterToRequest("properties", properties);
|
addParameterToRequest("properties", properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all movies, with limits
|
||||||
|
*
|
||||||
|
* @param limits Limits to retrieve. See {@link ListType.Limits}
|
||||||
|
* @param properties Properties to retrieve. See {@link VideoType.FieldsMovie} for a list of
|
||||||
|
* accepted values
|
||||||
|
*/
|
||||||
|
public GetMovies(ListType.Limits limits, String... properties) {
|
||||||
|
super();
|
||||||
|
addParameterToRequest("properties", properties);
|
||||||
|
addParameterToRequest("limits", limits);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMethodName() {
|
public String getMethodName() {
|
||||||
return METHOD_NAME;
|
return METHOD_NAME;
|
||||||
|
@ -201,6 +216,19 @@ public class VideoLibrary {
|
||||||
addParameterToRequest("properties", properties);
|
addParameterToRequest("properties", properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all tv shows, with limits
|
||||||
|
*
|
||||||
|
* @param limits Limits to retrieve. See {@link ListType.Limits}
|
||||||
|
* @param properties Properties to retrieve. See {@link VideoType.FieldsMovie} for a list of
|
||||||
|
* accepted values
|
||||||
|
*/
|
||||||
|
public GetTVShows(ListType.Limits limits, String... properties) {
|
||||||
|
super();
|
||||||
|
addParameterToRequest("properties", properties);
|
||||||
|
addParameterToRequest("limits", limits);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMethodName() {
|
public String getMethodName() {
|
||||||
return METHOD_NAME;
|
return METHOD_NAME;
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
package com.syncedsynapse.kore2.jsonrpc.type;
|
package com.syncedsynapse.kore2.jsonrpc.type;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.syncedsynapse.kore2.utils.JsonUtils;
|
import com.syncedsynapse.kore2.utils.JsonUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -310,6 +312,33 @@ public class ListType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List.Limits
|
||||||
|
*/
|
||||||
|
public static class Limits
|
||||||
|
implements ApiParameter {
|
||||||
|
public static final String START = "start";
|
||||||
|
public static final String END = "end";
|
||||||
|
|
||||||
|
protected static final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
public final int start;
|
||||||
|
public final int end;
|
||||||
|
|
||||||
|
public Limits(int start, int end) {
|
||||||
|
this.start = start;
|
||||||
|
this.end = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonNode toJsonNode() {
|
||||||
|
final ObjectNode node = objectMapper.createObjectNode();
|
||||||
|
node.put(START, start);
|
||||||
|
node.put(END, end);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enums for List.Fields.All
|
* Enums for List.Fields.All
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -35,6 +35,7 @@ import com.syncedsynapse.kore2.jsonrpc.event.MediaSyncEvent;
|
||||||
import com.syncedsynapse.kore2.jsonrpc.method.*;
|
import com.syncedsynapse.kore2.jsonrpc.method.*;
|
||||||
import com.syncedsynapse.kore2.jsonrpc.type.AudioType;
|
import com.syncedsynapse.kore2.jsonrpc.type.AudioType;
|
||||||
import com.syncedsynapse.kore2.jsonrpc.type.LibraryType;
|
import com.syncedsynapse.kore2.jsonrpc.type.LibraryType;
|
||||||
|
import com.syncedsynapse.kore2.jsonrpc.type.ListType;
|
||||||
import com.syncedsynapse.kore2.jsonrpc.type.VideoType;
|
import com.syncedsynapse.kore2.jsonrpc.type.VideoType;
|
||||||
import com.syncedsynapse.kore2.provider.MediaContract;
|
import com.syncedsynapse.kore2.provider.MediaContract;
|
||||||
import com.syncedsynapse.kore2.utils.LogUtils;
|
import com.syncedsynapse.kore2.utils.LogUtils;
|
||||||
|
@ -53,6 +54,12 @@ import de.greenrobot.event.EventBus;
|
||||||
public class LibrarySyncService extends Service {
|
public class LibrarySyncService extends Service {
|
||||||
public static final String TAG = LogUtils.makeLogTag(LibrarySyncService.class);
|
public static final String TAG = LogUtils.makeLogTag(LibrarySyncService.class);
|
||||||
|
|
||||||
|
private static final int LIMIT_SYNC_MOVIES = 300;
|
||||||
|
private static final int LIMIT_SYNC_TVSHOWS = 300;
|
||||||
|
private static final int LIMIT_SYNC_ARTISTS = 300;
|
||||||
|
private static final int LIMIT_SYNC_ALBUMS = 300;
|
||||||
|
private static final int LIMIT_SYNC_SONGS = 600;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Possible requests to sync
|
* Possible requests to sync
|
||||||
*/
|
*/
|
||||||
|
@ -362,7 +369,6 @@ public class LibrarySyncService extends Service {
|
||||||
return syncExtras;
|
return syncExtras;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public void sync(final SyncOrchestrator orchestrator,
|
public void sync(final SyncOrchestrator orchestrator,
|
||||||
final HostConnection hostConnection,
|
final HostConnection hostConnection,
|
||||||
|
@ -391,21 +397,7 @@ public class LibrarySyncService extends Service {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (movieId == -1) {
|
if (movieId == -1) {
|
||||||
// Delete and sync all movies
|
syncAllMovies(orchestrator, hostConnection, callbackHandler, contentResolver, properties, 0);
|
||||||
VideoLibrary.GetMovies action = new VideoLibrary.GetMovies(properties);
|
|
||||||
action.execute(hostConnection, new ApiCallback<List<VideoType.DetailsMovie>>() {
|
|
||||||
@Override
|
|
||||||
public void onSucess(List<VideoType.DetailsMovie> result) {
|
|
||||||
deleteMovies(contentResolver, hostId, -1);
|
|
||||||
insertMovies(orchestrator, contentResolver, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(int errorCode, String description) {
|
|
||||||
// Ok, something bad happend, just quit
|
|
||||||
orchestrator.syncItemFailed(errorCode, description);
|
|
||||||
}
|
|
||||||
}, callbackHandler);
|
|
||||||
} else {
|
} else {
|
||||||
// Sync a specific movie
|
// Sync a specific movie
|
||||||
VideoLibrary.GetMovieDetails action =
|
VideoLibrary.GetMovieDetails action =
|
||||||
|
@ -417,6 +409,7 @@ public class LibrarySyncService extends Service {
|
||||||
List<VideoType.DetailsMovie> movies = new ArrayList<VideoType.DetailsMovie>(1);
|
List<VideoType.DetailsMovie> movies = new ArrayList<VideoType.DetailsMovie>(1);
|
||||||
movies.add(result);
|
movies.add(result);
|
||||||
insertMovies(orchestrator, contentResolver, movies);
|
insertMovies(orchestrator, contentResolver, movies);
|
||||||
|
orchestrator.syncItemFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -428,6 +421,60 @@ public class LibrarySyncService extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Syncs all the movies, calling itself recursively
|
||||||
|
* Uses the {@link VideoLibrary.GetMovies} version with limits to make sure
|
||||||
|
* that Kodi doesn't blow up, and calls itself recursively until all the
|
||||||
|
* movies are returned
|
||||||
|
*/
|
||||||
|
private void syncAllMovies(final SyncOrchestrator orchestrator,
|
||||||
|
final HostConnection hostConnection,
|
||||||
|
final Handler callbackHandler,
|
||||||
|
final ContentResolver contentResolver,
|
||||||
|
final String properties[],
|
||||||
|
final int startIdx) {
|
||||||
|
// 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>>() {
|
||||||
|
@Override
|
||||||
|
public void onSucess(List<VideoType.DetailsMovie> result) {
|
||||||
|
if (startIdx == 0) {
|
||||||
|
// First call, delete movies from DB
|
||||||
|
deleteMovies(contentResolver, hostId, -1);
|
||||||
|
}
|
||||||
|
if (result.size() > 0) {
|
||||||
|
insertMovies(orchestrator, contentResolver, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogUtils.LOGD(TAG, "syncAllMovies, movies gotten: " + result.size());
|
||||||
|
if (result.size() == LIMIT_SYNC_MOVIES) {
|
||||||
|
// 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
|
||||||
|
// (hopefully this works)
|
||||||
|
result = null;
|
||||||
|
syncAllMovies(orchestrator, hostConnection, callbackHandler, contentResolver,
|
||||||
|
properties, startIdx + LIMIT_SYNC_MOVIES);
|
||||||
|
} else {
|
||||||
|
// Less than the limit was returned so we can finish
|
||||||
|
// (if it returned more there's a bug in Kodi but it
|
||||||
|
// shouldn't be a problem as they got inserted in the DB)
|
||||||
|
orchestrator.syncItemFinished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(int errorCode, String description) {
|
||||||
|
// Ok, something bad happend, just quit
|
||||||
|
orchestrator.syncItemFailed(errorCode, description);
|
||||||
|
}
|
||||||
|
}, callbackHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes one or all movies from the database (pass -1 on movieId to delete all)
|
||||||
|
*/
|
||||||
private void deleteMovies(final ContentResolver contentResolver,
|
private void deleteMovies(final ContentResolver contentResolver,
|
||||||
int hostId, int movieId) {
|
int hostId, int movieId) {
|
||||||
if (movieId == -1) {
|
if (movieId == -1) {
|
||||||
|
@ -446,6 +493,9 @@ public class LibrarySyncService extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts the given movies in the database
|
||||||
|
*/
|
||||||
private void insertMovies(final SyncOrchestrator orchestrator,
|
private void insertMovies(final SyncOrchestrator orchestrator,
|
||||||
final ContentResolver contentResolver,
|
final ContentResolver contentResolver,
|
||||||
final List<VideoType.DetailsMovie> movies) {
|
final List<VideoType.DetailsMovie> movies) {
|
||||||
|
@ -475,8 +525,6 @@ public class LibrarySyncService extends Service {
|
||||||
|
|
||||||
// Insert the cast list for this movie
|
// Insert the cast list for this movie
|
||||||
contentResolver.bulkInsert(MediaContract.MovieCast.CONTENT_URI, movieCastValuesBatch);
|
contentResolver.bulkInsert(MediaContract.MovieCast.CONTENT_URI, movieCastValuesBatch);
|
||||||
|
|
||||||
orchestrator.syncItemFinished();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,45 +574,30 @@ public class LibrarySyncService extends Service {
|
||||||
return syncExtras;
|
return syncExtras;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final static String getTVShowsProperties[] = {
|
||||||
|
VideoType.FieldsTVShow.TITLE, VideoType.FieldsTVShow.GENRE,
|
||||||
|
//VideoType.FieldsTVShow.YEAR,
|
||||||
|
VideoType.FieldsTVShow.RATING, VideoType.FieldsTVShow.PLOT,
|
||||||
|
VideoType.FieldsTVShow.STUDIO, VideoType.FieldsTVShow.MPAA,
|
||||||
|
VideoType.FieldsTVShow.CAST, VideoType.FieldsTVShow.PLAYCOUNT,
|
||||||
|
VideoType.FieldsTVShow.EPISODE, VideoType.FieldsTVShow.IMDBNUMBER,
|
||||||
|
VideoType.FieldsTVShow.PREMIERED,
|
||||||
|
//VideoType.FieldsTVShow.VOTES, VideoType.FieldsTVShow.LASTPLAYED,
|
||||||
|
VideoType.FieldsTVShow.FANART, VideoType.FieldsTVShow.THUMBNAIL,
|
||||||
|
VideoType.FieldsTVShow.FILE,
|
||||||
|
//VideoType.FieldsTVShow.ORIGINALTITLE, VideoType.FieldsTVShow.SORTTITLE,
|
||||||
|
// VideoType.FieldsTVShow.EPISODEGUIDE, VideoType.FieldsTVShow.SEASON,
|
||||||
|
VideoType.FieldsTVShow.WATCHEDEPISODES, VideoType.FieldsTVShow.DATEADDED,
|
||||||
|
//VideoType.FieldsTVShow.TAG, VideoType.FieldsTVShow.ART
|
||||||
|
};
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public void sync(final SyncOrchestrator orchestrator,
|
public void sync(final SyncOrchestrator orchestrator,
|
||||||
final HostConnection hostConnection,
|
final HostConnection hostConnection,
|
||||||
final Handler callbackHandler,
|
final Handler callbackHandler,
|
||||||
final ContentResolver contentResolver) {
|
final ContentResolver contentResolver) {
|
||||||
String getTVShowsProperties[] = {
|
|
||||||
VideoType.FieldsTVShow.TITLE, VideoType.FieldsTVShow.GENRE,
|
|
||||||
//VideoType.FieldsTVShow.YEAR,
|
|
||||||
VideoType.FieldsTVShow.RATING, VideoType.FieldsTVShow.PLOT,
|
|
||||||
VideoType.FieldsTVShow.STUDIO, VideoType.FieldsTVShow.MPAA,
|
|
||||||
VideoType.FieldsTVShow.CAST, VideoType.FieldsTVShow.PLAYCOUNT,
|
|
||||||
VideoType.FieldsTVShow.EPISODE, VideoType.FieldsTVShow.IMDBNUMBER,
|
|
||||||
VideoType.FieldsTVShow.PREMIERED,
|
|
||||||
//VideoType.FieldsTVShow.VOTES, VideoType.FieldsTVShow.LASTPLAYED,
|
|
||||||
VideoType.FieldsTVShow.FANART, VideoType.FieldsTVShow.THUMBNAIL,
|
|
||||||
VideoType.FieldsTVShow.FILE,
|
|
||||||
//VideoType.FieldsTVShow.ORIGINALTITLE, VideoType.FieldsTVShow.SORTTITLE,
|
|
||||||
// VideoType.FieldsTVShow.EPISODEGUIDE, VideoType.FieldsTVShow.SEASON,
|
|
||||||
VideoType.FieldsTVShow.WATCHEDEPISODES, VideoType.FieldsTVShow.DATEADDED,
|
|
||||||
//VideoType.FieldsTVShow.TAG, VideoType.FieldsTVShow.ART
|
|
||||||
};
|
|
||||||
|
|
||||||
if (tvshowId == -1) {
|
if (tvshowId == -1) {
|
||||||
// Sync all tvshows
|
syncAllTVShows(orchestrator, hostConnection, callbackHandler, contentResolver,
|
||||||
VideoLibrary.GetTVShows action = new VideoLibrary.GetTVShows(getTVShowsProperties);
|
0, new ArrayList<VideoType.DetailsTVShow>());
|
||||||
action.execute(hostConnection, new ApiCallback<List<VideoType.DetailsTVShow>>() {
|
|
||||||
@Override
|
|
||||||
public void onSucess(List<VideoType.DetailsTVShow> result) {
|
|
||||||
deleteTVShows(contentResolver, hostId, -1);
|
|
||||||
insertTVShowsAndGetDetails(orchestrator, hostConnection, callbackHandler,
|
|
||||||
contentResolver, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(int errorCode, String description) {
|
|
||||||
// Ok, something bad happend, just quit
|
|
||||||
orchestrator.syncItemFailed(errorCode, description);
|
|
||||||
}
|
|
||||||
}, callbackHandler);
|
|
||||||
} else {
|
} else {
|
||||||
VideoLibrary.GetTVShowDetails action =
|
VideoLibrary.GetTVShowDetails action =
|
||||||
new VideoLibrary.GetTVShowDetails(tvshowId, getTVShowsProperties);
|
new VideoLibrary.GetTVShowDetails(tvshowId, getTVShowsProperties);
|
||||||
|
@ -577,6 +610,7 @@ public class LibrarySyncService extends Service {
|
||||||
tvShows.add(result);
|
tvShows.add(result);
|
||||||
insertTVShowsAndGetDetails(orchestrator, hostConnection, callbackHandler,
|
insertTVShowsAndGetDetails(orchestrator, hostConnection, callbackHandler,
|
||||||
contentResolver, tvShows);
|
contentResolver, tvShows);
|
||||||
|
// insertTVShows calls syncItemFinished
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -588,6 +622,47 @@ public class LibrarySyncService extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Syncs all the TV shows, calling itself recursively
|
||||||
|
* Uses the {@link VideoLibrary.GetTVShows} version with limits to make sure
|
||||||
|
* that Kodi doesn't blow up, and calls itself recursively until all the
|
||||||
|
* shows are returned
|
||||||
|
*/
|
||||||
|
private void syncAllTVShows(final SyncOrchestrator orchestrator,
|
||||||
|
final HostConnection hostConnection,
|
||||||
|
final Handler callbackHandler,
|
||||||
|
final ContentResolver contentResolver,
|
||||||
|
final int startIdx,
|
||||||
|
final List<VideoType.DetailsTVShow> allResults) {
|
||||||
|
// 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>>() {
|
||||||
|
@Override
|
||||||
|
public void onSucess(List<VideoType.DetailsTVShow> result) {
|
||||||
|
allResults.addAll(result);
|
||||||
|
if (result.size() == LIMIT_SYNC_TVSHOWS) {
|
||||||
|
// 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,
|
||||||
|
startIdx + LIMIT_SYNC_TVSHOWS, allResults);
|
||||||
|
} else {
|
||||||
|
// Ok, we have all the shows, insert them
|
||||||
|
LogUtils.LOGD(TAG, "syncAllTVShows: Got all tv shows");
|
||||||
|
deleteTVShows(contentResolver, hostId, -1);
|
||||||
|
insertTVShowsAndGetDetails(orchestrator, hostConnection, callbackHandler,
|
||||||
|
contentResolver, allResults);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(int errorCode, String description) {
|
||||||
|
// Ok, something bad happend, just quit
|
||||||
|
orchestrator.syncItemFailed(errorCode, description);
|
||||||
|
}
|
||||||
|
}, callbackHandler);
|
||||||
|
}
|
||||||
|
|
||||||
private void deleteTVShows(final ContentResolver contentResolver,
|
private void deleteTVShows(final ContentResolver contentResolver,
|
||||||
int hostId, int tvshowId) {
|
int hostId, int tvshowId) {
|
||||||
if (tvshowId == -1) {
|
if (tvshowId == -1) {
|
||||||
|
@ -833,37 +908,61 @@ public class LibrarySyncService extends Service {
|
||||||
final HostConnection hostConnection,
|
final HostConnection hostConnection,
|
||||||
final Handler callbackHandler,
|
final Handler callbackHandler,
|
||||||
final ContentResolver contentResolver) {
|
final ContentResolver contentResolver) {
|
||||||
String getArtistsProperties[] = {
|
chainCallSyncArtists(orchestrator, hostConnection, callbackHandler, contentResolver,
|
||||||
// AudioType.FieldsArtists.INSTRUMENT, AudioType.FieldsArtists.STYLE,
|
0, new ArrayList<AudioType.DetailsArtist>());
|
||||||
// AudioType.FieldsArtists.MOOD, AudioType.FieldsArtists.BORN,
|
}
|
||||||
// AudioType.FieldsArtists.FORMED,
|
|
||||||
AudioType.FieldsArtists.DESCRIPTION,
|
|
||||||
AudioType.FieldsArtists.GENRE,
|
|
||||||
// AudioType.FieldsArtists.DIED,
|
|
||||||
// AudioType.FieldsArtists.DISBANDED, AudioType.FieldsArtists.YEARSACTIVE,
|
|
||||||
//AudioType.FieldsArtists.MUSICBRAINZARTISTID,
|
|
||||||
AudioType.FieldsArtists.FANART,
|
|
||||||
AudioType.FieldsArtists.THUMBNAIL
|
|
||||||
};
|
|
||||||
|
|
||||||
|
private final static String getArtistsProperties[] = {
|
||||||
|
// AudioType.FieldsArtists.INSTRUMENT, AudioType.FieldsArtists.STYLE,
|
||||||
|
// AudioType.FieldsArtists.MOOD, AudioType.FieldsArtists.BORN,
|
||||||
|
// AudioType.FieldsArtists.FORMED,
|
||||||
|
AudioType.FieldsArtists.DESCRIPTION,
|
||||||
|
AudioType.FieldsArtists.GENRE,
|
||||||
|
// AudioType.FieldsArtists.DIED,
|
||||||
|
// AudioType.FieldsArtists.DISBANDED, AudioType.FieldsArtists.YEARSACTIVE,
|
||||||
|
//AudioType.FieldsArtists.MUSICBRAINZARTISTID,
|
||||||
|
AudioType.FieldsArtists.FANART,
|
||||||
|
AudioType.FieldsArtists.THUMBNAIL
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Gets all artists recursively and forwards the call to Genres
|
||||||
|
* Genres->Albums->Songs
|
||||||
|
*/
|
||||||
|
public void chainCallSyncArtists(final SyncOrchestrator orchestrator,
|
||||||
|
final HostConnection hostConnection,
|
||||||
|
final Handler callbackHandler,
|
||||||
|
final ContentResolver contentResolver,
|
||||||
|
final int startIdx,
|
||||||
|
final List<AudioType.DetailsArtist> allResults) {
|
||||||
// Artists->Genres->Albums->Songs
|
// Artists->Genres->Albums->Songs
|
||||||
// Only gets album artists (first parameter)
|
// Only gets album artists (first parameter)
|
||||||
AudioLibrary.GetArtists action = new AudioLibrary.GetArtists(true, getArtistsProperties);
|
ListType.Limits limits = new ListType.Limits(startIdx, startIdx + LIMIT_SYNC_ARTISTS);
|
||||||
|
AudioLibrary.GetArtists action = new AudioLibrary.GetArtists(limits, true, getArtistsProperties);
|
||||||
action.execute(hostConnection, new ApiCallback<List<AudioType.DetailsArtist>>() {
|
action.execute(hostConnection, new ApiCallback<List<AudioType.DetailsArtist>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSucess(List<AudioType.DetailsArtist> result) {
|
public void onSucess(List<AudioType.DetailsArtist> result) {
|
||||||
// First delete all music info
|
allResults.addAll(result);
|
||||||
deleteMusicInfo(contentResolver, hostId);
|
if (result.size() == LIMIT_SYNC_ARTISTS) {
|
||||||
|
// Max limit returned, there may be some more
|
||||||
|
LogUtils.LOGD(TAG, "chainCallSyncArtists: More results on media center, recursing.");
|
||||||
|
chainCallSyncArtists(orchestrator, hostConnection, callbackHandler, contentResolver,
|
||||||
|
startIdx + LIMIT_SYNC_ARTISTS, allResults);
|
||||||
|
} else {
|
||||||
|
// Ok, we have all the shows, insert them
|
||||||
|
LogUtils.LOGD(TAG, "chainCallSyncArtists: Got all results, continuing");
|
||||||
|
|
||||||
ContentValues artistValuesBatch[] = new ContentValues[result.size()];
|
// First delete all music info
|
||||||
for (int i = 0; i < result.size(); i++) {
|
deleteMusicInfo(contentResolver, hostId);
|
||||||
AudioType.DetailsArtist artist = result.get(i);
|
|
||||||
artistValuesBatch[i] = SyncUtils.contentValuesFromArtist(hostId, artist);
|
ContentValues artistValuesBatch[] = new ContentValues[allResults.size()];
|
||||||
|
for (int i = 0; i < allResults.size(); i++) {
|
||||||
|
AudioType.DetailsArtist artist = allResults.get(i);
|
||||||
|
artistValuesBatch[i] = SyncUtils.contentValuesFromArtist(hostId, artist);
|
||||||
|
}
|
||||||
|
// Insert the artists and continue the syncing
|
||||||
|
contentResolver.bulkInsert(MediaContract.Artists.CONTENT_URI, artistValuesBatch);
|
||||||
|
chainCallSyncGenres(orchestrator, hostConnection, callbackHandler, contentResolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert the artists and continue the syncing
|
|
||||||
contentResolver.bulkInsert(MediaContract.Artists.CONTENT_URI, artistValuesBatch);
|
|
||||||
chainCallSyncGenres(orchestrator, hostConnection, callbackHandler, contentResolver);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -893,6 +992,9 @@ public class LibrarySyncService extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private final static String getGenresProperties[] = {
|
||||||
|
LibraryType.FieldsGenre.TITLE, LibraryType.FieldsGenre.THUMBNAIL
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* Syncs Audio genres and forwards calls to sync albums:
|
* Syncs Audio genres and forwards calls to sync albums:
|
||||||
* Genres->Albums->Songs
|
* Genres->Albums->Songs
|
||||||
|
@ -901,10 +1003,6 @@ public class LibrarySyncService extends Service {
|
||||||
final HostConnection hostConnection,
|
final HostConnection hostConnection,
|
||||||
final Handler callbackHandler,
|
final Handler callbackHandler,
|
||||||
final ContentResolver contentResolver) {
|
final ContentResolver contentResolver) {
|
||||||
String getGenresProperties[] = {
|
|
||||||
LibraryType.FieldsGenre.TITLE, LibraryType.FieldsGenre.THUMBNAIL
|
|
||||||
};
|
|
||||||
|
|
||||||
// Genres->Albums->Songs
|
// Genres->Albums->Songs
|
||||||
AudioLibrary.GetGenres action = new AudioLibrary.GetGenres(getGenresProperties);
|
AudioLibrary.GetGenres action = new AudioLibrary.GetGenres(getGenresProperties);
|
||||||
action.execute(hostConnection, new ApiCallback<List<LibraryType.DetailsGenre>>() {
|
action.execute(hostConnection, new ApiCallback<List<LibraryType.DetailsGenre>>() {
|
||||||
|
@ -920,7 +1018,8 @@ public class LibrarySyncService extends Service {
|
||||||
// Insert the genres
|
// Insert the genres
|
||||||
contentResolver.bulkInsert(MediaContract.AudioGenres.CONTENT_URI, genresValuesBatch);
|
contentResolver.bulkInsert(MediaContract.AudioGenres.CONTENT_URI, genresValuesBatch);
|
||||||
|
|
||||||
chainCallSyncAlbums(orchestrator, hostConnection, callbackHandler, contentResolver);
|
chainCallSyncAlbums(orchestrator, hostConnection, callbackHandler, contentResolver,
|
||||||
|
0, new ArrayList<AudioType.DetailsAlbum>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -931,89 +1030,100 @@ public class LibrarySyncService extends Service {
|
||||||
}, callbackHandler);
|
}, callbackHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final String getAlbumsProperties[] = {
|
||||||
|
AudioType.FieldsAlbum.TITLE, AudioType.FieldsAlbum.DESCRIPTION,
|
||||||
|
AudioType.FieldsAlbum.ARTIST, AudioType.FieldsAlbum.GENRE,
|
||||||
|
//AudioType.FieldsAlbum.THEME, AudioType.FieldsAlbum.MOOD,
|
||||||
|
//AudioType.FieldsAlbum.STYLE, AudioType.FieldsAlbum.TYPE,
|
||||||
|
AudioType.FieldsAlbum.ALBUMLABEL, AudioType.FieldsAlbum.RATING,
|
||||||
|
AudioType.FieldsAlbum.YEAR,
|
||||||
|
//AudioType.FieldsAlbum.MUSICBRAINZALBUMID,
|
||||||
|
//AudioType.FieldsAlbum.MUSICBRAINZALBUMARTISTID,
|
||||||
|
AudioType.FieldsAlbum.FANART, AudioType.FieldsAlbum.THUMBNAIL,
|
||||||
|
AudioType.FieldsAlbum.PLAYCOUNT, AudioType.FieldsAlbum.GENREID,
|
||||||
|
AudioType.FieldsAlbum.ARTISTID, AudioType.FieldsAlbum.DISPLAYARTIST
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Syncs Albums and forwards calls to sync songs:
|
* Syncs Albums recursively and forwards calls to sync songs:
|
||||||
* Albums->Songs
|
* Albums->Songs
|
||||||
*/
|
*/
|
||||||
private void chainCallSyncAlbums(final SyncOrchestrator orchestrator,
|
private void chainCallSyncAlbums(final SyncOrchestrator orchestrator,
|
||||||
final HostConnection hostConnection,
|
final HostConnection hostConnection,
|
||||||
final Handler callbackHandler,
|
final Handler callbackHandler,
|
||||||
final ContentResolver contentResolver) {
|
final ContentResolver contentResolver,
|
||||||
String getAlbumsProperties[] = {
|
final int startIdx,
|
||||||
AudioType.FieldsAlbum.TITLE, AudioType.FieldsAlbum.DESCRIPTION,
|
final List<AudioType.DetailsAlbum> allResults) {
|
||||||
AudioType.FieldsAlbum.ARTIST, AudioType.FieldsAlbum.GENRE,
|
|
||||||
//AudioType.FieldsAlbum.THEME, AudioType.FieldsAlbum.MOOD,
|
|
||||||
//AudioType.FieldsAlbum.STYLE, AudioType.FieldsAlbum.TYPE,
|
|
||||||
AudioType.FieldsAlbum.ALBUMLABEL, AudioType.FieldsAlbum.RATING,
|
|
||||||
AudioType.FieldsAlbum.YEAR,
|
|
||||||
//AudioType.FieldsAlbum.MUSICBRAINZALBUMID,
|
|
||||||
//AudioType.FieldsAlbum.MUSICBRAINZALBUMARTISTID,
|
|
||||||
AudioType.FieldsAlbum.FANART, AudioType.FieldsAlbum.THUMBNAIL,
|
|
||||||
AudioType.FieldsAlbum.PLAYCOUNT, AudioType.FieldsAlbum.GENREID,
|
|
||||||
AudioType.FieldsAlbum.ARTISTID, AudioType.FieldsAlbum.DISPLAYARTIST
|
|
||||||
};
|
|
||||||
|
|
||||||
final long albumSyncStartTime = System.currentTimeMillis();
|
final long albumSyncStartTime = System.currentTimeMillis();
|
||||||
// Albums->Songs
|
// Albums->Songs
|
||||||
AudioLibrary.GetAlbums action = new AudioLibrary.GetAlbums(getAlbumsProperties);
|
ListType.Limits limits = new ListType.Limits(startIdx, startIdx + LIMIT_SYNC_ALBUMS);
|
||||||
|
AudioLibrary.GetAlbums action = new AudioLibrary.GetAlbums(limits, getAlbumsProperties);
|
||||||
action.execute(hostConnection, new ApiCallback<List<AudioType.DetailsAlbum>>() {
|
action.execute(hostConnection, new ApiCallback<List<AudioType.DetailsAlbum>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSucess(List<AudioType.DetailsAlbum> result) {
|
public void onSucess(List<AudioType.DetailsAlbum> result) {
|
||||||
ContentValues albumValuesBatch[] = new ContentValues[result.size()];
|
allResults.addAll(result);
|
||||||
|
if (result.size() == LIMIT_SYNC_ALBUMS) {
|
||||||
|
// Max limit returned, there may be some more
|
||||||
|
LogUtils.LOGD(TAG, "chainCallSyncAlbums: More results on media center, recursing.");
|
||||||
|
chainCallSyncAlbums(orchestrator, hostConnection, callbackHandler, contentResolver,
|
||||||
|
startIdx + LIMIT_SYNC_ALBUMS, allResults);
|
||||||
|
} else {
|
||||||
|
// Ok, we have all the shows, insert them
|
||||||
|
LogUtils.LOGD(TAG, "chainCallSyncAlbums: Got all results, continuing");
|
||||||
|
|
||||||
int artistsCount = 0;
|
ContentValues albumValuesBatch[] = new ContentValues[allResults.size()];
|
||||||
int genresCount = 0;
|
int artistsCount = 0;
|
||||||
for (int i = 0; i < result.size(); i++) {
|
int genresCount = 0;
|
||||||
AudioType.DetailsAlbum album = result.get(i);
|
for (int i = 0; i < allResults.size(); i++) {
|
||||||
albumValuesBatch[i] = SyncUtils.contentValuesFromAlbum(hostId, album);
|
AudioType.DetailsAlbum album = allResults.get(i);
|
||||||
|
albumValuesBatch[i] = SyncUtils.contentValuesFromAlbum(hostId, album);
|
||||||
|
|
||||||
artistsCount += album.artistid.size();
|
artistsCount += album.artistid.size();
|
||||||
genresCount += album.genreid.size();
|
genresCount += album.genreid.size();
|
||||||
}
|
|
||||||
|
|
||||||
LogUtils.LOGD(TAG, "Finished parsing albums in: " +
|
|
||||||
(System.currentTimeMillis() - albumSyncStartTime));
|
|
||||||
|
|
||||||
// Insert the albums
|
|
||||||
contentResolver.bulkInsert(MediaContract.Albums.CONTENT_URI, albumValuesBatch);
|
|
||||||
|
|
||||||
LogUtils.LOGD(TAG, "Finished inserting albums in: " +
|
|
||||||
(System.currentTimeMillis() - albumSyncStartTime));
|
|
||||||
|
|
||||||
// Iterate on each album, collect the artists and the genres and insert them
|
|
||||||
ContentValues albumArtistsValuesBatch[] = new ContentValues[artistsCount];
|
|
||||||
ContentValues albumGenresValuesBatch[] = new ContentValues[genresCount];
|
|
||||||
int artistCount = 0, genreCount = 0;
|
|
||||||
for (AudioType.DetailsAlbum album : result) {
|
|
||||||
for (int artistId : album.artistid) {
|
|
||||||
albumArtistsValuesBatch[artistCount] = new ContentValues();
|
|
||||||
albumArtistsValuesBatch[artistCount].put(MediaContract.AlbumArtists.HOST_ID, hostId);
|
|
||||||
albumArtistsValuesBatch[artistCount].put(MediaContract.AlbumArtists.ALBUMID, album.albumid);
|
|
||||||
albumArtistsValuesBatch[artistCount].put(MediaContract.AlbumArtists.ARTISTID, artistId);
|
|
||||||
artistCount++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int genreId : album.genreid) {
|
LogUtils.LOGD(TAG, "Finished parsing albums in: " +
|
||||||
albumGenresValuesBatch[genreCount] = new ContentValues();
|
(System.currentTimeMillis() - albumSyncStartTime));
|
||||||
albumGenresValuesBatch[genreCount].put(MediaContract.AlbumGenres.HOST_ID, hostId);
|
|
||||||
albumGenresValuesBatch[genreCount].put(MediaContract.AlbumGenres.ALBUMID, album.albumid);
|
// Insert the albums
|
||||||
albumGenresValuesBatch[genreCount].put(MediaContract.AlbumGenres.GENREID, genreId);
|
contentResolver.bulkInsert(MediaContract.Albums.CONTENT_URI, albumValuesBatch);
|
||||||
genreCount++;
|
|
||||||
|
LogUtils.LOGD(TAG, "Finished inserting albums in: " +
|
||||||
|
(System.currentTimeMillis() - albumSyncStartTime));
|
||||||
|
|
||||||
|
// Iterate on each album, collect the artists and the genres and insert them
|
||||||
|
ContentValues albumArtistsValuesBatch[] = new ContentValues[artistsCount];
|
||||||
|
ContentValues albumGenresValuesBatch[] = new ContentValues[genresCount];
|
||||||
|
int artistCount = 0, genreCount = 0;
|
||||||
|
for (AudioType.DetailsAlbum album : allResults) {
|
||||||
|
for (int artistId : album.artistid) {
|
||||||
|
albumArtistsValuesBatch[artistCount] = new ContentValues();
|
||||||
|
albumArtistsValuesBatch[artistCount].put(MediaContract.AlbumArtists.HOST_ID, hostId);
|
||||||
|
albumArtistsValuesBatch[artistCount].put(MediaContract.AlbumArtists.ALBUMID, album.albumid);
|
||||||
|
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++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LogUtils.LOGD(TAG, "Finished parsing artists and genres in: " +
|
||||||
|
(System.currentTimeMillis() - albumSyncStartTime));
|
||||||
|
|
||||||
|
contentResolver.bulkInsert(MediaContract.AlbumArtists.CONTENT_URI, albumArtistsValuesBatch);
|
||||||
|
contentResolver.bulkInsert(MediaContract.AlbumGenres.CONTENT_URI, albumGenresValuesBatch);
|
||||||
|
|
||||||
|
LogUtils.LOGD(TAG, "Finished inserting artists and genres in: " +
|
||||||
|
(System.currentTimeMillis() - albumSyncStartTime));
|
||||||
|
chainCallSyncSongs(orchestrator, hostConnection, callbackHandler, contentResolver,
|
||||||
|
0, new ArrayList<AudioType.DetailsSong>());
|
||||||
}
|
}
|
||||||
|
|
||||||
LogUtils.LOGD(TAG, "Finished parsing artists and genres in: " +
|
|
||||||
(System.currentTimeMillis() - albumSyncStartTime));
|
|
||||||
|
|
||||||
contentResolver.bulkInsert(MediaContract.AlbumArtists.CONTENT_URI, albumArtistsValuesBatch);
|
|
||||||
contentResolver.bulkInsert(MediaContract.AlbumGenres.CONTENT_URI, albumGenresValuesBatch);
|
|
||||||
|
|
||||||
LogUtils.LOGD(TAG, "Finished inserting artists and genres in: " +
|
|
||||||
(System.currentTimeMillis() - albumSyncStartTime));
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: Continue to sync songs?
|
|
||||||
chainCallSyncSongs(orchestrator, hostConnection, callbackHandler, contentResolver);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1024,50 +1134,62 @@ public class LibrarySyncService extends Service {
|
||||||
}, callbackHandler);
|
}, callbackHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final String getSongsProperties[] = {
|
||||||
|
AudioType.FieldsSong.TITLE,
|
||||||
|
//AudioType.FieldsSong.ARTIST, AudioType.FieldsSong.ALBUMARTIST, AudioType.FieldsSong.GENRE,
|
||||||
|
//AudioType.FieldsSong.YEAR, AudioType.FieldsSong.RATING,
|
||||||
|
//AudioType.FieldsSong.ALBUM,
|
||||||
|
AudioType.FieldsSong.TRACK, AudioType.FieldsSong.DURATION,
|
||||||
|
//AudioType.FieldsSong.COMMENT, AudioType.FieldsSong.LYRICS,
|
||||||
|
//AudioType.FieldsSong.MUSICBRAINZTRACKID,
|
||||||
|
//AudioType.FieldsSong.MUSICBRAINZARTISTID,
|
||||||
|
//AudioType.FieldsSong.MUSICBRAINZALBUMID,
|
||||||
|
//AudioType.FieldsSong.MUSICBRAINZALBUMARTISTID,
|
||||||
|
//AudioType.FieldsSong.PLAYCOUNT, AudioType.FieldsSong.FANART,
|
||||||
|
AudioType.FieldsSong.THUMBNAIL, AudioType.FieldsSong.FILE,
|
||||||
|
AudioType.FieldsSong.ALBUMID,
|
||||||
|
//AudioType.FieldsSong.LASTPLAYED, AudioType.FieldsSong.DISC,
|
||||||
|
//AudioType.FieldsSong.GENREID, AudioType.FieldsSong.ARTISTID,
|
||||||
|
//AudioType.FieldsSong.DISPLAYARTIST, AudioType.FieldsSong.ALBUMARTISTID
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Syncs songs and stops
|
* Syncs songs and stops
|
||||||
*/
|
*/
|
||||||
private void chainCallSyncSongs(final SyncOrchestrator orchestrator,
|
private void chainCallSyncSongs(final SyncOrchestrator orchestrator,
|
||||||
final HostConnection hostConnection,
|
final HostConnection hostConnection,
|
||||||
final Handler callbackHandler,
|
final Handler callbackHandler,
|
||||||
final ContentResolver contentResolver) {
|
final ContentResolver contentResolver,
|
||||||
String getSongsProperties[] = {
|
final int startIdx,
|
||||||
AudioType.FieldsSong.TITLE,
|
final List<AudioType.DetailsSong> allResults) {
|
||||||
//AudioType.FieldsSong.ARTIST, AudioType.FieldsSong.ALBUMARTIST, AudioType.FieldsSong.GENRE,
|
|
||||||
//AudioType.FieldsSong.YEAR, AudioType.FieldsSong.RATING,
|
|
||||||
//AudioType.FieldsSong.ALBUM,
|
|
||||||
AudioType.FieldsSong.TRACK, AudioType.FieldsSong.DURATION,
|
|
||||||
//AudioType.FieldsSong.COMMENT, AudioType.FieldsSong.LYRICS,
|
|
||||||
//AudioType.FieldsSong.MUSICBRAINZTRACKID,
|
|
||||||
//AudioType.FieldsSong.MUSICBRAINZARTISTID,
|
|
||||||
//AudioType.FieldsSong.MUSICBRAINZALBUMID,
|
|
||||||
//AudioType.FieldsSong.MUSICBRAINZALBUMARTISTID,
|
|
||||||
//AudioType.FieldsSong.PLAYCOUNT, AudioType.FieldsSong.FANART,
|
|
||||||
AudioType.FieldsSong.THUMBNAIL, AudioType.FieldsSong.FILE,
|
|
||||||
AudioType.FieldsSong.ALBUMID,
|
|
||||||
//AudioType.FieldsSong.LASTPLAYED, AudioType.FieldsSong.DISC,
|
|
||||||
//AudioType.FieldsSong.GENREID, AudioType.FieldsSong.ARTISTID,
|
|
||||||
//AudioType.FieldsSong.DISPLAYARTIST, AudioType.FieldsSong.ALBUMARTISTID
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Songs
|
// Songs
|
||||||
AudioLibrary.GetSongs action = new AudioLibrary.GetSongs(getSongsProperties);
|
ListType.Limits limits = new ListType.Limits(startIdx, startIdx + LIMIT_SYNC_SONGS);
|
||||||
|
AudioLibrary.GetSongs action = new AudioLibrary.GetSongs(limits, getSongsProperties);
|
||||||
action.execute(hostConnection, new ApiCallback<List<AudioType.DetailsSong>>() {
|
action.execute(hostConnection, new ApiCallback<List<AudioType.DetailsSong>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSucess(List<AudioType.DetailsSong> result) {
|
public void onSucess(List<AudioType.DetailsSong> result) {
|
||||||
LogUtils.LOGD(TAG, "GetSongs result size: " + result.size());
|
allResults.addAll(result);
|
||||||
ContentValues songValuesBatch[] = new ContentValues[result.size()];
|
if (result.size() == LIMIT_SYNC_SONGS) {
|
||||||
|
// Max limit returned, there may be some more
|
||||||
|
LogUtils.LOGD(TAG, "chainCallSyncSongs: More results on media center, recursing.");
|
||||||
|
chainCallSyncSongs(orchestrator, hostConnection, callbackHandler, contentResolver,
|
||||||
|
startIdx + LIMIT_SYNC_SONGS, allResults);
|
||||||
|
} else {
|
||||||
|
// Ok, we have all the songs, insert them
|
||||||
|
LogUtils.LOGD(TAG, "chainCallSyncSongs: Got all results, continuing");
|
||||||
|
|
||||||
for (int i = 0; i < result.size(); i++) {
|
ContentValues songValuesBatch[] = new ContentValues[allResults.size()];
|
||||||
AudioType.DetailsSong song = result.get(i);
|
|
||||||
songValuesBatch[i] = SyncUtils.contentValuesFromSong(hostId, song);
|
for (int i = 0; i < allResults.size(); i++) {
|
||||||
|
AudioType.DetailsSong song = allResults.get(i);
|
||||||
|
songValuesBatch[i] = SyncUtils.contentValuesFromSong(hostId, song);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert the songs
|
||||||
|
contentResolver.bulkInsert(MediaContract.Songs.CONTENT_URI, songValuesBatch);
|
||||||
|
|
||||||
|
orchestrator.syncItemFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert the songs
|
|
||||||
contentResolver.bulkInsert(MediaContract.Songs.CONTENT_URI, songValuesBatch);
|
|
||||||
|
|
||||||
orchestrator.syncItemFinished();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue