Rework to avoid using preferences object to retrieve options
This commit is contained in:
@@ -14,15 +14,15 @@ import java.util.zip.ZipInputStream;
|
||||
/**
|
||||
* Zip implementation of {@link Archiver}
|
||||
*/
|
||||
public class ZipDecompresser implements Archiver {
|
||||
public class ZipArchiver implements Archiver {
|
||||
|
||||
@Inject
|
||||
ZipDecompresser() {
|
||||
ZipArchiver() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compress(final List<Path> files, final Path destination) throws IOException {
|
||||
public void compress(final List<Path> files, final Path destination) {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ public class ZipDecompresser implements Archiver {
|
||||
}
|
||||
return destPath;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String archiveExtension() {
|
||||
return "zip";
|
||||
@@ -3,7 +3,7 @@ package com.github.gtache.autosubtitle.modules.archive.impl;
|
||||
import com.github.gtache.autosubtitle.archive.Archiver;
|
||||
import com.github.gtache.autosubtitle.archive.ArchiverProvider;
|
||||
import com.github.gtache.autosubtitle.archive.impl.ArchiverProviderImpl;
|
||||
import com.github.gtache.autosubtitle.archive.impl.ZipDecompresser;
|
||||
import com.github.gtache.autosubtitle.archive.impl.ZipArchiver;
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import dagger.multibindings.IntoMap;
|
||||
@@ -25,5 +25,5 @@ public abstract class ArchiveModule {
|
||||
@Binds
|
||||
@StringKey("zip")
|
||||
@IntoMap
|
||||
abstract Archiver bindsZipDecompresser(final ZipDecompresser decompresser);
|
||||
abstract Archiver bindsZipDecompresser(final ZipArchiver decompresser);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import dagger.Module;
|
||||
/**
|
||||
* Dagger module for subtitles
|
||||
*/
|
||||
@Module(includes = {SubtitleConverterModule.class})
|
||||
@Module(includes = SubtitleConverterModule.class)
|
||||
public abstract class SubtitleModule {
|
||||
|
||||
private SubtitleModule() {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.converter.impl;
|
||||
|
||||
import com.github.gtache.autosubtitle.VideoInfo;
|
||||
import com.github.gtache.autosubtitle.modules.impl.FontName;
|
||||
import com.github.gtache.autosubtitle.modules.impl.FontSize;
|
||||
import com.github.gtache.autosubtitle.subtitle.Font;
|
||||
import com.github.gtache.autosubtitle.subtitle.Subtitle;
|
||||
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.FormatOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseException;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
|
||||
import com.github.gtache.autosubtitle.subtitle.impl.FontImpl;
|
||||
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleCollectionImpl;
|
||||
@@ -20,7 +20,7 @@ import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.prefs.Preferences;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
@@ -35,47 +35,38 @@ public class ASSSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
|
||||
private static final String DIALOGUE = "Dialogue:";
|
||||
private static final String EVENTS_SECTION = "[Events]";
|
||||
private static final String STYLES_SECTION = "[V4+ Styles]";
|
||||
private static final Pattern NEWLINE_PATTERN = Pattern.compile("\\n");
|
||||
private final Translator<?> translator;
|
||||
private final Preferences preferences;
|
||||
private final String defaultFontName;
|
||||
private final int defaultFontSize;
|
||||
|
||||
@Inject
|
||||
ASSSubtitleConverter(final Translator translator, final Preferences preferences,
|
||||
@FontName final String defaultFontName, @FontSize final int defaultFontSize) {
|
||||
ASSSubtitleConverter(final Translator translator) {
|
||||
this.translator = requireNonNull(translator);
|
||||
this.preferences = requireNonNull(preferences);
|
||||
this.defaultFontName = Objects.requireNonNull(defaultFontName);
|
||||
if (defaultFontSize <= 0) {
|
||||
throw new IllegalArgumentException("Font size must be positive : " + defaultFontSize);
|
||||
}
|
||||
this.defaultFontSize = defaultFontSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String format(final SubtitleCollection<?> collection, final VideoInfo videoInfo) {
|
||||
public String format(final SubtitleCollection<?> collection, final FormatOptions options) {
|
||||
final var subtitles = collection.subtitles().stream().sorted(Comparator.comparing(Subtitle::start).thenComparing(Subtitle::end)).toList();
|
||||
final var scriptInfo = getScriptInfo(videoInfo);
|
||||
final var styles = getStyles(subtitles);
|
||||
final var events = getEvents(subtitles);
|
||||
final var scriptInfo = getScriptInfo(options.videoInfo());
|
||||
final var styles = getStyles(subtitles, options.defaultFont());
|
||||
final var events = getEvents(subtitles, options.defaultFont());
|
||||
return scriptInfo + "\n\n" + styles + "\n\n" + events + "\n";
|
||||
}
|
||||
|
||||
private String getEvents(final Collection<? extends Subtitle> subtitles) {
|
||||
private static String getEvents(final Collection<? extends Subtitle> subtitles, final Font defaultFont) {
|
||||
return EVENTS_SECTION + "\n" + "Format: Start, End, Style, Text\n" +
|
||||
subtitles.stream().map(this::getEvent).collect(Collectors.joining("\n"));
|
||||
subtitles.stream().map(s -> getEvent(s, defaultFont)).collect(Collectors.joining("\n"));
|
||||
}
|
||||
|
||||
private String getEvent(final Subtitle subtitle) {
|
||||
return DIALOGUE + " " + formatTime(subtitle.start()) + "," + formatTime(subtitle.end()) + "," + getName(subtitle.font()) + "," + subtitle.content();
|
||||
private static String getEvent(final Subtitle subtitle, final Font defaultFont) {
|
||||
return DIALOGUE + " " + formatTime(subtitle.start()) + "," + formatTime(subtitle.end()) + "," + getName(subtitle.font(), defaultFont) + "," + subtitle.content();
|
||||
}
|
||||
|
||||
private String getName(final Font font) {
|
||||
private static String getName(final Font font, final Font defaultFont) {
|
||||
final String fontName;
|
||||
final int fontSize;
|
||||
if (font == null) {
|
||||
fontName = preferences.get("fontName", defaultFontName);
|
||||
fontSize = preferences.getInt("fontSize", defaultFontSize);
|
||||
fontName = defaultFont.name();
|
||||
fontSize = defaultFont.size();
|
||||
} else {
|
||||
fontName = font.name();
|
||||
fontSize = font.size();
|
||||
@@ -83,16 +74,16 @@ public class ASSSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
|
||||
return fontName + fontSize;
|
||||
}
|
||||
|
||||
private String getStyles(final Collection<? extends Subtitle> subtitles) {
|
||||
return STYLES_SECTION + "\n" + "Format: Name, Fontname, Fontsize\n" + listStyles(subtitles);
|
||||
private static String getStyles(final Collection<? extends Subtitle> subtitles, final Font defaultFont) {
|
||||
return STYLES_SECTION + "\n" + "Format: Name, Fontname, Fontsize\n" + listStyles(subtitles, defaultFont);
|
||||
}
|
||||
|
||||
private String listStyles(final Collection<? extends Subtitle> subtitles) {
|
||||
private static String listStyles(final Collection<? extends Subtitle> subtitles, final Font defaultFont) {
|
||||
final var uniqueStyles = subtitles.stream().map(Subtitle::font).filter(Objects::nonNull).collect(Collectors.toSet());
|
||||
if (subtitles.stream().anyMatch(s -> s.font() == null)) {
|
||||
uniqueStyles.add(new FontImpl(preferences.get("fontName", defaultFontName), preferences.getInt("fontSize", defaultFontSize)));
|
||||
uniqueStyles.add(defaultFont);
|
||||
}
|
||||
return uniqueStyles.stream().map(f -> STYLE + " " + getName(f) + ", " + f.name() + ", " + f.size()).collect(Collectors.joining("\n"));
|
||||
return uniqueStyles.stream().map(f -> STYLE + " " + getName(f, defaultFont) + ", " + f.name() + ", " + f.size()).collect(Collectors.joining("\n"));
|
||||
}
|
||||
|
||||
private static String getScriptInfo(final VideoInfo videoInfo) {
|
||||
@@ -103,32 +94,21 @@ public class ASSSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
|
||||
WrapStyle: 1""".formatted(videoInfo.width(), videoInfo.height());
|
||||
}
|
||||
|
||||
private static String formatTime(final long time) {
|
||||
final var millisPerHour = 3600000;
|
||||
final var millisPerMinute = 60000;
|
||||
final var hours = time / millisPerHour;
|
||||
final var minutes = (time - hours * millisPerHour) / millisPerMinute;
|
||||
final var seconds = (time - hours * millisPerHour - minutes * millisPerMinute) / 1000;
|
||||
final var millis = time - hours * millisPerHour - minutes * millisPerMinute - seconds * 1000;
|
||||
final var hundredths = millis / 10;
|
||||
return String.format("%d:%02d:%02d.%02d", hours, minutes, seconds, hundredths);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubtitleCollectionImpl<SubtitleImpl> parse(final String content) throws ParseException {
|
||||
final var fonts = parseFonts(content);
|
||||
public SubtitleCollectionImpl<SubtitleImpl> parse(final String content, final ParseOptions options) throws ParseException {
|
||||
final var fonts = parseFonts(content, options.defaultFont());
|
||||
final var subtitles = parseSubtitles(content, fonts);
|
||||
final var text = subtitles.stream().map(Subtitle::content).collect(Collectors.joining());
|
||||
final var language = translator.getLanguage(text);
|
||||
return new SubtitleCollectionImpl<>(text, subtitles, language);
|
||||
}
|
||||
|
||||
private static List<SubtitleImpl> parseSubtitles(final String content, final Map<String, Font> fonts) throws ParseException {
|
||||
private static List<SubtitleImpl> parseSubtitles(final String content, final Map<String, ? extends Font> fonts) throws ParseException {
|
||||
final var fontIndex = content.indexOf(EVENTS_SECTION);
|
||||
if (fontIndex == -1) {
|
||||
throw new ParseException("Events section not found in " + content);
|
||||
} else {
|
||||
final var split = content.substring(fontIndex).split("\\n");
|
||||
final var split = NEWLINE_PATTERN.split(content.substring(fontIndex));
|
||||
final List<String> fields;
|
||||
if (split[0].startsWith(EVENTS_SECTION)) {
|
||||
fields = getFields(split[1]);
|
||||
@@ -155,12 +135,12 @@ public class ASSSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Font> parseFonts(final String content) throws ParseException {
|
||||
private static Map<String, Font> parseFonts(final String content, final Font defaultFont) throws ParseException {
|
||||
final var fontIndex = content.indexOf(STYLES_SECTION);
|
||||
if (fontIndex == -1) {
|
||||
throw new ParseException("Styles section not found in " + content);
|
||||
} else {
|
||||
final var split = content.substring(fontIndex).split("\\n");
|
||||
final var split = NEWLINE_PATTERN.split(content.substring(fontIndex));
|
||||
final List<String> fields;
|
||||
if (split[0].startsWith(STYLES_SECTION)) {
|
||||
fields = getFields(split[1]);
|
||||
@@ -178,7 +158,7 @@ public class ASSSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
|
||||
final var name = values.get(fontNameIndex);
|
||||
final var size = Integer.parseInt(values.get(fontSizeIndex));
|
||||
return new FontImpl(name, size);
|
||||
}).collect(Collectors.toMap(this::getName, f -> f));
|
||||
}).collect(Collectors.toMap(f -> getName(f, defaultFont), f -> f));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,6 +176,16 @@ public class ASSSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
|
||||
return (hours * 3600L + minutes * 60L + seconds) * 1000L + hundredths * 10L;
|
||||
}
|
||||
|
||||
private static String formatTime(final long time) {
|
||||
final var millisPerHour = 3600000;
|
||||
final var millisPerMinute = 60000;
|
||||
final var hours = time / millisPerHour;
|
||||
final var minutes = (time - hours * millisPerHour) / millisPerMinute;
|
||||
final var seconds = (time - hours * millisPerHour - minutes * millisPerMinute) / 1000;
|
||||
final var hundredths = (time - hours * millisPerHour - minutes * millisPerMinute - seconds * 1000) / 10;
|
||||
return String.format("%02d:%02d:%02d.%02d", hours, minutes, seconds, hundredths);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String formatName() {
|
||||
return "ass";
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.converter.impl;
|
||||
|
||||
import com.github.gtache.autosubtitle.VideoInfo;
|
||||
import com.github.gtache.autosubtitle.subtitle.Font;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.FormatOptions;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Implementation of {@link FormatOptions}
|
||||
*/
|
||||
public record FormatOptionsImpl(VideoInfo videoInfo, Font defaultFont) implements FormatOptions {
|
||||
public FormatOptionsImpl {
|
||||
Objects.requireNonNull(videoInfo);
|
||||
Objects.requireNonNull(defaultFont);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.converter.impl;
|
||||
|
||||
import com.github.gtache.autosubtitle.subtitle.Font;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseOptions;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Implementation of {@link ParseOptions}
|
||||
*/
|
||||
public record ParseOptionsImpl(int maxLineLength, int maxLines, Font defaultFont) implements ParseOptions {
|
||||
public ParseOptionsImpl {
|
||||
if (maxLineLength <= 0) {
|
||||
throw new IllegalArgumentException("maxLineLength must be > 0");
|
||||
}
|
||||
if (maxLines <= 0) {
|
||||
throw new IllegalArgumentException("maxLines must be > 0");
|
||||
}
|
||||
Objects.requireNonNull(defaultFont);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.converter.impl;
|
||||
|
||||
import com.github.gtache.autosubtitle.VideoInfo;
|
||||
import com.github.gtache.autosubtitle.subtitle.Subtitle;
|
||||
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.FormatOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseException;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
|
||||
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleCollectionImpl;
|
||||
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleImpl;
|
||||
@@ -12,6 +13,7 @@ import com.github.gtache.autosubtitle.translation.Translator;
|
||||
import javax.inject.Inject;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
@@ -22,6 +24,9 @@ import static java.util.Objects.requireNonNull;
|
||||
*/
|
||||
public class SRTSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
|
||||
|
||||
private static final Pattern ARROW_PATTERN = Pattern.compile(" --> ");
|
||||
private static final Pattern DOUBLE_NEWLINE_PATTERN = Pattern.compile("\n\n");
|
||||
|
||||
private final Translator<?> translator;
|
||||
|
||||
@Inject
|
||||
@@ -30,7 +35,7 @@ public class SRTSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String format(final SubtitleCollection<?> collection, final VideoInfo videoInfo) {
|
||||
public String format(final SubtitleCollection<?> collection, final FormatOptions options) {
|
||||
final var subtitles = collection.subtitles().stream().sorted(Comparator.comparing(Subtitle::start).thenComparing(Subtitle::end)).toList();
|
||||
return IntStream.range(0, subtitles.size()).mapToObj(i -> {
|
||||
final var subtitle = subtitles.get(i);
|
||||
@@ -40,24 +45,14 @@ public class SRTSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
|
||||
}).collect(Collectors.joining("\n\n")) + "\n";
|
||||
}
|
||||
|
||||
private static String formatTime(final long time) {
|
||||
final var millisPerHour = 3600000;
|
||||
final var millisPerMinute = 60000;
|
||||
final var hours = time / millisPerHour;
|
||||
final var minutes = (time - hours * millisPerHour) / millisPerMinute;
|
||||
final var seconds = (time - hours * millisPerHour - minutes * millisPerMinute) / 1000;
|
||||
final var millis = time - hours * millisPerHour - minutes * millisPerMinute - seconds * 1000;
|
||||
return String.format("%02d:%02d:%02d,%03d", hours, minutes, seconds, millis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubtitleCollectionImpl<SubtitleImpl> parse(final String content) throws ParseException {
|
||||
public SubtitleCollectionImpl<SubtitleImpl> parse(final String content, final ParseOptions options) throws ParseException {
|
||||
try {
|
||||
final var elements = content.split("\n\n");
|
||||
final var elements = DOUBLE_NEWLINE_PATTERN.split(content);
|
||||
final var subtitles = Arrays.stream(elements).filter(element -> !element.isBlank()).map(element -> {
|
||||
final var lines = element.split("\n");
|
||||
final var time = lines[1];
|
||||
final var timeSplit = time.split(" --> ");
|
||||
final var timeSplit = ARROW_PATTERN.split(time);
|
||||
final var startTimeStr = timeSplit[0];
|
||||
final var endTimeStr = timeSplit[1];
|
||||
final var start = parseTime(startTimeStr);
|
||||
@@ -82,6 +77,16 @@ public class SRTSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
|
||||
return (hours * 3600L + minutes * 60L + seconds) * 1000 + millis;
|
||||
}
|
||||
|
||||
private static String formatTime(final long time) {
|
||||
final var millisPerHour = 3600000;
|
||||
final var millisPerMinute = 60000;
|
||||
final var hours = time / millisPerHour;
|
||||
final var minutes = (time - hours * millisPerHour) / millisPerMinute;
|
||||
final var seconds = (time - hours * millisPerHour - minutes * millisPerMinute) / 1000;
|
||||
final var millis = time - hours * millisPerHour - minutes * millisPerMinute - seconds * 1000;
|
||||
return String.format("%02d:%02d:%02d,%03d", hours, minutes, seconds, millis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String formatName() {
|
||||
return "srt";
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.extractor.impl;
|
||||
|
||||
import com.github.gtache.autosubtitle.Language;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModel;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Implementation of {@link ExtractOptions}
|
||||
*/
|
||||
public record ExtractOptionsImpl(Language language, ExtractionModel model,
|
||||
ParseOptions parseOptions) implements ExtractOptions {
|
||||
|
||||
public ExtractOptionsImpl {
|
||||
Objects.requireNonNull(language);
|
||||
Objects.requireNonNull(model);
|
||||
Objects.requireNonNull(parseOptions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.impl;
|
||||
|
||||
import com.github.gtache.autosubtitle.subtitle.ExportOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.OutputFormat;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.FormatOptions;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Implementation of {@link ExportOptions}
|
||||
*/
|
||||
public record ExportOptionsImpl(OutputFormat outputFormat, FormatOptions formatOptions) implements ExportOptions {
|
||||
|
||||
public ExportOptionsImpl {
|
||||
Objects.requireNonNull(outputFormat);
|
||||
Objects.requireNonNull(formatOptions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.impl;
|
||||
|
||||
import com.github.gtache.autosubtitle.subtitle.ImportOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseOptions;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* Implementation of {@link ImportOptions}
|
||||
*/
|
||||
public record ImportOptionsImpl(ParseOptions parseOptions) implements ImportOptions {
|
||||
public ImportOptionsImpl {
|
||||
requireNonNull(parseOptions);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
@@ -17,7 +16,7 @@ public record SubtitleCollectionImpl<T extends Subtitle>(String text, Collection
|
||||
Language language) implements SubtitleCollection<T> {
|
||||
|
||||
public SubtitleCollectionImpl {
|
||||
Objects.requireNonNull(text);
|
||||
requireNonNull(text);
|
||||
subtitles = List.copyOf(subtitles);
|
||||
requireNonNull(language);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.impl;
|
||||
|
||||
import com.github.gtache.autosubtitle.Language;
|
||||
import com.github.gtache.autosubtitle.VideoInfo;
|
||||
import com.github.gtache.autosubtitle.archive.Archiver;
|
||||
import com.github.gtache.autosubtitle.archive.ArchiverProvider;
|
||||
import com.github.gtache.autosubtitle.subtitle.ExportOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.ImportOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
|
||||
import com.github.gtache.autosubtitle.subtitle.SubtitleImporterExporter;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.FormatException;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseException;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverterProvider;
|
||||
@@ -40,19 +42,19 @@ public class SubtitleImporterExporterImpl implements SubtitleImporterExporter<Su
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Language, SubtitleCollection<SubtitleImpl>> importSubtitles(final Path file) throws IOException, ParseException {
|
||||
public Map<Language, SubtitleCollection<SubtitleImpl>> importSubtitles(final Path file, final ImportOptions options) throws IOException, ParseException {
|
||||
final var fileName = file.getFileName().toString();
|
||||
final var extension = fileName.substring(fileName.lastIndexOf('.') + 1);
|
||||
if (archiverProvider.getArchiver(extension) == null) {
|
||||
final var loaded = loadSingleFile(file);
|
||||
final var loaded = loadSingleFile(file, options);
|
||||
logger.info("Loaded {}", file);
|
||||
return Map.of(loaded.language(), loaded);
|
||||
} else {
|
||||
return loadArchive(file);
|
||||
return loadArchive(file, options);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Language, SubtitleCollection<SubtitleImpl>> loadArchive(final Path file) throws IOException, ParseException {
|
||||
private Map<Language, SubtitleCollection<SubtitleImpl>> loadArchive(final Path file, final ImportOptions options) throws IOException, ParseException {
|
||||
final var fileName = file.getFileName().toString();
|
||||
final var extension = fileName.substring(fileName.lastIndexOf('.') + 1);
|
||||
final var archiver = archiverProvider.getArchiver(extension);
|
||||
@@ -64,7 +66,7 @@ public class SubtitleImporterExporterImpl implements SubtitleImporterExporter<Su
|
||||
}
|
||||
final var map = new EnumMap<Language, SubtitleCollection<SubtitleImpl>>(Language.class);
|
||||
for (final var path : files) {
|
||||
final var loaded = loadSingleFile(path);
|
||||
final var loaded = loadSingleFile(path, options);
|
||||
map.put(loaded.language(), loaded);
|
||||
Files.deleteIfExists(path);
|
||||
}
|
||||
@@ -73,39 +75,39 @@ public class SubtitleImporterExporterImpl implements SubtitleImporterExporter<Su
|
||||
return map;
|
||||
}
|
||||
|
||||
private SubtitleCollection<SubtitleImpl> loadSingleFile(final Path file) throws ParseException {
|
||||
private SubtitleCollection<SubtitleImpl> loadSingleFile(final Path file, final ImportOptions options) throws ParseException {
|
||||
final var fileName = file.getFileName().toString();
|
||||
final var extension = fileName.substring(fileName.lastIndexOf('.') + 1);
|
||||
final var parser = converterProvider.getConverter(extension);
|
||||
if (parser == null) {
|
||||
throw new ParseException("No converter found for " + file);
|
||||
} else {
|
||||
final var parsed = parser.parse(file);
|
||||
final var parsed = parser.parse(file, options.parseOptions());
|
||||
return new SubtitleCollectionImpl<>(parsed.text(), parsed.subtitles().stream().map(SubtitleImpl::new).toList(), parsed.language());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportSubtitles(final Collection<? extends SubtitleCollection<?>> collections, final VideoInfo videoInfo, final Path file) throws IOException {
|
||||
public void exportSubtitles(final Collection<? extends SubtitleCollection<?>> collections, final ExportOptions options, final Path file) throws IOException {
|
||||
final var fileName = file.getFileName().toString();
|
||||
final var extension = fileName.substring(fileName.lastIndexOf('.') + 1);
|
||||
if (archiverProvider.getArchiver(extension) != null) {
|
||||
saveArchive(file, collections, videoInfo);
|
||||
saveArchive(file, collections, options);
|
||||
} else if (collections.size() == 1) {
|
||||
saveSingleFile(file, collections.iterator().next(), videoInfo);
|
||||
saveSingleFile(file, collections.iterator().next(), options);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Cannot export multiple collections to a non-archive file : " + file);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveArchive(final Path file, final Iterable<? extends SubtitleCollection<?>> collections, final VideoInfo videoInfo) throws IOException {
|
||||
private void saveArchive(final Path file, final Iterable<? extends SubtitleCollection<?>> collections, final ExportOptions options) throws IOException {
|
||||
final var fileName = file.getFileName().toString();
|
||||
final var extension = fileName.substring(fileName.lastIndexOf('.') + 1);
|
||||
final var archiver = archiverProvider.getArchiver(extension);
|
||||
final var tempDir = Files.createTempDirectory("autosubtitle");
|
||||
for (final var collection : collections) {
|
||||
final var subtitleFile = tempDir.resolve(collection.language().name().toLowerCase() + ".json");
|
||||
saveSingleFile(subtitleFile, collection, videoInfo);
|
||||
saveSingleFile(subtitleFile, collection, options);
|
||||
}
|
||||
final var files = new ArrayList<Path>();
|
||||
try (final var stream = Files.list(tempDir)) {
|
||||
@@ -119,16 +121,20 @@ public class SubtitleImporterExporterImpl implements SubtitleImporterExporter<Su
|
||||
logger.info("Saved {}", file);
|
||||
}
|
||||
|
||||
private void saveSingleFile(final Path file, final SubtitleCollection<?> collection, final VideoInfo videoInfo) throws IOException {
|
||||
private void saveSingleFile(final Path file, final SubtitleCollection<?> collection, final ExportOptions options) throws IOException {
|
||||
final var fileName = file.getFileName().toString();
|
||||
final var extension = fileName.substring(fileName.lastIndexOf('.') + 1);
|
||||
final var converter = converterProvider.getConverter(extension);
|
||||
if (converter == null) {
|
||||
throw new IOException("No converter found for " + file);
|
||||
} else {
|
||||
final var string = converter.format(collection, videoInfo);
|
||||
Files.writeString(file, string);
|
||||
logger.info("Saved {}", file);
|
||||
try {
|
||||
final var string = converter.format(collection, options.formatOptions());
|
||||
Files.writeString(file, string);
|
||||
logger.info("Saved {}", file);
|
||||
} catch (final FormatException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,27 +11,27 @@ import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class TestZipDecompresser {
|
||||
class TestZipArchiver {
|
||||
|
||||
private final ZipDecompresser zipDecompresser;
|
||||
private final ZipArchiver zipArchiver;
|
||||
|
||||
TestZipDecompresser() {
|
||||
this.zipDecompresser = new ZipDecompresser();
|
||||
TestZipArchiver() {
|
||||
this.zipArchiver = new ZipArchiver();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsPathSupported() {
|
||||
assertTrue(zipDecompresser.isPathSupported(Path.of("test.zip")));
|
||||
assertFalse(zipDecompresser.isPathSupported(Path.of("test")));
|
||||
assertFalse(zipDecompresser.isPathSupported(Path.of("test.txt")));
|
||||
assertFalse(zipDecompresser.isPathSupported(Path.of("test.zip2")));
|
||||
assertTrue(zipArchiver.isPathSupported(Path.of("test.zip")));
|
||||
assertFalse(zipArchiver.isPathSupported(Path.of("test")));
|
||||
assertFalse(zipArchiver.isPathSupported(Path.of("test.txt")));
|
||||
assertFalse(zipArchiver.isPathSupported(Path.of("test.zip2")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCompress() {
|
||||
final var paths = List.of(Paths.get("file.txt"));
|
||||
final var target = Paths.get("target");
|
||||
assertThrows(UnsupportedOperationException.class, () -> zipDecompresser.compress(paths, target));
|
||||
assertThrows(UnsupportedOperationException.class, () -> zipArchiver.compress(paths, target));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -43,7 +43,7 @@ class TestZipDecompresser {
|
||||
}
|
||||
Files.copy(in, file);
|
||||
}
|
||||
zipDecompresser.decompress(file, tempDir);
|
||||
zipArchiver.decompress(file, tempDir);
|
||||
final var inTxt = tempDir.resolve("in.txt");
|
||||
final var bin = tempDir.resolve("bin");
|
||||
final var binTxt = bin.resolve("bin.txt");
|
||||
@@ -64,6 +64,6 @@ class TestZipDecompresser {
|
||||
void testIllegal() {
|
||||
final var source = Paths.get("source");
|
||||
final var target = Paths.get("target");
|
||||
assertThrows(IllegalArgumentException.class, () -> zipDecompresser.decompress(source, target));
|
||||
assertThrows(IllegalArgumentException.class, () -> zipArchiver.decompress(source, target));
|
||||
}
|
||||
}
|
||||
@@ -26,25 +26,25 @@ class TestArchitecture {
|
||||
|
||||
@Test
|
||||
void testGetArchitecture() {
|
||||
for (final var value : Architecture.values()) {
|
||||
for (final var value : values()) {
|
||||
System.setProperty("os.arch", value.name());
|
||||
assertEquals(value, Architecture.getArchitecture());
|
||||
assertEquals(value, getArchitecture());
|
||||
}
|
||||
System.setProperty("os.arch", "any");
|
||||
assertEquals(UNKNOWN, Architecture.getArchitecture());
|
||||
assertEquals(UNKNOWN, getArchitecture());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetArchitectureName() {
|
||||
assertEquals(I386, Architecture.getArchitecture("i386"));
|
||||
assertEquals(I386, Architecture.getArchitecture("I386"));
|
||||
assertEquals(I386, getArchitecture("i386"));
|
||||
assertEquals(I386, getArchitecture("I386"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsAMD64() {
|
||||
final var expectedAMD64 = Set.of(X86, X86_64, AMD64);
|
||||
expectedAMD64.forEach(a -> assertTrue(a.isAMD64()));
|
||||
Arrays.stream(Architecture.values()).filter(a -> !expectedAMD64.contains(a))
|
||||
Arrays.stream(values()).filter(a -> !expectedAMD64.contains(a))
|
||||
.forEach(a -> assertFalse(a.isAMD64()));
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ class TestArchitecture {
|
||||
void testIsARM64() {
|
||||
final var expectedARM64 = Set.of(ARM64, ARMV8, ARMV9, AARCH64);
|
||||
expectedARM64.forEach(a -> assertTrue(a.isARM64()));
|
||||
Arrays.stream(Architecture.values()).filter(a -> !expectedARM64.contains(a))
|
||||
Arrays.stream(values()).filter(a -> !expectedARM64.contains(a))
|
||||
.forEach(a -> assertFalse(a.isARM64()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@ package com.github.gtache.autosubtitle.subtitle.converter.impl;
|
||||
import com.github.gtache.autosubtitle.Language;
|
||||
import com.github.gtache.autosubtitle.VideoInfo;
|
||||
import com.github.gtache.autosubtitle.subtitle.Subtitle;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.FormatOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseException;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.impl.FontImpl;
|
||||
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleCollectionImpl;
|
||||
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleImpl;
|
||||
@@ -15,9 +17,8 @@ import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
@@ -27,28 +28,28 @@ import static org.mockito.Mockito.when;
|
||||
class TestASSSubtitleConverter {
|
||||
|
||||
private final Translator<Subtitle> translator;
|
||||
private final Preferences preferences;
|
||||
private final FormatOptions formatOptions;
|
||||
private final ParseOptions parseOptions;
|
||||
private final Language language;
|
||||
private final VideoInfo videoInfo;
|
||||
private final String defaultFontName;
|
||||
private final int defaultFontSize;
|
||||
private final ASSSubtitleConverter converter;
|
||||
|
||||
TestASSSubtitleConverter(@Mock final Translator<Subtitle> translator,
|
||||
@Mock final Preferences preferences,
|
||||
@Mock final Language language,
|
||||
@Mock final FormatOptions formatOptions,
|
||||
@Mock final ParseOptions parseOptions,
|
||||
@Mock final VideoInfo videoInfo) {
|
||||
this.translator = Objects.requireNonNull(translator);
|
||||
this.preferences = Objects.requireNonNull(preferences);
|
||||
this.language = Objects.requireNonNull(language);
|
||||
this.videoInfo = Objects.requireNonNull(videoInfo);
|
||||
this.defaultFontName = "Arial";
|
||||
this.defaultFontSize = 12;
|
||||
this.converter = new ASSSubtitleConverter(translator, preferences, defaultFontName, defaultFontSize);
|
||||
this.translator = requireNonNull(translator);
|
||||
this.language = requireNonNull(language);
|
||||
this.formatOptions = requireNonNull(formatOptions);
|
||||
this.parseOptions = requireNonNull(parseOptions);
|
||||
this.videoInfo = requireNonNull(videoInfo);
|
||||
this.converter = new ASSSubtitleConverter(translator);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
when(formatOptions.videoInfo()).thenReturn(videoInfo);
|
||||
when(videoInfo.width()).thenReturn(1920);
|
||||
when(videoInfo.height()).thenReturn(1080);
|
||||
when(translator.getLanguage(anyString())).thenReturn(language);
|
||||
@@ -69,7 +70,7 @@ class TestASSSubtitleConverter {
|
||||
|
||||
[Events]
|
||||
Format: Start, End, Style, Text
|
||||
Dialogue: 0:00:00.00,0:00:00.41,Arial12,Test ?
|
||||
Dialogue: 00:00:00.00,00:00:00.41,Arial12,Test ?
|
||||
Dialogue: 123:45:54.32,124:00:00.00,Times New Roman13,Test2.
|
||||
""";
|
||||
|
||||
@@ -82,8 +83,8 @@ class TestASSSubtitleConverter {
|
||||
final var subtitle1 = new SubtitleImpl("Test ?", start1, end1, arial, null);
|
||||
final var subtitle2 = new SubtitleImpl("Test2.", start2, end2, times, null);
|
||||
final var subtitles = new SubtitleCollectionImpl<>(subtitle1.content() + subtitle2.content(), Arrays.asList(subtitle1, subtitle2), language);
|
||||
assertEquals(subtitles, converter.parse(in));
|
||||
assertEquals(in, converter.format(subtitles, videoInfo));
|
||||
assertEquals(subtitles, converter.parse(in, parseOptions));
|
||||
assertEquals(in, converter.format(subtitles, formatOptions));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -114,7 +115,7 @@ class TestASSSubtitleConverter {
|
||||
final var subtitle1 = new SubtitleImpl("Test ?", start1, end1, arial, null);
|
||||
final var subtitle2 = new SubtitleImpl("Test2.", start2, end2, times, null);
|
||||
final var subtitles = new SubtitleCollectionImpl<>(subtitle1.content() + subtitle2.content(), Arrays.asList(subtitle1, subtitle2), language);
|
||||
assertEquals(subtitles, converter.parse(in));
|
||||
assertEquals(subtitles, converter.parse(in, parseOptions));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -125,7 +126,7 @@ class TestASSSubtitleConverter {
|
||||
test1 test2
|
||||
test3 test4
|
||||
""";
|
||||
assertThrows(ParseException.class, () -> converter.parse(in));
|
||||
assertThrows(ParseException.class, () -> converter.parse(in, parseOptions));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -135,9 +136,6 @@ class TestASSSubtitleConverter {
|
||||
|
||||
@Test
|
||||
void testIllegal() {
|
||||
assertThrows(NullPointerException.class, () -> new ASSSubtitleConverter(null, preferences, defaultFontName, defaultFontSize));
|
||||
assertThrows(NullPointerException.class, () -> new ASSSubtitleConverter(translator, null, defaultFontName, defaultFontSize));
|
||||
assertThrows(NullPointerException.class, () -> new ASSSubtitleConverter(translator, preferences, null, defaultFontSize));
|
||||
assertThrows(IllegalArgumentException.class, () -> new ASSSubtitleConverter(translator, preferences, defaultFontName, 0));
|
||||
assertThrows(NullPointerException.class, () -> new ASSSubtitleConverter(null));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.converter.impl;
|
||||
|
||||
import com.github.gtache.autosubtitle.VideoInfo;
|
||||
import com.github.gtache.autosubtitle.subtitle.Font;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.FormatOptions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class TestFormatOptionsImpl {
|
||||
|
||||
private final VideoInfo videoInfo;
|
||||
private final Font defaultFont;
|
||||
private final FormatOptions formatOptions;
|
||||
|
||||
TestFormatOptionsImpl(@Mock final VideoInfo videoInfo, @Mock final Font defaultFont) {
|
||||
this.videoInfo = Objects.requireNonNull(videoInfo);
|
||||
this.defaultFont = Objects.requireNonNull(defaultFont);
|
||||
this.formatOptions = new FormatOptionsImpl(videoInfo, defaultFont);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetters() {
|
||||
assertEquals(videoInfo, formatOptions.videoInfo());
|
||||
assertEquals(defaultFont, formatOptions.defaultFont());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIllegal() {
|
||||
assertThrows(NullPointerException.class, () -> new FormatOptionsImpl(null, defaultFont));
|
||||
assertThrows(NullPointerException.class, () -> new FormatOptionsImpl(videoInfo, null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.converter.impl;
|
||||
|
||||
import com.github.gtache.autosubtitle.subtitle.Font;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseOptions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class TestParseOptionsImpl {
|
||||
|
||||
private final int maxLineLength;
|
||||
private final int maxLines;
|
||||
private final Font defaultFont;
|
||||
private final ParseOptions parseOptions;
|
||||
|
||||
TestParseOptionsImpl(@Mock final Font defaultFont) {
|
||||
this.defaultFont = Objects.requireNonNull(defaultFont);
|
||||
this.maxLineLength = 1;
|
||||
this.maxLines = 1;
|
||||
this.parseOptions = new ParseOptionsImpl(maxLineLength, maxLines, defaultFont);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetters() {
|
||||
assertEquals(maxLineLength, parseOptions.maxLineLength());
|
||||
assertEquals(maxLines, parseOptions.maxLines());
|
||||
assertEquals(defaultFont, parseOptions.defaultFont());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIllegal() {
|
||||
assertThrows(IllegalArgumentException.class, () -> new ParseOptionsImpl(0, 1, defaultFont));
|
||||
assertThrows(IllegalArgumentException.class, () -> new ParseOptionsImpl(1, 0, defaultFont));
|
||||
assertThrows(NullPointerException.class, () -> new ParseOptionsImpl(1, 1, null));
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.converter.impl;
|
||||
|
||||
import com.github.gtache.autosubtitle.Language;
|
||||
import com.github.gtache.autosubtitle.VideoInfo;
|
||||
import com.github.gtache.autosubtitle.subtitle.Subtitle;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.FormatOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseException;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleCollectionImpl;
|
||||
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleImpl;
|
||||
import com.github.gtache.autosubtitle.translation.Translator;
|
||||
@@ -26,13 +27,16 @@ class TestSRTSubtitleConverter {
|
||||
|
||||
private final Translator<Subtitle> translator;
|
||||
private final Language language;
|
||||
private final VideoInfo videoInfo;
|
||||
private final FormatOptions formatOptions;
|
||||
private final ParseOptions parseOptions;
|
||||
private final SRTSubtitleConverter converter;
|
||||
|
||||
TestSRTSubtitleConverter(@Mock final Translator<Subtitle> translator, @Mock final Language language, @Mock final VideoInfo videoInfo) {
|
||||
TestSRTSubtitleConverter(@Mock final Translator<Subtitle> translator, @Mock final Language language,
|
||||
@Mock final FormatOptions formatOptions, @Mock final ParseOptions parseOptions) {
|
||||
this.translator = Objects.requireNonNull(translator);
|
||||
this.language = Objects.requireNonNull(language);
|
||||
this.videoInfo = Objects.requireNonNull(videoInfo);
|
||||
this.formatOptions = Objects.requireNonNull(formatOptions);
|
||||
this.parseOptions = Objects.requireNonNull(parseOptions);
|
||||
this.converter = new SRTSubtitleConverter(translator);
|
||||
}
|
||||
|
||||
@@ -62,8 +66,8 @@ class TestSRTSubtitleConverter {
|
||||
final var subtitle1 = new SubtitleImpl("test5 test6\ntest7 test8", start1, end1, null, null);
|
||||
final var subtitle2 = new SubtitleImpl("test1 test2\ntest3 test4", start2, end2, null, null);
|
||||
final var subtitles = new SubtitleCollectionImpl<>(subtitle1.content() + " " + subtitle2.content(), Arrays.asList(subtitle1, subtitle2), language);
|
||||
assertEquals(subtitles, converter.parse(in));
|
||||
assertEquals(in, converter.format(subtitles, videoInfo));
|
||||
assertEquals(subtitles, converter.parse(in, parseOptions));
|
||||
assertEquals(in, converter.format(subtitles, formatOptions));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -74,7 +78,7 @@ class TestSRTSubtitleConverter {
|
||||
test1 test2
|
||||
test3 test4
|
||||
""";
|
||||
assertThrows(ParseException.class, () -> converter.parse(in));
|
||||
assertThrows(ParseException.class, () -> converter.parse(in, parseOptions));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.extractor.impl;
|
||||
|
||||
import com.github.gtache.autosubtitle.Audio;
|
||||
import com.github.gtache.autosubtitle.Language;
|
||||
import com.github.gtache.autosubtitle.Video;
|
||||
import com.github.gtache.autosubtitle.subtitle.Subtitle;
|
||||
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
|
||||
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractEvent;
|
||||
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModel;
|
||||
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.extractor.SubtitleExtractorListener;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -56,12 +55,12 @@ class TestAbstractSubtitleExtractor {
|
||||
private static final class DummySubtitleExtractor extends AbstractSubtitleExtractor {
|
||||
|
||||
@Override
|
||||
public SubtitleCollection<Subtitle> extract(final Video video, final Language language, final ExtractionModel model) {
|
||||
public SubtitleCollection<Subtitle> extract(final Video video, final ExtractOptions options) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubtitleCollection<Subtitle> extract(final Audio audio, final Language language, final ExtractionModel model) {
|
||||
public SubtitleCollection<Subtitle> extract(final Audio audio, final ExtractOptions options) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.extractor.impl;
|
||||
|
||||
import com.github.gtache.autosubtitle.Language;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModel;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class TestExtractOptionsImpl {
|
||||
|
||||
private final Language language;
|
||||
private final ExtractionModel model;
|
||||
private final ParseOptions parseOptions;
|
||||
private final ExtractOptions extractOptions;
|
||||
|
||||
TestExtractOptionsImpl(@Mock final Language language, @Mock final ExtractionModel model, @Mock final ParseOptions parseOptions) {
|
||||
this.language = requireNonNull(language);
|
||||
this.model = requireNonNull(model);
|
||||
this.parseOptions = requireNonNull(parseOptions);
|
||||
this.extractOptions = new ExtractOptionsImpl(language, model, parseOptions);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetters() {
|
||||
assertEquals(language, extractOptions.language());
|
||||
assertEquals(model, extractOptions.model());
|
||||
assertEquals(parseOptions, extractOptions.parseOptions());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIllegal() {
|
||||
assertThrows(NullPointerException.class, () -> new ExtractOptionsImpl(null, model, parseOptions));
|
||||
assertThrows(NullPointerException.class, () -> new ExtractOptionsImpl(language, null, parseOptions));
|
||||
assertThrows(NullPointerException.class, () -> new ExtractOptionsImpl(language, model, null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.impl;
|
||||
|
||||
import com.github.gtache.autosubtitle.subtitle.ExportOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.OutputFormat;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.FormatOptions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class TestExportOptionsImpl {
|
||||
|
||||
private final OutputFormat outputFormat;
|
||||
private final FormatOptions formatOptions;
|
||||
private final ExportOptions exportOptions;
|
||||
|
||||
TestExportOptionsImpl(@Mock final OutputFormat outputFormat, @Mock final FormatOptions formatOptions) {
|
||||
this.outputFormat = requireNonNull(outputFormat);
|
||||
this.formatOptions = requireNonNull(formatOptions);
|
||||
this.exportOptions = new ExportOptionsImpl(outputFormat, formatOptions);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetters() {
|
||||
assertEquals(outputFormat, exportOptions.outputFormat());
|
||||
assertEquals(formatOptions, exportOptions.formatOptions());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIllegal() {
|
||||
assertThrows(NullPointerException.class, () -> new ExportOptionsImpl(null, formatOptions));
|
||||
assertThrows(NullPointerException.class, () -> new ExportOptionsImpl(outputFormat, null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.impl;
|
||||
|
||||
import com.github.gtache.autosubtitle.subtitle.ImportOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseOptions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class TestImportOptionsImpl {
|
||||
|
||||
private final ParseOptions parseOptions;
|
||||
private final ImportOptions importOptions;
|
||||
|
||||
TestImportOptionsImpl(@Mock final ParseOptions parseOptions) {
|
||||
this.parseOptions = requireNonNull(parseOptions);
|
||||
this.importOptions = new ImportOptionsImpl(parseOptions);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetters() {
|
||||
assertEquals(parseOptions, importOptions.parseOptions());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIllegal() {
|
||||
assertThrows(NullPointerException.class, () -> new ImportOptionsImpl(null));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.impl;
|
||||
|
||||
import com.github.gtache.autosubtitle.Language;
|
||||
import com.github.gtache.autosubtitle.VideoInfo;
|
||||
import com.github.gtache.autosubtitle.archive.Archiver;
|
||||
import com.github.gtache.autosubtitle.archive.ArchiverProvider;
|
||||
import com.github.gtache.autosubtitle.subtitle.ExportOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.ImportOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
|
||||
import com.github.gtache.autosubtitle.subtitle.SubtitleImporterExporter;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.FormatException;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.FormatOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseException;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverterProvider;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
@@ -33,25 +38,38 @@ class TestSubtitleImporterExporterImpl {
|
||||
private final ArchiverProvider archiverProvider;
|
||||
private final SubtitleConverterProvider converterProvider;
|
||||
private final SubtitleImporterExporter<SubtitleImpl> subtitleImporterExporter;
|
||||
private final VideoInfo videoInfo;
|
||||
private final ExportOptions exportOptions;
|
||||
private final FormatOptions formatOptions;
|
||||
private final ImportOptions importOptions;
|
||||
private final ParseOptions parseOptions;
|
||||
private final Path path;
|
||||
private final SubtitleCollection<SubtitleImpl> firstCollection;
|
||||
private final SubtitleCollection<SubtitleImpl> secondCollection;
|
||||
|
||||
TestSubtitleImporterExporterImpl(@Mock final ArchiverProvider archiverProvider,
|
||||
@Mock final SubtitleConverterProvider converterProvider,
|
||||
@Mock final VideoInfo videoInfo,
|
||||
@Mock final ExportOptions exportOptions, @Mock final FormatOptions formatOptions,
|
||||
@Mock final ImportOptions importOptions, @Mock final ParseOptions parseOptions,
|
||||
@Mock final SubtitleCollection<SubtitleImpl> firstCollection,
|
||||
@Mock final SubtitleCollection<SubtitleImpl> secondCollection) {
|
||||
this.archiverProvider = requireNonNull(archiverProvider);
|
||||
this.converterProvider = requireNonNull(converterProvider);
|
||||
this.videoInfo = requireNonNull(videoInfo);
|
||||
this.exportOptions = requireNonNull(exportOptions);
|
||||
this.formatOptions = requireNonNull(formatOptions);
|
||||
this.importOptions = requireNonNull(importOptions);
|
||||
this.parseOptions = requireNonNull(parseOptions);
|
||||
this.subtitleImporterExporter = new SubtitleImporterExporterImpl(archiverProvider, converterProvider);
|
||||
this.path = Paths.get("out.out");
|
||||
this.firstCollection = requireNonNull(firstCollection);
|
||||
this.secondCollection = requireNonNull(secondCollection);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
when(exportOptions.formatOptions()).thenReturn(formatOptions);
|
||||
when(importOptions.parseOptions()).thenReturn(parseOptions);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testImportSubtitlesArchive() throws IOException, ParseException {
|
||||
final var archiver = mock(Archiver.class);
|
||||
@@ -76,7 +94,7 @@ class TestSubtitleImporterExporterImpl {
|
||||
when(firstCollection.subtitles()).thenReturn(subtitles);
|
||||
when(firstCollection.text()).thenReturn("text");
|
||||
when(firstCollection.language()).thenReturn(Language.EN);
|
||||
when(converter1.parse(any(Path.class))).thenReturn(firstCollection);
|
||||
when(converter1.parse(any(Path.class), eq(parseOptions))).thenReturn(firstCollection);
|
||||
|
||||
final var s3 = new SubtitleImpl("test3", 0, 100, null, null);
|
||||
final var s4 = new SubtitleImpl("test4", 100, 200, null, null);
|
||||
@@ -84,9 +102,9 @@ class TestSubtitleImporterExporterImpl {
|
||||
when(secondCollection.subtitles()).thenReturn(subtitles2);
|
||||
when(secondCollection.text()).thenReturn("text2");
|
||||
when(secondCollection.language()).thenReturn(Language.FR);
|
||||
when(converter2.parse(any(Path.class))).thenReturn(secondCollection);
|
||||
when(converter2.parse(any(Path.class), eq(parseOptions))).thenReturn(secondCollection);
|
||||
|
||||
final var result = subtitleImporterExporter.importSubtitles(path);
|
||||
final var result = subtitleImporterExporter.importSubtitles(path, importOptions);
|
||||
|
||||
assertEquals(2, result.size());
|
||||
final var collection1 = result.get(Language.EN);
|
||||
@@ -103,7 +121,7 @@ class TestSubtitleImporterExporterImpl {
|
||||
void testImportSubtitlesSingle() throws IOException, ParseException {
|
||||
final var converter = mock(SubtitleConverter.class);
|
||||
when(converterProvider.getConverter("out")).thenReturn(converter);
|
||||
when(converter.parse(path)).thenReturn(firstCollection);
|
||||
when(converter.parse(path, parseOptions)).thenReturn(firstCollection);
|
||||
final var s1 = new SubtitleImpl("test", 0, 100, null, null);
|
||||
final var s2 = new SubtitleImpl("test2", 100, 200, null, null);
|
||||
final var subtitles = List.of(s1, s2);
|
||||
@@ -111,7 +129,7 @@ class TestSubtitleImporterExporterImpl {
|
||||
when(firstCollection.text()).thenReturn("text");
|
||||
when(firstCollection.language()).thenReturn(Language.EN);
|
||||
|
||||
final var result = subtitleImporterExporter.importSubtitles(path);
|
||||
final var result = subtitleImporterExporter.importSubtitles(path, importOptions);
|
||||
|
||||
assertEquals(1, result.size());
|
||||
final var collection = result.get(Language.EN);
|
||||
@@ -121,12 +139,12 @@ class TestSubtitleImporterExporterImpl {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testImportSubtitlesSingleParseException() throws IOException, ParseException {
|
||||
assertThrows(ParseException.class, () -> subtitleImporterExporter.importSubtitles(path));
|
||||
void testImportSubtitlesSingleParseException() {
|
||||
assertThrows(ParseException.class, () -> subtitleImporterExporter.importSubtitles(path, importOptions));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExportSubtitlesArchive(@TempDir final Path outputDir) throws IOException, ParseException {
|
||||
void testExportSubtitlesArchive(@TempDir final Path outputDir) throws IOException, FormatException {
|
||||
final var outputPath = outputDir.resolve("out.out");
|
||||
final var collection = List.of(firstCollection, secondCollection);
|
||||
final var archiver = mock(Archiver.class);
|
||||
@@ -135,13 +153,13 @@ class TestSubtitleImporterExporterImpl {
|
||||
when(converterProvider.getConverter("json")).thenReturn(converter);
|
||||
when(firstCollection.language()).thenReturn(Language.EN);
|
||||
when(secondCollection.language()).thenReturn(Language.FR);
|
||||
when(converter.format(firstCollection, videoInfo)).thenReturn("en");
|
||||
when(converter.format(secondCollection, videoInfo)).thenReturn("fr");
|
||||
when(converter.format(firstCollection, formatOptions)).thenReturn("en");
|
||||
when(converter.format(secondCollection, formatOptions)).thenReturn("fr");
|
||||
|
||||
subtitleImporterExporter.exportSubtitles(collection, videoInfo, outputPath);
|
||||
subtitleImporterExporter.exportSubtitles(collection, exportOptions, outputPath);
|
||||
|
||||
verify(converter).format(collection.get(0), videoInfo);
|
||||
verify(converter).format(collection.get(1), videoInfo);
|
||||
verify(converter).format(collection.get(0), formatOptions);
|
||||
verify(converter).format(collection.get(1), formatOptions);
|
||||
final var captor = ArgumentCaptor.forClass(List.class);
|
||||
verify(archiver).compress(captor.capture(), eq(outputPath));
|
||||
final var files = (List<Path>) captor.getValue();
|
||||
@@ -151,26 +169,26 @@ class TestSubtitleImporterExporterImpl {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExportSubtitlesSingle(@TempDir final Path outputDir) throws IOException {
|
||||
void testExportSubtitlesSingle(@TempDir final Path outputDir) throws IOException, FormatException {
|
||||
final var outputPath = outputDir.resolve("out.out");
|
||||
final var collection = List.of(firstCollection);
|
||||
final var converter = mock(SubtitleConverter.class);
|
||||
when(converterProvider.getConverter("out")).thenReturn(converter);
|
||||
final var expected = "expected";
|
||||
when(converter.format(collection.getFirst(), videoInfo)).thenReturn(expected);
|
||||
subtitleImporterExporter.exportSubtitles(collection, videoInfo, outputPath);
|
||||
when(converter.format(collection.getFirst(), formatOptions)).thenReturn(expected);
|
||||
subtitleImporterExporter.exportSubtitles(collection, exportOptions, outputPath);
|
||||
assertEquals(expected, Files.readString(outputPath));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExportSubtitlesSingleException() {
|
||||
final var collection = List.of(firstCollection);
|
||||
assertThrows(IOException.class, () -> subtitleImporterExporter.exportSubtitles(collection, videoInfo, path));
|
||||
assertThrows(IOException.class, () -> subtitleImporterExporter.exportSubtitles(collection, exportOptions, path));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExportSubtitlesMultipleException() {
|
||||
assertThrows(IllegalArgumentException.class, () -> subtitleImporterExporter.exportSubtitles(List.of(firstCollection, secondCollection), videoInfo, path));
|
||||
assertThrows(IllegalArgumentException.class, () -> subtitleImporterExporter.exportSubtitles(List.of(firstCollection, secondCollection), exportOptions, path));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user