* improved handling of multi-part movies

* added OpenSubtitles as movie name source
This commit is contained in:
Reinhard Pointner 2010-01-26 19:08:09 +00:00
parent 33b439c620
commit d1b111765e
8 changed files with 120 additions and 24 deletions

View File

@ -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>

View File

@ -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()));
}
}
});

View File

@ -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();
}
}

View File

@ -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)));
}
}

View File

@ -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;
}
}

View File

@ -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)));

View File

@ -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;

View File

@ -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);