* clean release info from any auto-detected series name word sequence

This commit is contained in:
Reinhard Pointner 2011-12-03 10:50:45 +00:00
parent b93e85b9dd
commit 9cb97bf93a
5 changed files with 147 additions and 143 deletions

View File

@ -8,7 +8,7 @@ import static net.sourceforge.filebot.MediaTypes.*;
import static net.sourceforge.filebot.WebServices.*;
import static net.sourceforge.filebot.cli.CLILogging.*;
import static net.sourceforge.filebot.hash.VerificationUtilities.*;
import static net.sourceforge.filebot.similarity.SeriesNameMatcher.*;
import static net.sourceforge.filebot.mediainfo.ReleaseInfo.*;
import static net.sourceforge.filebot.subtitle.SubtitleUtilities.*;
import static net.sourceforge.tuned.FileUtilities.*;
@ -46,7 +46,6 @@ import net.sourceforge.filebot.format.MediaBindingBean;
import net.sourceforge.filebot.hash.HashType;
import net.sourceforge.filebot.hash.VerificationFileReader;
import net.sourceforge.filebot.hash.VerificationFileWriter;
import net.sourceforge.filebot.mediainfo.ReleaseInfo;
import net.sourceforge.filebot.similarity.EpisodeMetrics;
import net.sourceforge.filebot.similarity.Match;
import net.sourceforge.filebot.similarity.Matcher;
@ -98,7 +97,7 @@ public class CmdlineOperations implements CmdlineInterface {
Collection<String> cwsList = emptySet();
if (max >= 5) {
cwsList = detectSeriesName(mediaFiles);
cwsList = detectSeriesNames(mediaFiles);
}
SeriesNameMatcher nameMatcher = new SeriesNameMatcher();
@ -557,10 +556,7 @@ public class CmdlineOperations implements CmdlineInterface {
private Collection<String> detectQuery(Collection<File> mediaFiles, boolean strict) throws Exception {
Collection<String> names = detectSeriesName(mediaFiles);
// clean detected word sequence from unwanted data
names = new LinkedHashSet<String>(new ReleaseInfo().cleanRG(names));
Collection<String> names = detectSeriesNames(mediaFiles);
if (names.isEmpty() || (strict && names.size() > 1)) {
throw new Exception("Unable to auto-select query: " + names);

View File

@ -12,27 +12,40 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.sourceforge.filebot.similarity.SeriesNameMatcher;
import net.sourceforge.filebot.web.CachedResource;
public class ReleaseInfo {
public static Collection<String> detectSeriesNames(Collection<File> files) throws IOException {
SeriesNameMatcher matcher = new SeriesNameMatcher();
ReleaseInfo cleaner = new ReleaseInfo();
// match common word sequence and clean detected word sequence from unwanted elements
Collection<String> names = matcher.matchAll(files.toArray(new File[files.size()]));
return new LinkedHashSet<String>(cleaner.cleanRG(names));
}
public String getVideoSource(File file) {
// check parent and itself for group names
return matchLast(getVideoSourcePattern(), file.getParent(), file.getName());
}
public String getReleaseGroup(File file) throws IOException {
// check parent and itself for group names
return matchLast(getReleaseGroupPattern(), file.getParent(), file.getName());
}
protected String matchLast(Pattern pattern, CharSequence... sequence) {
String lastMatch = null;
@ -49,27 +62,27 @@ public class ReleaseInfo {
return lastMatch;
}
public List<String> clean(Iterable<String> items) throws IOException {
return clean(items, getVideoSourcePattern(), getCodecPattern());
}
public String clean(String item) throws IOException {
return clean(item, getVideoSourcePattern(), getCodecPattern());
}
public List<String> cleanRG(Iterable<String> items) throws IOException {
return clean(items, getReleaseGroupPattern(), getVideoSourcePattern(), getCodecPattern());
}
public String cleanRG(String item) throws IOException {
return clean(item, getReleaseGroupPattern(), getVideoSourcePattern(), getCodecPattern());
}
public List<String> clean(Iterable<String> items, Pattern... blacklisted) {
List<String> cleanedItems = new ArrayList<String>();
for (String it : items) {
@ -79,7 +92,7 @@ public class ReleaseInfo {
return cleanedItems;
}
public String clean(String item, Pattern... blacklisted) {
for (Pattern it : blacklisted) {
item = it.matcher(item).replaceAll("");
@ -88,27 +101,27 @@ public class ReleaseInfo {
return item.replaceAll("[\\p{Punct}\\p{Space}]+", " ").trim();
}
public Pattern getCodecPattern() {
// pattern matching any video source name
String pattern = getBundle(getClass().getName()).getString("pattern.codec");
return compile("(?<!\\p{Alnum})(" + pattern + ")(?!\\p{Alnum})", CASE_INSENSITIVE);
}
public Pattern getVideoSourcePattern() {
// pattern matching any video source name
String pattern = getBundle(getClass().getName()).getString("pattern.video.source");
return compile("(?<!\\p{Alnum})(" + pattern + ")(?!\\p{Alnum})", CASE_INSENSITIVE);
}
public Pattern getReleaseGroupPattern() throws IOException {
// pattern matching any release group name enclosed in separators
return compile("(?<!\\p{Alnum})(" + join(releaseGroupResource.get(), "|") + ")(?!\\p{Alnum})", CASE_INSENSITIVE);
}
// fetch release group names online and try to update the data every other day
protected final CachedResource<String[]> releaseGroupResource = new CachedResource<String[]>(getBundle(getClass().getName()).getString("url.release-groups"), DAYS.toMillis(2)) {

View File

@ -15,9 +15,9 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.TreeMap;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -28,17 +28,12 @@ import net.sourceforge.tuned.FileUtilities;
public class SeriesNameMatcher {
public static Collection<String> detectSeriesName(Collection<File> files) {
return new SeriesNameMatcher().matchAll(files.toArray(new File[files.size()]));
}
protected final SeasonEpisodeMatcher seasonEpisodeMatcher = new SeasonEpisodeMatcher(new SeasonEpisodeFilter(30, 50, 1000));
protected final NameSimilarityMetric nameSimilarityMetric = new NameSimilarityMetric();
protected final int commonWordSequenceMaxStartIndex = 3;
public Collection<String> matchAll(File[] files) {
SeriesNameCollection seriesNames = new SeriesNameCollection();
@ -59,7 +54,7 @@ public class SeriesNameMatcher {
return seriesNames;
}
public Collection<String> matchAll(String[] names) {
SeriesNameCollection seriesNames = new SeriesNameCollection();
@ -79,7 +74,7 @@ public class SeriesNameMatcher {
return seriesNames;
}
/**
* Try to match and verify all series names using known season episode patterns.
*
@ -114,7 +109,7 @@ public class SeriesNameMatcher {
return thresholdCollection;
}
/**
* Try to match all common word sequences in the given list.
*
@ -144,7 +139,7 @@ public class SeriesNameMatcher {
return results;
}
/**
* Try to match a series name from the given episode name using known season episode
* patterns.
@ -164,7 +159,7 @@ public class SeriesNameMatcher {
return null;
}
/**
* Try to match a series name from the first common word sequence.
*
@ -202,7 +197,7 @@ public class SeriesNameMatcher {
return join(common, " ");
}
protected String normalize(String name) {
// remove group names and checksums, any [...] or (...)
name = name.replaceAll("\\([^\\(]*\\)", "");
@ -215,7 +210,7 @@ public class SeriesNameMatcher {
return name.trim();
}
protected <T> T[] firstCommonSequence(T[] seq1, T[] seq2, int maxStartIndex, Comparator<T> equalsComparator) {
for (int i = 0; i < seq1.length && i <= maxStartIndex; i++) {
for (int j = 0; j < seq2.length && j <= maxStartIndex; j++) {
@ -241,7 +236,7 @@ public class SeriesNameMatcher {
return null;
}
private Map<File, String[]> mapNamesByFolder(File... files) {
Map<File, List<File>> filesByFolder = new LinkedHashMap<File, List<File>>();
@ -268,7 +263,7 @@ public class SeriesNameMatcher {
return namesByFolder;
}
protected String[] names(Collection<File> files) {
String[] names = new String[files.size()];
@ -282,12 +277,12 @@ public class SeriesNameMatcher {
return names;
}
protected static class SeriesNameCollection extends AbstractCollection<String> {
private final Map<String, String> data = new LinkedHashMap<String, String>();
@Override
public boolean add(String value) {
value = value.trim();
@ -308,12 +303,12 @@ public class SeriesNameMatcher {
return false;
}
protected String key(Object value) {
return value.toString().toLowerCase();
}
protected float firstCharacterCaseBalance(String s) {
int upper = 0;
int lower = 0;
@ -333,19 +328,19 @@ public class SeriesNameMatcher {
return (lower + (upper * 1.01f)) / Math.abs(lower - upper);
}
@Override
public boolean contains(Object value) {
return data.containsKey(key(value));
}
@Override
public Iterator<String> iterator() {
return data.values().iterator();
}
@Override
public int size() {
return data.size();
@ -353,7 +348,7 @@ public class SeriesNameMatcher {
}
protected static class ThresholdCollection<E> extends AbstractCollection<E> {
private final Collection<E> heaven;
@ -361,14 +356,14 @@ public class SeriesNameMatcher {
private final int threshold;
public ThresholdCollection(int threshold, Comparator<E> equalityComparator) {
this.heaven = new ArrayList<E>();
this.limbo = new TreeMap<E, Collection<E>>(equalityComparator);
this.threshold = threshold;
}
@Override
public boolean add(E value) {
Collection<E> buffer = limbo.get(value);
@ -400,18 +395,18 @@ public class SeriesNameMatcher {
return false;
};
public boolean addDirect(E element) {
return heaven.add(element);
}
@Override
public Iterator<E> iterator() {
return heaven.iterator();
}
@Override
public int size() {
return heaven.size();

View File

@ -4,7 +4,7 @@ package net.sourceforge.filebot.ui.rename;
import static java.util.Collections.*;
import static net.sourceforge.filebot.MediaTypes.*;
import static net.sourceforge.filebot.similarity.SeriesNameMatcher.*;
import static net.sourceforge.filebot.mediainfo.ReleaseInfo.*;
import static net.sourceforge.filebot.web.EpisodeUtilities.*;
import static net.sourceforge.tuned.FileUtilities.*;
import static net.sourceforge.tuned.ui.TunedUtilities.*;
@ -51,12 +51,12 @@ class EpisodeListMatcher implements AutoCompleteMatcher {
private final EpisodeListProvider provider;
public EpisodeListMatcher(EpisodeListProvider provider) {
this.provider = provider;
}
protected SearchResult selectSearchResult(final String query, final List<SearchResult> searchResults, final Component parent) throws Exception {
if (searchResults.size() == 1) {
return searchResults.get(0);
@ -111,13 +111,13 @@ class EpisodeListMatcher implements AutoCompleteMatcher {
return showSelectDialog.get();
}
private String normalizeName(String value) {
// remove trailing braces, e.g. Doctor Who (2005) -> doctor who
return removeTrailingBrackets(value).toLowerCase();
}
protected Set<Episode> fetchEpisodeSet(Collection<String> seriesNames, final Locale locale, final Component parent) throws Exception {
List<Callable<List<Episode>>> tasks = new ArrayList<Callable<List<Episode>>>();
@ -165,7 +165,7 @@ class EpisodeListMatcher implements AutoCompleteMatcher {
}
}
@Override
public List<Match<File, ?>> match(final List<File> files, final Locale locale, final boolean autodetection, final Component parent) throws Exception {
// focus on movie and subtitle files
@ -173,7 +173,7 @@ class EpisodeListMatcher implements AutoCompleteMatcher {
final Map<File, List<File>> filesByFolder = mapByFolder(mediaFiles);
// do matching all at once
if (filesByFolder.keySet().size() <= 5 || detectSeriesName(mediaFiles).size() <= 5) {
if (filesByFolder.keySet().size() <= 5 || detectSeriesNames(mediaFiles).size() <= 5) {
return matchEpisodeSet(mediaFiles, locale, autodetection, parent);
}
@ -209,13 +209,13 @@ class EpisodeListMatcher implements AutoCompleteMatcher {
}
}
public List<Match<File, ?>> matchEpisodeSet(final List<File> files, Locale locale, boolean autodetection, Component parent) throws Exception {
Set<Episode> episodes = emptySet();
// detect series name and fetch episode list
if (autodetection) {
Collection<String> names = detectSeriesName(files);
Collection<String> names = detectSeriesNames(files);
if (names.size() > 0) {
// only allow one fetch session at a time so later requests can make use of cached results
synchronized (provider) {

View File

@ -4,7 +4,7 @@ package net.sourceforge.filebot.ui.subtitle;
import static javax.swing.BorderFactory.*;
import static javax.swing.JOptionPane.*;
import static net.sourceforge.filebot.similarity.SeriesNameMatcher.*;
import static net.sourceforge.filebot.mediainfo.ReleaseInfo.*;
import static net.sourceforge.filebot.subtitle.SubtitleUtilities.*;
import static net.sourceforge.tuned.FileUtilities.*;
import static net.sourceforge.tuned.StringUtilities.*;
@ -27,8 +27,8 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.Map.Entry;
import java.util.TreeSet;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@ -87,7 +87,7 @@ class SubtitleAutoMatchDialog extends JDialog {
private ExecutorService queryService;
private ExecutorService downloadService;
public SubtitleAutoMatchDialog(Window owner) {
super(owner, "Download Subtitles", ModalityType.DOCUMENT_MODAL);
@ -102,7 +102,7 @@ class SubtitleAutoMatchDialog extends JDialog {
content.add(new JButton(finishAction), "tag cancel");
}
protected JPanel createServicePanel(Color color) {
JPanel panel = new JPanel(new MigLayout("hidemode 3"));
panel.setBorder(new RoundBorder());
@ -112,7 +112,7 @@ class SubtitleAutoMatchDialog extends JDialog {
return panel;
}
protected JTable createTable() {
JTable table = new JTable(new SubtitleMappingTableModel());
table.setDefaultRenderer(SubtitleMapping.class, new SubtitleMappingOptionRenderer());
@ -148,22 +148,22 @@ class SubtitleAutoMatchDialog extends JDialog {
return table;
}
public void setVideoFiles(File[] videoFiles) {
subtitleMappingTable.setModel(new SubtitleMappingTableModel(videoFiles));
}
public void addSubtitleService(VideoHashSubtitleService service) {
addSubtitleService(new VideoHashSubtitleServiceBean(service), hashMatcherServicePanel);
}
public void addSubtitleService(SubtitleProvider service) {
addSubtitleService(new SubtitleProviderBean(service, this), nameMatcherServicePanel);
}
protected void addSubtitleService(final SubtitleServiceBean service, final JPanel servicePanel) {
final LinkButton component = new LinkButton(service.getName(), ResourceManager.getIcon("database"), service.getLink());
component.setVisible(false);
@ -189,11 +189,11 @@ class SubtitleAutoMatchDialog extends JDialog {
servicePanel.add(component);
}
// remember last user input
private List<String> userQuery = new ArrayList<String>();
protected List<String> getUserQuery(String suggestion, String title, Component parent) throws Exception {
synchronized (userQuery) {
if (userQuery.isEmpty()) {
@ -203,7 +203,7 @@ class SubtitleAutoMatchDialog extends JDialog {
}
}
public void startQuery(String languageName) {
final SubtitleMappingTableModel mappingModel = (SubtitleMappingTableModel) subtitleMappingTable.getModel();
QueryTask queryTask = new QueryTask(services, mappingModel.getVideoFiles(), languageName, SubtitleAutoMatchDialog.this) {
@ -232,7 +232,7 @@ class SubtitleAutoMatchDialog extends JDialog {
queryService.submit(queryTask);
}
private Boolean showConfirmReplaceDialog(List<?> files) {
JList existingFilesComponent = new JList(files.toArray()) {
@ -262,7 +262,7 @@ class SubtitleAutoMatchDialog extends JDialog {
return null;
}
private final Action downloadAction = new AbstractAction("Download", ResourceManager.getIcon("dialog.continue")) {
@Override
@ -361,17 +361,17 @@ class SubtitleAutoMatchDialog extends JDialog {
}
};
private static class SubtitleMappingOptionRenderer extends DefaultTableCellRenderer {
private final JComboBox optionComboBox = new SimpleComboBox();
public SubtitleMappingOptionRenderer() {
optionComboBox.setRenderer(new SubtitleOptionRenderer());
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
SubtitleMapping mapping = (SubtitleMapping) value;
@ -413,12 +413,12 @@ class SubtitleAutoMatchDialog extends JDialog {
}
}
private static class SubtitleOptionRenderer extends DefaultListCellRenderer {
private final Border padding = createEmptyBorder(3, 3, 3, 3);
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, null, index, isSelected, cellHasFocus);
@ -444,14 +444,14 @@ class SubtitleAutoMatchDialog extends JDialog {
}
}
private static class SubtitleMappingTableModel extends AbstractTableModel implements Iterable<SubtitleMapping> {
private final SubtitleMapping[] data;
private boolean optionColumnVisible = false;
public SubtitleMappingTableModel(File... videoFiles) {
data = new SubtitleMapping[videoFiles.length];
@ -461,7 +461,7 @@ class SubtitleAutoMatchDialog extends JDialog {
}
}
public List<File> getVideoFiles() {
return new AbstractList<File>() {
@ -470,7 +470,7 @@ class SubtitleAutoMatchDialog extends JDialog {
return data[index].getVideoFile();
}
@Override
public int size() {
return data.length;
@ -478,13 +478,13 @@ class SubtitleAutoMatchDialog extends JDialog {
};
}
@Override
public Iterator<SubtitleMapping> iterator() {
return Arrays.asList(data).iterator();
}
public void setOptionColumnVisible(boolean optionColumnVisible) {
if (this.optionColumnVisible == optionColumnVisible)
return;
@ -495,13 +495,13 @@ class SubtitleAutoMatchDialog extends JDialog {
fireTableStructureChanged();
}
@Override
public int getColumnCount() {
return optionColumnVisible ? 2 : 1;
}
@Override
public String getColumnName(int column) {
switch (column) {
@ -514,13 +514,13 @@ class SubtitleAutoMatchDialog extends JDialog {
return null;
}
@Override
public int getRowCount() {
return data.length;
}
@Override
public Object getValueAt(int row, int column) {
switch (column) {
@ -533,19 +533,19 @@ class SubtitleAutoMatchDialog extends JDialog {
return null;
}
@Override
public void setValueAt(Object value, int row, int column) {
data[row].setSelectedOption((SubtitleDescriptorBean) value);
}
@Override
public boolean isCellEditable(int row, int column) {
return column == 1 && data[row].isEditable();
}
@Override
public Class<?> getColumnClass(int column) {
switch (column) {
@ -558,17 +558,17 @@ class SubtitleAutoMatchDialog extends JDialog {
return null;
}
private class SubtitleMappingListener implements PropertyChangeListener {
private final int index;
public SubtitleMappingListener(int index) {
this.index = index;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
// update state and subtitle options
@ -577,7 +577,7 @@ class SubtitleAutoMatchDialog extends JDialog {
}
}
private static class SubtitleMapping extends AbstractBean {
private File videoFile;
@ -586,38 +586,38 @@ class SubtitleAutoMatchDialog extends JDialog {
private SubtitleDescriptorBean selectedOption;
private List<SubtitleDescriptorBean> options = new ArrayList<SubtitleDescriptorBean>();
public SubtitleMapping(File videoFile) {
this.videoFile = videoFile;
}
public File getVideoFile() {
return videoFile;
}
public File getSubtitleFile() {
return subtitleFile;
}
public void setSubtitleFile(File subtitleFile) {
this.subtitleFile = subtitleFile;
firePropertyChange("subtitleFile", null, this.subtitleFile);
}
public boolean isEditable() {
return subtitleFile == null && selectedOption != null && (selectedOption.getState() == null || selectedOption.getError() != null);
}
public SubtitleDescriptorBean getSelectedOption() {
return selectedOption;
}
public void setSelectedOption(SubtitleDescriptorBean selectedOption) {
if (this.selectedOption != null) {
this.selectedOption.removePropertyChangeListener(selectedOptionListener);
@ -629,12 +629,12 @@ class SubtitleAutoMatchDialog extends JDialog {
firePropertyChange("selectedOption", null, this.selectedOption);
}
public SubtitleDescriptorBean[] getOptions() {
return options.toArray(new SubtitleDescriptorBean[0]);
}
public void addOptions(List<SubtitleDescriptorBean> options) {
this.options.addAll(options);
@ -643,7 +643,7 @@ class SubtitleAutoMatchDialog extends JDialog {
}
}
private final PropertyChangeListener selectedOptionListener = new PropertyChangeListener() {
@Override
@ -653,7 +653,7 @@ class SubtitleAutoMatchDialog extends JDialog {
};
}
private static class SubtitleDescriptorBean extends AbstractBean {
private final File videoFile;
@ -663,39 +663,39 @@ class SubtitleAutoMatchDialog extends JDialog {
private StateValue state;
private Exception error;
public SubtitleDescriptorBean(File videoFile, SubtitleDescriptor descriptor, SubtitleServiceBean service) {
this.videoFile = videoFile;
this.descriptor = descriptor;
this.service = service;
}
public float getMatchProbability() {
return service.getMatchProbabilty(videoFile, descriptor);
}
public String getText() {
return formatSubtitle(descriptor.getName(), getLanguageName(), getType());
}
public Icon getIcon() {
return service.getIcon();
}
public String getLanguageName() {
return descriptor.getLanguageName();
}
public String getType() {
return descriptor.getType();
}
public MemoryFile fetch() throws Exception {
setState(StateValue.STARTED);
@ -715,30 +715,30 @@ class SubtitleAutoMatchDialog extends JDialog {
}
}
public Exception getError() {
return error;
}
public StateValue getState() {
return state;
}
public void setState(StateValue state) {
this.state = state;
firePropertyChange("state", null, this.state);
}
@Override
public String toString() {
return getText();
}
}
private static class QueryTask extends SwingWorker<Collection<File>, Map<File, List<SubtitleDescriptorBean>>> {
private final Component parent;
@ -747,7 +747,7 @@ class SubtitleAutoMatchDialog extends JDialog {
private final Collection<File> remainingVideos;
private final String languageName;
public QueryTask(Collection<SubtitleServiceBean> services, Collection<File> videoFiles, String languageName, Component parent) {
this.parent = parent;
this.services = services;
@ -755,7 +755,7 @@ class SubtitleAutoMatchDialog extends JDialog {
this.languageName = languageName;
}
@Override
protected Collection<File> doInBackground() throws Exception {
for (SubtitleServiceBean service : services) {
@ -804,24 +804,24 @@ class SubtitleAutoMatchDialog extends JDialog {
}
}
private static class DownloadTask extends SwingWorker<File, Void> {
private final File video;
private final SubtitleDescriptorBean descriptor;
public DownloadTask(File video, SubtitleDescriptorBean descriptor) {
this.video = video;
this.descriptor = descriptor;
}
public SubtitleDescriptorBean getSubtitleBean() {
return descriptor;
}
public File getDestination(MemoryFile subtitle) {
if (descriptor.getType() == null && subtitle == null)
return null;
@ -832,7 +832,7 @@ class SubtitleAutoMatchDialog extends JDialog {
return new File(video.getParentFile(), formatSubtitle(base, descriptor.getLanguageName(), ext));
}
@Override
protected File doInBackground() {
try {
@ -855,7 +855,7 @@ class SubtitleAutoMatchDialog extends JDialog {
}
}
protected static abstract class SubtitleServiceBean extends AbstractBean {
private final String name;
@ -865,35 +865,35 @@ class SubtitleAutoMatchDialog extends JDialog {
private StateValue state = StateValue.PENDING;
private Throwable error = null;
public SubtitleServiceBean(String name, Icon icon, URI link) {
this.name = name;
this.icon = icon;
this.link = link;
}
public String getName() {
return name;
}
public Icon getIcon() {
return icon;
}
public URI getLink() {
return link;
}
public abstract float getMatchProbabilty(File videoFile, SubtitleDescriptor descriptor);
protected abstract Map<File, List<SubtitleDescriptor>> getSubtitleList(Collection<File> files, String languageName, Component parent) throws Exception;
public final Map<File, List<SubtitleDescriptor>> lookupSubtitles(Collection<File> files, String languageName, Component parent) throws Exception {
setState(StateValue.STARTED);
@ -910,61 +910,61 @@ class SubtitleAutoMatchDialog extends JDialog {
}
}
private void setState(StateValue state) {
this.state = state;
firePropertyChange("state", null, this.state);
}
public StateValue getState() {
return state;
}
public Throwable getError() {
return error;
}
}
protected static class VideoHashSubtitleServiceBean extends SubtitleServiceBean {
private VideoHashSubtitleService service;
public VideoHashSubtitleServiceBean(VideoHashSubtitleService service) {
super(service.getName(), service.getIcon(), service.getLink());
this.service = service;
}
@Override
protected Map<File, List<SubtitleDescriptor>> getSubtitleList(Collection<File> files, String languageName, Component parent) throws Exception {
return service.getSubtitleList(files.toArray(new File[0]), languageName);
}
@Override
public float getMatchProbabilty(File videoFile, SubtitleDescriptor descriptor) {
return 1;
}
}
protected static class SubtitleProviderBean extends SubtitleServiceBean {
private SubtitleAutoMatchDialog inputProvider;
private SubtitleProvider service;
public SubtitleProviderBean(SubtitleProvider service, SubtitleAutoMatchDialog inputProvider) {
super(service.getName(), service.getIcon(), service.getLink());
this.service = service;
this.inputProvider = inputProvider;
}
@Override
protected Map<File, List<SubtitleDescriptor>> getSubtitleList(Collection<File> files, String languageName, Component parent) throws Exception {
Map<File, List<SubtitleDescriptor>> subtitlesByFile = new HashMap<File, List<SubtitleDescriptor>>();
@ -973,7 +973,7 @@ class SubtitleAutoMatchDialog extends JDialog {
}
// auto-detect query and search for subtitles
Collection<String> querySet = detectSeriesName(files);
Collection<String> querySet = detectSeriesNames(files);
List<SubtitleDescriptor> subtitles = findSubtitles(service, querySet, languageName);
// if auto-detection fails, ask user for input
@ -1016,7 +1016,7 @@ class SubtitleAutoMatchDialog extends JDialog {
return subtitlesByFile;
}
@Override
public float getMatchProbabilty(File videoFile, SubtitleDescriptor descriptor) {
return EpisodeMetrics.verificationMetric().getSimilarity(videoFile, descriptor) * 0.9f;