diff --git a/source/net/filebot/WebServices.java b/source/net/filebot/WebServices.java index d70c8ba0..b0038444 100644 --- a/source/net/filebot/WebServices.java +++ b/source/net/filebot/WebServices.java @@ -22,7 +22,7 @@ import java.util.concurrent.Future; import java.util.logging.Level; import java.util.stream.Stream; -import net.filebot.media.XattrMetaInfoProvider; +import net.filebot.media.LocalDatasource; import net.filebot.similarity.MetricAvg; import net.filebot.web.AcoustIDClient; import net.filebot.web.AnidbClient; @@ -70,11 +70,10 @@ public final class WebServices { // other sources public static final FanartTVClient FanartTV = new FanartTVClient(getApiKey("fanart.tv")); public static final AcoustIDClient AcoustID = new AcoustIDClient(getApiKey("acoustid")); - public static final XattrMetaInfoProvider XattrMetaData = new XattrMetaInfoProvider(); public static final ID3Lookup MediaInfoID3 = new ID3Lookup(); public static Datasource[] getServices() { - return new Datasource[] { TheMovieDB, OMDb, TheTVDB, AniDB, TheMovieDB_TV, TVmaze, AcoustID, MediaInfoID3, XattrMetaData, OpenSubtitles, Shooter, FanartTV }; + return new Datasource[] { TheMovieDB, OMDb, TheTVDB, AniDB, TheMovieDB_TV, TVmaze, AcoustID, MediaInfoID3, LocalDatasource.EXIF, LocalDatasource.XATTR, LocalDatasource.FILE, OpenSubtitles, Shooter, FanartTV }; } public static MovieIdentificationService[] getMovieIdentificationServices() { @@ -89,6 +88,10 @@ public final class WebServices { return new MusicIdentificationService[] { AcoustID, MediaInfoID3 }; } + public static LocalDatasource[] getLocalDatasources() { + return new LocalDatasource[] { LocalDatasource.EXIF, LocalDatasource.XATTR, LocalDatasource.FILE }; + } + public static SubtitleProvider[] getSubtitleProviders(Locale locale) { return new SubtitleProvider[] { OpenSubtitles }; } diff --git a/source/net/filebot/cli/CmdlineOperations.java b/source/net/filebot/cli/CmdlineOperations.java index fb2b1e36..21e636de 100644 --- a/source/net/filebot/cli/CmdlineOperations.java +++ b/source/net/filebot/cli/CmdlineOperations.java @@ -55,8 +55,8 @@ import net.filebot.hash.VerificationFileWriter; import net.filebot.media.AutoDetection; import net.filebot.media.AutoDetection.Group; import net.filebot.media.AutoDetection.Type; +import net.filebot.media.LocalDatasource; import net.filebot.media.VideoQuality; -import net.filebot.media.XattrMetaInfoProvider; import net.filebot.similarity.CommonSequenceMatcher; import net.filebot.similarity.EpisodeMatcher; import net.filebot.similarity.Match; @@ -101,9 +101,9 @@ public class CmdlineOperations implements CmdlineInterface { return renameMusic(files, action, conflict, output, format, singletonList((MusicIdentificationService) db), exec); } - // generic file / xattr mode - if (db instanceof XattrMetaInfoProvider) { - return renameFiles(files, action, conflict, output, format, (XattrMetaInfoProvider) db, filter, strict, exec); + // photo / xattr / plain file mode + if (db instanceof LocalDatasource) { + return renameFiles(files, action, conflict, output, format, (LocalDatasource) db, filter, strict, exec); } // auto-detect mode for each fileset @@ -513,7 +513,7 @@ public class CmdlineOperations implements CmdlineInterface { return renameAll(formatMatches(matches, format, outputDir), renameAction, conflictAction, null, exec); } - public List renameFiles(Collection files, RenameAction renameAction, ConflictAction conflictAction, File outputDir, ExpressionFileFormat format, XattrMetaInfoProvider service, ExpressionFilter filter, boolean strict, ExecCommand exec) throws Exception { + public List renameFiles(Collection files, RenameAction renameAction, ConflictAction conflictAction, File outputDir, ExpressionFileFormat format, LocalDatasource service, ExpressionFilter filter, boolean strict, ExecCommand exec) throws Exception { log.config(format("Rename files using [%s]", service.getName())); Map renameMap = new LinkedHashMap(); diff --git a/source/net/filebot/media/LocalDatasource.java b/source/net/filebot/media/LocalDatasource.java new file mode 100644 index 00000000..c4d7d93e --- /dev/null +++ b/source/net/filebot/media/LocalDatasource.java @@ -0,0 +1,91 @@ +package net.filebot.media; + +import static java.util.stream.Collectors.*; +import static net.filebot.Logging.*; +import static net.filebot.util.FileUtilities.*; + +import java.io.File; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.swing.Icon; + +import net.filebot.ResourceManager; +import net.filebot.web.Datasource; + +public enum LocalDatasource implements Datasource { + + XATTR, EXIF, FILE; + + @Override + public String getIdentifier() { + switch (this) { + case XATTR: + return "xattr"; + case EXIF: + return "exif"; + default: + return "file"; + } + } + + @Override + public String getName() { + switch (this) { + case XATTR: + return "Extended Attributes"; + case EXIF: + return "Exif Metadata"; + default: + return "Plain File"; + } + } + + @Override + public Icon getIcon() { + switch (this) { + case XATTR: + return ResourceManager.getIcon("search.xattr"); + case EXIF: + return ResourceManager.getIcon("search.exif"); + default: + return ResourceManager.getIcon("search.generic"); + } + } + + public Map match(Collection files, boolean strict) { + switch (this) { + case XATTR: + Map xattrMap = new LinkedHashMap(files.size()); + for (File f : files) { + Object object = xattr.getMetaInfo(f); + if (object != null) { + xattrMap.put(f, object); + } else if (!strict) { + xattrMap.put(f, f); + } + } + return xattrMap; + case EXIF: + Map exifMap = new LinkedHashMap(files.size()); + for (File f : filter(files, ImageMetadata.SUPPORTED_FILE_TYPES)) { + try { + ImageMetadata metadata = new ImageMetadata(f); + if (metadata.getDateTaken().isPresent()) { + exifMap.put(f, f); // photo mode is the same as generic file mode (but only select photo files) + } + } catch (Exception e) { + debug.warning(format("%s [%s]", e, f)); + } + } + return exifMap; + default: + return files.stream().collect(toMap(f -> f, f -> f, (a, b) -> a, LinkedHashMap::new)); + } + } + + // enable xattr regardless of -DuseExtendedFileAttributes system properties + private static final XattrMetaInfo xattr = new XattrMetaInfo(true, false); + +} diff --git a/source/net/filebot/media/PlainFileMatcher.java b/source/net/filebot/media/PlainFileMatcher.java new file mode 100644 index 00000000..7c9c7166 --- /dev/null +++ b/source/net/filebot/media/PlainFileMatcher.java @@ -0,0 +1,36 @@ +package net.filebot.media; + +import static java.util.stream.Collectors.*; + +import java.io.File; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.swing.Icon; + +import net.filebot.ResourceManager; +import net.filebot.web.Datasource; + +public class PlainFileMatcher implements Datasource { + + @Override + public String getIdentifier() { + return "file"; + } + + @Override + public String getName() { + return "Plain File"; + } + + @Override + public Icon getIcon() { + return ResourceManager.getIcon("search.generic"); + } + + public Map match(Collection files, boolean strict) { + return files.stream().collect(toMap(f -> f, f -> f, (a, b) -> a, LinkedHashMap::new)); + } + +} diff --git a/source/net/filebot/media/XattrMetaInfoProvider.java b/source/net/filebot/media/XattrMetaInfoProvider.java deleted file mode 100644 index b1c7d494..00000000 --- a/source/net/filebot/media/XattrMetaInfoProvider.java +++ /dev/null @@ -1,49 +0,0 @@ -package net.filebot.media; - -import java.io.File; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.Map; - -import javax.swing.Icon; - -import net.filebot.ResourceManager; -import net.filebot.web.Datasource; - -public class XattrMetaInfoProvider implements Datasource { - - @Override - public String getIdentifier() { - return "xattr"; - } - - @Override - public String getName() { - return "Extended Attributes"; - } - - @Override - public Icon getIcon() { - return ResourceManager.getIcon("search.xattr"); - } - - public Map match(Collection files, boolean strict) { - // enable xattr regardless of -DuseExtendedFileAttributes system properties - XattrMetaInfo xattr = new XattrMetaInfo(true, false); - - Map result = new LinkedHashMap(); - - for (File f : files) { - Object object = xattr.getMetaInfo(f); - - if (object != null) { - result.put(f, object); - } else if (!strict) { - result.put(f, f); - } - } - - return result; - } - -} diff --git a/source/net/filebot/ui/rename/PlainFileMatcher.java b/source/net/filebot/ui/rename/LocalFileMatcher.java similarity index 54% rename from source/net/filebot/ui/rename/PlainFileMatcher.java rename to source/net/filebot/ui/rename/LocalFileMatcher.java index 68ec530e..590a4c14 100644 --- a/source/net/filebot/ui/rename/PlainFileMatcher.java +++ b/source/net/filebot/ui/rename/LocalFileMatcher.java @@ -10,32 +10,39 @@ import java.util.Locale; import javax.swing.Icon; -import net.filebot.ResourceManager; +import net.filebot.media.LocalDatasource; import net.filebot.similarity.Match; import net.filebot.web.Datasource; import net.filebot.web.SortOrder; -public class PlainFileMatcher implements Datasource, AutoCompleteMatcher { +public class LocalFileMatcher implements Datasource, AutoCompleteMatcher { + + private final LocalDatasource datasource; + + public LocalFileMatcher(LocalDatasource datasource) { + this.datasource = datasource; + } @Override public String getIdentifier() { - return "file"; + return datasource.getIdentifier(); } @Override public String getName() { - return "Plain File"; + return datasource.getName(); } @Override public Icon getIcon() { - return ResourceManager.getIcon("search.generic"); + return datasource.getIcon(); } @Override public List> match(Collection files, boolean strict, SortOrder order, Locale locale, boolean autodetection, Component parent) throws Exception { - return files.stream().map(f -> { - return new Match(f, f); + // always use strict mode internally to make behavior more simple and consistent for GUI users + return datasource.match(files, true).entrySet().stream().map(it -> { + return new Match(it.getKey(), it.getValue()); }).collect(toList()); } diff --git a/source/net/filebot/ui/rename/PhotoFileMatcher.java b/source/net/filebot/ui/rename/PhotoFileMatcher.java deleted file mode 100644 index 03d066e5..00000000 --- a/source/net/filebot/ui/rename/PhotoFileMatcher.java +++ /dev/null @@ -1,56 +0,0 @@ -package net.filebot.ui.rename; - -import static net.filebot.Logging.*; -import static net.filebot.util.FileUtilities.*; - -import java.awt.Component; -import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Locale; - -import javax.swing.Icon; - -import net.filebot.ResourceManager; -import net.filebot.media.ImageMetadata; -import net.filebot.similarity.Match; -import net.filebot.web.Datasource; -import net.filebot.web.SortOrder; - -public class PhotoFileMatcher implements Datasource, AutoCompleteMatcher { - - @Override - public String getIdentifier() { - return "exif"; - } - - @Override - public String getName() { - return "Exif Metadata"; - } - - @Override - public Icon getIcon() { - return ResourceManager.getIcon("search.exif"); - } - - @Override - public List> match(Collection files, boolean strict, SortOrder order, Locale locale, boolean autodetection, Component parent) throws Exception { - List> matches = new ArrayList>(); - - for (File f : filter(files, ImageMetadata.SUPPORTED_FILE_TYPES)) { - try { - ImageMetadata metadata = new ImageMetadata(f); - if (metadata.getDateTaken().isPresent()) { - matches.add(new Match(f, f)); // photo mode is the same as generic file mode (but only select photo files) - } - } catch (Exception e) { - debug.warning(format("%s [%s]", e, f)); - } - } - - return matches; - } - -} diff --git a/source/net/filebot/ui/rename/Preset.java b/source/net/filebot/ui/rename/Preset.java index 840a3427..0ee28497 100644 --- a/source/net/filebot/ui/rename/Preset.java +++ b/source/net/filebot/ui/rename/Preset.java @@ -141,11 +141,7 @@ public class Preset { } public static Datasource[] getSupportedServices() { - return Stream.of(getEpisodeListProviders(), getMovieIdentificationServices(), getMusicIdentificationServices(), getGenericFileMatcherServices()).flatMap(Stream::of).toArray(Datasource[]::new); - } - - public static Datasource[] getGenericFileMatcherServices() { - return new Datasource[] { new PhotoFileMatcher(), new XattrFileMatcher(), new PlainFileMatcher() }; + return Stream.of(getEpisodeListProviders(), getMovieIdentificationServices(), getMusicIdentificationServices(), getLocalDatasources()).flatMap(Stream::of).toArray(Datasource[]::new); } public static StandardRenameAction[] getSupportedActions() { diff --git a/source/net/filebot/ui/rename/RenamePanel.java b/source/net/filebot/ui/rename/RenamePanel.java index ce8101c9..ac885435 100644 --- a/source/net/filebot/ui/rename/RenamePanel.java +++ b/source/net/filebot/ui/rename/RenamePanel.java @@ -65,6 +65,7 @@ import net.filebot.UserFiles; import net.filebot.WebServices; import net.filebot.format.ExpressionFileFormat; import net.filebot.format.MediaBindingBean; +import net.filebot.media.LocalDatasource; import net.filebot.media.MetaAttributes; import net.filebot.platform.mac.MacAppUtilities; import net.filebot.similarity.Match; @@ -323,7 +324,7 @@ public class RenamePanel extends JComponent { withWaitCursor(evt.getSource(), () -> { if (namesList.getModel().isEmpty()) { // match to xattr metadata object or the file itself - Map xattr = WebServices.XattrMetaData.match(renameModel.files(), false); + Map xattr = LocalDatasource.XATTR.match(renameModel.files(), false); renameModel.clear(); renameModel.addAll(xattr.values(), xattr.keySet()); diff --git a/source/net/filebot/ui/rename/XattrFileMatcher.java b/source/net/filebot/ui/rename/XattrFileMatcher.java deleted file mode 100644 index dbb093bb..00000000 --- a/source/net/filebot/ui/rename/XattrFileMatcher.java +++ /dev/null @@ -1,28 +0,0 @@ -package net.filebot.ui.rename; - -import java.awt.Component; -import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Locale; - -import net.filebot.media.XattrMetaInfoProvider; -import net.filebot.similarity.Match; -import net.filebot.web.SortOrder; - -public class XattrFileMatcher extends XattrMetaInfoProvider implements AutoCompleteMatcher { - - @Override - public List> match(Collection files, boolean strict, SortOrder order, Locale locale, boolean autodetection, Component parent) throws Exception { - List> matches = new ArrayList>(); - - // use strict mode to exclude files that are not xattr tagged - match(files, true).forEach((k, v) -> { - matches.add(new Match(k, v)); - }); - - return matches; - } - -}