* use TV Series index only for TV-mode and Anime index only for Anime-mode

This commit is contained in:
Reinhard Pointner 2014-01-08 09:28:04 +00:00
parent c4ab4e8382
commit ef2a64003b
5 changed files with 62 additions and 22 deletions

View File

@ -41,7 +41,6 @@ import net.sourceforge.filebot.HistorySpooler;
import net.sourceforge.filebot.Language; import net.sourceforge.filebot.Language;
import net.sourceforge.filebot.MediaTypes; import net.sourceforge.filebot.MediaTypes;
import net.sourceforge.filebot.RenameAction; import net.sourceforge.filebot.RenameAction;
import net.sourceforge.filebot.WebServices;
import net.sourceforge.filebot.archive.Archive; import net.sourceforge.filebot.archive.Archive;
import net.sourceforge.filebot.archive.FileMapper; import net.sourceforge.filebot.archive.FileMapper;
import net.sourceforge.filebot.format.ExpressionFilter; import net.sourceforge.filebot.format.ExpressionFilter;
@ -130,9 +129,9 @@ public class CmdlineOperations implements CmdlineInterface {
CLILogger.finest(format("Filename pattern: [%.02f] SxE, [%.02f] CWS", sxe / max, cws / max)); CLILogger.finest(format("Filename pattern: [%.02f] SxE, [%.02f] CWS", sxe / max, cws / max));
if (sxe > (max * 0.65) || cws > (max * 0.65)) { if (sxe > (max * 0.65) || cws > (max * 0.65)) {
return renameSeries(files, action, conflictAction, outputDir, format, WebServices.TheTVDB, query, SortOrder.forName(sortOrder), filter, locale, strict); // use default episode db return renameSeries(files, action, conflictAction, outputDir, format, TheTVDB, query, SortOrder.forName(sortOrder), filter, locale, strict); // use default episode db
} else { } else {
return renameMovie(files, action, conflictAction, outputDir, format, WebServices.TMDb, query, filter, locale, strict); // use default movie db return renameMovie(files, action, conflictAction, outputDir, format, TMDb, query, filter, locale, strict); // use default movie db
} }
} }
@ -151,7 +150,7 @@ public class CmdlineOperations implements CmdlineInterface {
List<Match<File, ?>> matches = new ArrayList<Match<File, ?>>(); List<Match<File, ?>> matches = new ArrayList<Match<File, ?>>();
// auto-determine optimal batch sets // auto-determine optimal batch sets
for (Entry<Set<File>, Set<String>> sameSeriesGroup : mapSeriesNamesByFiles(mediaFiles, locale).entrySet()) { for (Entry<Set<File>, Set<String>> sameSeriesGroup : mapSeriesNamesByFiles(mediaFiles, locale, db != AniDB, db == AniDB).entrySet()) {
List<List<File>> batchSets = new ArrayList<List<File>>(); List<List<File>> batchSets = new ArrayList<List<File>>();
if (sameSeriesGroup.getValue() != null && sameSeriesGroup.getValue().size() > 0) { if (sameSeriesGroup.getValue() != null && sameSeriesGroup.getValue().size() > 0) {
@ -168,7 +167,7 @@ public class CmdlineOperations implements CmdlineInterface {
// auto-detect series name if not given // auto-detect series name if not given
if (query == null) { if (query == null) {
// detect series name by common word sequence // detect series name by common word sequence
seriesNames = detectSeriesNames(batch, locale); seriesNames = detectSeriesNames(batch, locale, db != AniDB, db == AniDB);
CLILogger.config("Auto-detected query: " + seriesNames); CLILogger.config("Auto-detected query: " + seriesNames);
} else { } else {
// use --q option // use --q option
@ -663,7 +662,7 @@ public class CmdlineOperations implements CmdlineInterface {
} }
// lookup subtitles by hash // lookup subtitles by hash
for (VideoHashSubtitleService service : WebServices.getVideoHashSubtitleServices()) { for (VideoHashSubtitleService service : getVideoHashSubtitleServices()) {
if (remainingVideos.isEmpty() || (databaseFilter != null && !databaseFilter.matcher(service.getName()).matches())) { if (remainingVideos.isEmpty() || (databaseFilter != null && !databaseFilter.matcher(service.getName()).matches())) {
continue; continue;
} }
@ -687,7 +686,7 @@ public class CmdlineOperations implements CmdlineInterface {
if (query == null) { if (query == null) {
try { try {
List<File> videoFiles = filter(files, VIDEO_FILES); List<File> videoFiles = filter(files, VIDEO_FILES);
querySet.addAll(detectSeriesNames(videoFiles, language.getLocale())); querySet.addAll(detectSeriesNames(videoFiles, language.getLocale(), true, false));
// auto-detect movie names // auto-detect movie names
for (File f : videoFiles) { for (File f : videoFiles) {
@ -708,7 +707,7 @@ public class CmdlineOperations implements CmdlineInterface {
querySet.add(query); querySet.add(query);
} }
for (SubtitleProvider service : WebServices.getSubtitleProviders()) { for (SubtitleProvider service : getSubtitleProviders()) {
if (remainingVideos.isEmpty() || (databaseFilter != null && !databaseFilter.matcher(service.getName()).matches())) { if (remainingVideos.isEmpty() || (databaseFilter != null && !databaseFilter.matcher(service.getName()).matches())) {
continue; continue;
} }

View File

@ -134,14 +134,14 @@ public class MediaDetection {
return new DateMetric().parse(object); return new DateMetric().parse(object);
} }
public static Map<Set<File>, Set<String>> mapSeriesNamesByFiles(Collection<File> files, Locale locale) throws Exception { public static Map<Set<File>, Set<String>> mapSeriesNamesByFiles(Collection<File> files, Locale locale, boolean useSeriesIndex, boolean useAnimeIndex) throws Exception {
// map series names by folder // map series names by folder
Map<File, Set<String>> seriesNamesByFolder = new HashMap<File, Set<String>>(); Map<File, Set<String>> seriesNamesByFolder = new HashMap<File, Set<String>>();
Map<File, List<File>> filesByFolder = mapByFolder(files); Map<File, List<File>> filesByFolder = mapByFolder(files);
for (Entry<File, List<File>> it : filesByFolder.entrySet()) { for (Entry<File, List<File>> it : filesByFolder.entrySet()) {
Set<String> namesForFolder = new TreeSet<String>(getLenientCollator(locale)); Set<String> namesForFolder = new TreeSet<String>(getLenientCollator(locale));
namesForFolder.addAll(detectSeriesNames(it.getValue(), locale)); namesForFolder.addAll(detectSeriesNames(it.getValue(), locale, useSeriesIndex, useAnimeIndex));
seriesNamesByFolder.put(it.getKey(), namesForFolder); seriesNamesByFolder.put(it.getKey(), namesForFolder);
} }
@ -271,6 +271,20 @@ public class MediaDetection {
} }
public static List<String> detectSeriesNames(Collection<File> files, Locale locale) throws Exception { public static List<String> detectSeriesNames(Collection<File> files, Locale locale) throws Exception {
return detectSeriesNames(files, locale, true, true);
}
public static List<String> detectSeriesNames(Collection<File> files, Locale locale, boolean useSeriesIndex, boolean useAnimeIndex) throws Exception {
List<IndexEntry<SearchResult>> index = new ArrayList<IndexEntry<SearchResult>>();
if (useSeriesIndex)
index.addAll(getSeriesIndex());
if (useAnimeIndex)
index.addAll(getAnimeIndex());
return detectSeriesNames(files, locale, index);
}
public static List<String> detectSeriesNames(Collection<File> files, Locale locale, List<IndexEntry<SearchResult>> seriesIndex) throws Exception {
List<String> names = new ArrayList<String>(); List<String> names = new ArrayList<String>();
// try xattr metadata if enabled // try xattr metadata if enabled
@ -400,16 +414,15 @@ public class MediaDetection {
return matches; return matches;
} }
private static final List<IndexEntry<SearchResult>> seriesIndex = new ArrayList<IndexEntry<SearchResult>>(100000); private static final ArrayList<IndexEntry<SearchResult>> seriesIndex = new ArrayList<IndexEntry<SearchResult>>(0);
public static List<IndexEntry<SearchResult>> getSeriesIndex() throws IOException { public static List<IndexEntry<SearchResult>> getSeriesIndex() throws IOException {
synchronized (seriesIndex) { synchronized (seriesIndex) {
if (seriesIndex.isEmpty()) { if (seriesIndex.isEmpty()) {
seriesIndex.ensureCapacity(100000);
try { try {
for (SearchResult[] index : new SearchResult[][] { releaseInfo.getTheTVDBIndex(), releaseInfo.getAnidbIndex() }) { for (SearchResult it : releaseInfo.getTheTVDBIndex()) {
for (SearchResult it : index) { seriesIndex.addAll(HighPerformanceMatcher.prepare(it));
seriesIndex.addAll(HighPerformanceMatcher.prepare(it));
}
} }
} catch (Exception e) { } catch (Exception e) {
// can't load movie index, just try again next time // can't load movie index, just try again next time
@ -423,6 +436,28 @@ public class MediaDetection {
} }
} }
private static final ArrayList<IndexEntry<SearchResult>> animeIndex = new ArrayList<IndexEntry<SearchResult>>(0);
public static List<IndexEntry<SearchResult>> getAnimeIndex() throws IOException {
synchronized (animeIndex) {
if (animeIndex.isEmpty()) {
animeIndex.ensureCapacity(50000);
try {
for (SearchResult it : releaseInfo.getAnidbIndex()) {
animeIndex.addAll(HighPerformanceMatcher.prepare(it));
}
} catch (Exception e) {
// can't load movie index, just try again next time
Logger.getLogger(MediaDetection.class.getClass().getName()).log(Level.SEVERE, "Failed to load anime index: " + e.getMessage(), e);
// rely on online search
return emptyList();
}
}
return animeIndex;
}
}
public static List<String> matchSeriesByName(Collection<String> files, int maxStartIndex) throws Exception { public static List<String> matchSeriesByName(Collection<String> files, int maxStartIndex) throws Exception {
HighPerformanceMatcher nameMatcher = new HighPerformanceMatcher(maxStartIndex); HighPerformanceMatcher nameMatcher = new HighPerformanceMatcher(maxStartIndex);
List<String> matches = new ArrayList<String>(); List<String> matches = new ArrayList<String>();
@ -755,11 +790,12 @@ public class MediaDetection {
return matches != null && matches.size() > 0 ? matches.get(0) : null; return matches != null && matches.size() > 0 ? matches.get(0) : null;
} }
private static final List<IndexEntry<Movie>> movieIndex = new ArrayList<IndexEntry<Movie>>(100000); private static final ArrayList<IndexEntry<Movie>> movieIndex = new ArrayList<IndexEntry<Movie>>(0);
public static List<IndexEntry<Movie>> getMovieIndex() throws IOException { public static List<IndexEntry<Movie>> getMovieIndex() throws IOException {
synchronized (movieIndex) { synchronized (movieIndex) {
if (movieIndex.isEmpty()) { if (movieIndex.isEmpty()) {
movieIndex.ensureCapacity(100000);
try { try {
for (Movie it : releaseInfo.getMovieList()) { for (Movie it : releaseInfo.getMovieList()) {
movieIndex.addAll(HighPerformanceMatcher.prepare(it)); movieIndex.addAll(HighPerformanceMatcher.prepare(it));

View File

@ -50,11 +50,16 @@ class EpisodeListMatcher implements AutoCompleteMatcher {
private final EpisodeListProvider provider; private final EpisodeListProvider provider;
private boolean useAnimeIndex;
private boolean useSeriesIndex;
// only allow one fetch session at a time so later requests can make use of cached results // only allow one fetch session at a time so later requests can make use of cached results
private final Object providerLock = new Object(); private final Object providerLock = new Object();
public EpisodeListMatcher(EpisodeListProvider provider) { public EpisodeListMatcher(EpisodeListProvider provider, boolean useSeriesIndex, boolean useAnimeIndex) {
this.provider = provider; this.provider = provider;
this.useSeriesIndex = useSeriesIndex;
this.useAnimeIndex = useAnimeIndex;
} }
protected SearchResult selectSearchResult(final String query, final List<SearchResult> searchResults, Map<String, SearchResult> selectionMemory, final Component parent) throws Exception { protected SearchResult selectSearchResult(final String query, final List<SearchResult> searchResults, Map<String, SearchResult> selectionMemory, final Component parent) throws Exception {
@ -180,7 +185,7 @@ class EpisodeListMatcher implements AutoCompleteMatcher {
final Map<String, List<String>> inputMemory = new TreeMap<String, List<String>>(CommonSequenceMatcher.getLenientCollator(Locale.ROOT)); final Map<String, List<String>> inputMemory = new TreeMap<String, List<String>>(CommonSequenceMatcher.getLenientCollator(Locale.ROOT));
// detect series names and create episode list fetch tasks // detect series names and create episode list fetch tasks
for (Entry<Set<File>, Set<String>> sameSeriesGroup : mapSeriesNamesByFiles(mediaFiles, locale).entrySet()) { for (Entry<Set<File>, Set<String>> sameSeriesGroup : mapSeriesNamesByFiles(mediaFiles, locale, useSeriesIndex, useAnimeIndex).entrySet()) {
final List<List<File>> batchSets = new ArrayList<List<File>>(); final List<List<File>> batchSets = new ArrayList<List<File>>();
final Collection<String> queries = sameSeriesGroup.getValue(); final Collection<String> queries = sameSeriesGroup.getValue();
@ -265,7 +270,7 @@ class EpisodeListMatcher implements AutoCompleteMatcher {
// require user input if auto-detection has failed or has been disabled // require user input if auto-detection has failed or has been disabled
if (episodes.isEmpty()) { if (episodes.isEmpty()) {
List<String> detectedSeriesNames = detectSeriesNames(files, locale); List<String> detectedSeriesNames = detectSeriesNames(files, locale, useSeriesIndex, useAnimeIndex);
String parentPathHint = normalizePathSeparators(getRelativePathTail(files.get(0).getParentFile(), 2).getPath()); String parentPathHint = normalizePathSeparators(getRelativePathTail(files.get(0).getParentFile(), 2).getPath());
String suggestion = detectedSeriesNames.size() > 0 ? join(detectedSeriesNames, ", ") : parentPathHint; String suggestion = detectedSeriesNames.size() > 0 ? join(detectedSeriesNames, ", ") : parentPathHint;

View File

@ -288,8 +288,8 @@ public class RenamePanel extends JComponent {
actionPopup.addDescription(new JLabel("Episode Mode:")); actionPopup.addDescription(new JLabel("Episode Mode:"));
// create actions for match popup episode list completion // create actions for match popup episode list completion
for (EpisodeListProvider provider : WebServices.getEpisodeListProviders()) { for (EpisodeListProvider db : WebServices.getEpisodeListProviders()) {
actionPopup.add(new AutoCompleteAction(provider.getName(), provider.getIcon(), new EpisodeListMatcher(provider))); actionPopup.add(new AutoCompleteAction(db.getName(), db.getIcon(), new EpisodeListMatcher(db, db != WebServices.AniDB, db == WebServices.AniDB)));
} }
actionPopup.addSeparator(); actionPopup.addSeparator();

View File

@ -935,7 +935,7 @@ class SubtitleAutoMatchDialog extends JDialog {
Collection<String> querySet = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER); Collection<String> querySet = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
// auto-detect series names // auto-detect series names
querySet.addAll(detectSeriesNames(files, Locale.ROOT)); querySet.addAll(detectSeriesNames(files, Locale.ROOT, true, false));
// auto-detect movie names // auto-detect movie names
for (File f : files) { for (File f : files) {