/* This file is part of Subsonic. Subsonic is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Subsonic is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Subsonic. If not, see <http://www.gnu.org/licenses/>. Copyright 2009 (C) Sindre Mehus */ package github.daneren2005.dsub.service.sync; import android.annotation.TargetApi; import android.content.Context; import android.util.Log; import java.io.File; import java.util.ArrayList; import java.util.List; import github.daneren2005.dsub.R; import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.domain.Playlist; import github.daneren2005.dsub.service.DownloadFile; import github.daneren2005.dsub.service.parser.SubsonicRESTException; import github.daneren2005.dsub.util.FileUtil; import github.daneren2005.dsub.util.Notifications; import github.daneren2005.dsub.util.SyncUtil; import github.daneren2005.dsub.util.SyncUtil.SyncSet; import github.daneren2005.dsub.util.Util; /** * Created by Scott on 8/28/13. */ public class PlaylistSyncAdapter extends SubsonicSyncAdapter { private static String TAG = PlaylistSyncAdapter.class.getSimpleName(); // Update playlists every day to make sure they are still valid private static int MAX_PLAYLIST_AGE = 24; public PlaylistSyncAdapter(Context context, boolean autoInitialize) { super(context, autoInitialize); } @TargetApi(14) public PlaylistSyncAdapter(Context context, boolean autoInitialize, boolean allowParallelSyncs) { super(context, autoInitialize, allowParallelSyncs); } @Override public void onExecuteSync(Context context, int instance) throws NetworkNotValidException { String serverName = Util.getServerName(context, instance); List<Playlist> remainder = null; try { // Just update playlist listings so user doesn't have to remainder = musicService.getPlaylists(true, context, null); } catch(Exception e) { Log.e(TAG, "Failed to refresh playlist list for " + serverName); } ArrayList<SyncSet> playlistList = SyncUtil.getSyncedPlaylists(context, instance); List<String> updated = new ArrayList<String>(); String updatedId = null; boolean removed = false; for(int i = 0; i < playlistList.size(); i++) { SyncSet cachedPlaylist = playlistList.get(i); String id = cachedPlaylist.id; // Remove playlist from remainder list if(remainder != null) { remainder.remove(new Playlist(id, "")); } try { MusicDirectory playlist = musicService.getPlaylist(true, id, serverName, context, null); // Get list of original paths List<String> origPathList = new ArrayList<String>(); if(cachedPlaylist.synced != null) { origPathList.addAll(cachedPlaylist.synced); } else { cachedPlaylist.synced = new ArrayList<String>(); } for(MusicDirectory.Entry entry: playlist.getChildren()) { DownloadFile file = new DownloadFile(context, entry, true); String path = file.getCompleteFile().getPath(); while(!file.isSaved() && !file.isFailedMax()) { throwIfNetworkInvalid(); file.downloadNow(musicService); if(file.isSaved() && !updated.contains(playlist.getName())) { updated.add(playlist.getName()); if(updatedId == null) { updatedId = playlist.getId(); } } } // Add to cached path set if saved if(file.isSaved() && !cachedPlaylist.synced.contains(path)) { cachedPlaylist.synced.add(path); } origPathList.remove(path); } // Check to unpin all paths which are no longer in playlist if(origPathList.size() > 0) { for(String path: origPathList) { File saveFile = new File(path); FileUtil.unpinSong(context, saveFile); cachedPlaylist.synced.remove(path); } removed = true; } } catch(SubsonicRESTException e) { if(e.getCode() == 70) { SyncUtil.removeSyncedPlaylist(context, id, instance); Log.i(TAG, "Unsync deleted playlist " + id + " for " + serverName); } } catch(Exception e) { Log.e(TAG, "Failed to get playlist " + id + " for " + serverName, e); } if(updated.size() > 0 || removed) { SyncUtil.setSyncedPlaylists(context, instance, playlistList); } } // For remaining playlists, check to make sure they have been updated recently if(remainder != null) { for (Playlist playlist : remainder) { MusicDirectory dir = FileUtil.deserialize(context, Util.getCacheName(context, instance, "playlist", playlist.getId()), MusicDirectory.class, MAX_PLAYLIST_AGE); if (dir == null) { try { musicService.getPlaylist(true, playlist.getId(), serverName, context, null); } catch(Exception e) { Log.w(TAG, "Failed to update playlist for " + playlist.getName()); } } } } if(updated.size() > 0) { Notifications.showSyncNotification(context, R.string.sync_new_playlists, SyncUtil.joinNames(updated), updatedId); } } }