/** * Manual refresh, displays a dialog. * * @param bAsk ask for refreshing type (deep or fast ?) * @param bAfterMove is this refresh done after a device location change ? * @param forcedDeep : override bAsk and force a deep refresh * @param dirsToRefresh : only refresh specified dirs, or all of them if null */ public void manualRefresh( final boolean bAsk, final boolean bAfterMove, final boolean forcedDeep, List<Directory> dirsToRefresh) { int i = 0; try { i = prepareRefresh(bAsk); if (i == OPTION_REFRESH_CANCEL) { return; } bAlreadyRefreshing = true; } catch (JajukException je) { Messages.showErrorMessage(je.getCode()); Log.debug(je); return; } try { reporter = new ManualDeviceRefreshReporter(this); reporter.startup(); // clean old files up (takes a while) if (!bAfterMove) { cleanRemovedFiles(dirsToRefresh); } reporter.cleanupDone(); // Actual refresh refreshCommand(((i == Device.OPTION_REFRESH_DEEP) || forcedDeep), true, dirsToRefresh); // cleanup logical items org.jajuk.base.Collection.cleanupLogical(); // if it is a move, clean old files *after* the refresh if (bAfterMove) { cleanRemovedFiles(dirsToRefresh); } // notify views to refresh ObservationManager.notify(new JajukEvent(JajukEvents.DEVICE_REFRESH)); // Commit collection at each refresh (can be useful if // application // is closed brutally with control-C or shutdown and that // exit hook has no time to perform commit). // But don't commit when any device is refreshing to avoid collisions. if (!DeviceManager.getInstance().isAnyDeviceRefreshing()) { try { org.jajuk.base.Collection.commit(SessionService.getConfFileByPath(Const.FILE_COLLECTION)); } catch (final IOException e) { Log.error(e); } } } finally { // Do not let current reporter as a manual reporter because it would fail // in NPE with auto-refresh reporter = null; // Make sure to unlock refreshing bAlreadyRefreshing = false; } }
/** * Walk through tall Files and remove the ones for the current device. * * @param dirsToRefresh list of the directory to refresh, null if all of them * @return true if there was any file removed. */ private boolean cleanFiles(List<Directory> dirsToRefresh) { boolean bChanges = false; final List<org.jajuk.base.File> files = FileManager.getInstance().getFiles(); for (final org.jajuk.base.File file : files) { // check if it is a file located inside refreshed directory if (dirsToRefresh != null) { boolean checkIt = false; for (Directory directory : dirsToRefresh) { if (file.hasAncestor(directory)) { checkIt = true; } } // This item is not in given directories, just continue if (!checkIt) { continue; } } if (!ExitService.isExiting() && file.getDirectory().getDevice().equals(this) && file.isReady() && // Remove file if it doesn't exist any more or if it is a iTunes // file (useful for jajuk < 1.4) (!file.getFIO().exists() || file.getName().startsWith("._"))) { FileManager.getInstance().removeFile(file); Log.debug("Removed: " + file); bChanges = true; if (reporter != null) { reporter.notifyFileOrPlaylistDropped(); } } } return bChanges; }
/** * Walk through all Playlists and remove the ones for the current device. * * @param dirsToRefresh list of the directory to refresh, null if all of them * @return true if there was any playlist removed */ private boolean cleanPlaylist(List<Directory> dirsToRefresh) { boolean bChanges = false; final List<Playlist> plfiles = PlaylistManager.getInstance().getPlaylists(); for (final Playlist plf : plfiles) { // check if it is a playlist located inside refreshed directory if (dirsToRefresh != null) { boolean checkIt = false; for (Directory directory : dirsToRefresh) { if (plf.hasAncestor(directory)) { checkIt = true; } } // This item is not in given directories, just continue if (!checkIt) { continue; } } if (!ExitService.isExiting() && plf.getDirectory().getDevice().equals(this) && plf.isReady() && !plf.getFIO().exists()) { PlaylistManager.getInstance().removeItem(plf); Log.debug("Removed: " + plf); if (reporter != null) { reporter.notifyFileOrPlaylistDropped(); } bChanges = true; } } return bChanges; }
/** * Scan recursively. * * @param dir top directory to scan * @param bDeepScan whether we want to perform a deep scan (read tags again) */ private void scanRecursively(final Directory dir, final boolean bDeepScan) { dir.scan(bDeepScan, reporter); if (reporter != null) { reporter.updateState(dir); } final File[] files = dir.getFio().listFiles(UtilSystem.getDirFilter()); if (files != null) { for (final File element : files) { // Leave ASAP if exit request if (ExitService.isExiting()) { return; } final Directory subDir = DirectoryManager.getInstance().registerDirectory(element.getName(), dir, this); scanRecursively(subDir, bDeepScan); } } }
/** * The refresh itself. * * @param bDeepScan whether it is a deep refresh request or only fast * @param bManual whether it is a manual refresh or auto * @param dirsToRefresh list of the directory to refresh, null if all of them * @return true if some changes occurred in device */ boolean refreshCommand( final boolean bDeepScan, final boolean bManual, List<Directory> dirsToRefresh) { try { // Check if this device is mounted (useful when called by // automatic refresh) if (!isMounted()) { return false; } // Check that device is still available boolean readyToMount = checkDevice(); if (!readyToMount) { return false; } bAlreadyRefreshing = true; // reporter is already set in case of manual refresh if (reporter == null) { reporter = new RefreshReporter(this); } // Notify the reporter of the actual refresh startup reporter.refreshStarted(); lDateLastRefresh = System.currentTimeMillis(); // check Jajuk is not exiting because a refresh cannot start in // this state if (ExitService.isExiting()) { return false; } int iNbFilesBeforeRefresh = FileManager.getInstance().getElementCount(); int iNbDirsBeforeRefresh = DirectoryManager.getInstance().getElementCount(); int iNbPlaylistsBeforeRefresh = PlaylistManager.getInstance().getElementCount(); if (bDeepScan && Log.isDebugEnabled()) { Log.debug("Starting refresh of device : " + this); } // Create a directory for device itself and scan files to allow // files at the root of the device final Directory top = DirectoryManager.getInstance().registerDirectory(this); if (!getDirectories().contains(top)) { addDirectory(top); } // Start actual scan List<Directory> dirs = null; if (dirsToRefresh == null) { // No directory specified ? refresh the top directory dirs = new ArrayList<Directory>(1); dirs.add(top); } else { dirs = dirsToRefresh; } for (Directory dir : dirs) { scanRecursively(dir, bDeepScan); } // Force a GUI refresh if new files or directories discovered or have been // removed if (((FileManager.getInstance().getElementCount() - iNbFilesBeforeRefresh) != 0) || ((DirectoryManager.getInstance().getElementCount() - iNbDirsBeforeRefresh) != 0) || ((PlaylistManager.getInstance().getElementCount() - iNbPlaylistsBeforeRefresh) != 0)) { return true; } return false; } catch (final Exception e) { // and regular ones logged Log.error(e); return false; } finally { // make sure to unlock refreshing even if an error occurred bAlreadyRefreshing = false; // reporter is null if mount is not mounted due to early return if (reporter != null) { // Notify the reporter of the actual refresh startup reporter.done(); // Reset the reporter as next time, it could be another type reporter = null; } } }