* improved handling of multi-part movies
* added OpenSubtitles as movie name source
This commit is contained in:
parent
33b439c620
commit
d1b111765e
@ -195,7 +195,7 @@
|
||||
<mkdir dir="${dir.build}" />
|
||||
|
||||
<!-- compile -->
|
||||
<javac srcdir="${dir.source}:${dir.test}" destdir="${dir.build}" source="1.6" encoding="utf-8">
|
||||
<javac srcdir="${dir.source}:${dir.test}" destdir="${dir.build}" source="1.6" encoding="utf-8" includeAntRuntime="false">
|
||||
<classpath>
|
||||
<fileset dir="${dir.lib}" includes="*.jar" />
|
||||
</classpath>
|
||||
|
@ -3,8 +3,8 @@ package net.sourceforge.filebot;
|
||||
|
||||
|
||||
import static javax.swing.JFrame.*;
|
||||
import static net.sourceforge.tuned.ui.TunedUtilities.*;
|
||||
|
||||
import java.awt.Window;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.security.CodeSource;
|
||||
@ -96,16 +96,19 @@ public class Main {
|
||||
}
|
||||
|
||||
|
||||
private static void restoreWindowBounds(Window window, final Settings settings) {
|
||||
private static void restoreWindowBounds(final JFrame window, final Settings settings) {
|
||||
// store bounds on close
|
||||
window.addWindowListener(new WindowAdapter() {
|
||||
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
settings.put("window.x", String.valueOf(e.getWindow().getX()));
|
||||
settings.put("window.y", String.valueOf(e.getWindow().getY()));
|
||||
settings.put("window.width", String.valueOf(e.getWindow().getWidth()));
|
||||
settings.put("window.height", String.valueOf(e.getWindow().getHeight()));
|
||||
// don't save window bounds if window is maximized
|
||||
if (!isMaximized(window)) {
|
||||
settings.put("window.x", String.valueOf(window.getX()));
|
||||
settings.put("window.y", String.valueOf(window.getY()));
|
||||
settings.put("window.width", String.valueOf(window.getWidth()));
|
||||
settings.put("window.height", String.valueOf(window.getHeight()));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -2,15 +2,16 @@
|
||||
package net.sourceforge.filebot.ui.panel.rename;
|
||||
|
||||
|
||||
import java.util.Formatter;
|
||||
|
||||
import net.sourceforge.filebot.similarity.Match;
|
||||
import net.sourceforge.filebot.web.MovieDescriptor;
|
||||
|
||||
|
||||
class MovieFormatter implements MatchFormatter {
|
||||
|
||||
@Override
|
||||
public boolean canFormat(Match<?, ?> match) {
|
||||
return match.getValue() instanceof MovieDescriptor;
|
||||
return match.getValue() instanceof MoviePart;
|
||||
}
|
||||
|
||||
|
||||
@ -22,8 +23,15 @@ class MovieFormatter implements MatchFormatter {
|
||||
|
||||
@Override
|
||||
public String format(Match<?, ?> match) {
|
||||
// use default format for the time being
|
||||
return match.getValue().toString();
|
||||
MoviePart video = (MoviePart) match.getValue();
|
||||
Formatter name = new Formatter(new StringBuilder());
|
||||
|
||||
// format as single-file or multi-part movie
|
||||
name.format("%s (%d)", video.getMovie().getName(), video.getMovie().getYear());
|
||||
|
||||
if (video.getPartCount() > 1)
|
||||
name.format(" CD%d", video.getPartIndex() + 1);
|
||||
|
||||
return name.out().toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,10 +11,15 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.RunnableFuture;
|
||||
@ -44,18 +49,44 @@ class MovieHashMatcher implements AutoCompleteMatcher {
|
||||
File[] movieFiles = filter(files, VIDEO_FILES).toArray(new File[0]);
|
||||
MovieDescriptor[] movieDescriptors = service.getMovieDescriptors(movieFiles);
|
||||
|
||||
// map movies to (possibly multiple) files (in natural order)
|
||||
Map<MovieDescriptor, SortedSet<File>> filesByMovie = new HashMap<MovieDescriptor, SortedSet<File>>();
|
||||
|
||||
// map all files by movie
|
||||
for (int i = 0; i < movieFiles.length; i++) {
|
||||
MovieDescriptor movie = movieDescriptors[i];
|
||||
|
||||
// unknown hash, try via imdb id from nfo file
|
||||
if (movie == null) {
|
||||
movie = determineMovie(movieFiles[i]);
|
||||
}
|
||||
|
||||
// check if we managed to lookup the movie descriptor
|
||||
if (movie != null) {
|
||||
// get file list for movie
|
||||
SortedSet<File> movieParts = filesByMovie.get(movie);
|
||||
|
||||
if (movieParts == null) {
|
||||
movieParts = new TreeSet<File>();
|
||||
filesByMovie.put(movie, movieParts);
|
||||
}
|
||||
|
||||
movieParts.add(movieFiles[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// collect all File/MoviePart matches
|
||||
List<Match<File, ?>> matches = new ArrayList<Match<File, ?>>();
|
||||
|
||||
for (int i = 0; i < movieDescriptors.length; i++) {
|
||||
if (movieDescriptors[i] != null) {
|
||||
matches.add(new Match<File, MovieDescriptor>(movieFiles[i], movieDescriptors[i]));
|
||||
} else {
|
||||
// unknown hash, try via imdb id from nfo file
|
||||
MovieDescriptor movie = determineMovie(movieFiles[i]);
|
||||
|
||||
if (movie != null) {
|
||||
matches.add(new Match<File, MovieDescriptor>(movieFiles[i], movie));
|
||||
}
|
||||
for (Entry<MovieDescriptor, SortedSet<File>> entry : filesByMovie.entrySet()) {
|
||||
MovieDescriptor movie = entry.getKey();
|
||||
|
||||
int partIndex = 0;
|
||||
int partCount = entry.getValue().size();
|
||||
|
||||
// add all movie parts
|
||||
for (File file : entry.getValue()) {
|
||||
matches.add(new Match<File, MoviePart>(file, new MoviePart(movie, partIndex++, partCount)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,45 @@
|
||||
|
||||
package net.sourceforge.filebot.ui.panel.rename;
|
||||
|
||||
|
||||
import net.sourceforge.filebot.web.MovieDescriptor;
|
||||
|
||||
|
||||
class MoviePart {
|
||||
|
||||
private final MovieDescriptor movie;
|
||||
|
||||
private final int partIndex;
|
||||
private final int partCount;
|
||||
|
||||
|
||||
public MoviePart(MovieDescriptor movie) {
|
||||
this(movie, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
public MoviePart(MovieDescriptor movie, int partIndex, int partCount) {
|
||||
if (partCount < 1 || partIndex >= partCount)
|
||||
throw new IllegalArgumentException("Illegal part: " + partIndex + "/" + partCount);
|
||||
|
||||
this.movie = movie;
|
||||
this.partIndex = partIndex;
|
||||
this.partCount = partCount;
|
||||
}
|
||||
|
||||
|
||||
public MovieDescriptor getMovie() {
|
||||
return movie;
|
||||
}
|
||||
|
||||
|
||||
public int getPartIndex() {
|
||||
return partIndex;
|
||||
}
|
||||
|
||||
|
||||
public int getPartCount() {
|
||||
return partCount;
|
||||
}
|
||||
|
||||
}
|
@ -41,6 +41,7 @@ import net.sourceforge.filebot.web.Episode;
|
||||
import net.sourceforge.filebot.web.EpisodeListProvider;
|
||||
import net.sourceforge.filebot.web.IMDbClient;
|
||||
import net.sourceforge.filebot.web.MovieDescriptor;
|
||||
import net.sourceforge.filebot.web.OpenSubtitlesClient;
|
||||
import net.sourceforge.filebot.web.TMDbClient;
|
||||
import net.sourceforge.filebot.web.TVDotComClient;
|
||||
import net.sourceforge.filebot.web.TVRageClient;
|
||||
@ -152,6 +153,9 @@ public class RenamePanel extends JComponent {
|
||||
actionPopup.addDescription(new JLabel("Movie Mode:"));
|
||||
|
||||
// create action for movie name completion
|
||||
OpenSubtitlesClient osdb = new OpenSubtitlesClient(String.format("%s %s", getApplicationName(), getApplicationVersion()));
|
||||
actionPopup.add(new AutoCompleteAction(osdb.getName(), osdb.getIcon(), new MovieHashMatcher(osdb)));
|
||||
|
||||
TMDbClient tmdb = new TMDbClient(getApplicationProperty("themoviedb.apikey"));
|
||||
actionPopup.add(new AutoCompleteAction(tmdb.getName(), tmdb.getIcon(), new MovieHashMatcher(tmdb)));
|
||||
|
||||
|
@ -5,6 +5,7 @@ package net.sourceforge.tuned.ui;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.Point;
|
||||
@ -98,6 +99,11 @@ public final class TunedUtilities {
|
||||
}
|
||||
|
||||
|
||||
public static boolean isMaximized(Frame frame) {
|
||||
return (frame.getExtendedState() & Frame.MAXIMIZED_BOTH) != 0;
|
||||
}
|
||||
|
||||
|
||||
public static Window getWindow(Object component) {
|
||||
if (component instanceof Window)
|
||||
return (Window) component;
|
||||
|
@ -44,8 +44,7 @@ public class TheTVDBClientTest {
|
||||
|
||||
TheTVDBSearchResult first = (TheTVDBSearchResult) results.get(0);
|
||||
|
||||
// test encoding (umlauts)
|
||||
assertEquals("Buffy - Im Bann der Dämonen", first.getName());
|
||||
assertEquals("Buffy", first.getName());
|
||||
assertEquals(70327, first.getSeriesId());
|
||||
|
||||
TheTVDBSearchResult second = (TheTVDBSearchResult) results.get(1);
|
||||
|
Loading…
Reference in New Issue
Block a user