Moves some modules and files, adds save subtitles

This commit is contained in:
Guillaume Tâche
2024-08-06 20:03:19 +02:00
parent 5efdaa6f63
commit c2efb71195
117 changed files with 989 additions and 353 deletions

219
.idea/csv-editor.xml generated Normal file
View File

@@ -0,0 +1,219 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CsvFileAttributes">
<option name="attributeMap">
<map>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-arccos.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-arccosh.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-arcsin.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-arcsinh.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-arctan.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-arctanh.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-cbrt.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-cos.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-cosh.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-exp.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-exp2.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-expm1.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-log.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-log10.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-log1p.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-log2.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-sin.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-sinh.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-tan.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\core\tests\data\umath-validation-set-tanh.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\random\tests\data\mt19937-testset-1.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\random\tests\data\mt19937-testset-2.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\random\tests\data\pcg64-testset-1.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\random\tests\data\pcg64-testset-2.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\random\tests\data\pcg64dxsm-testset-1.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\random\tests\data\pcg64dxsm-testset-2.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\random\tests\data\philox-testset-1.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\random\tests\data\philox-testset-2.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\random\tests\data\sfc64-testset-1.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
<entry key="\tools\whisper\whisper-env\Lib\site-packages\numpy\random\tests\data\sfc64-testset-2.csv">
<value>
<Attribute>
<option name="separator" value="," />
</Attribute>
</value>
</entry>
</map>
</option>
</component>
</project>

16
.idea/encodings.xml generated
View File

@@ -5,18 +5,26 @@
<file url="file://$PROJECT_DIR$/api/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/api/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/cli/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/cli/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/cli/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/cli/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/client/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/client/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/core/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/core/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/core/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/core/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/deepl/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/deepl/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/deepl/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/deepl/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ffmpeg/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/ffmpeg/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ffmpeg/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/ffmpeg/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/fx/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/gui/api/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/fx/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/gui/api/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/gui/core/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/gui/core/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/gui/fx/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/gui/fx/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/gui/run/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/gui/run/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/gui/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/gui/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/gui/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/gui/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/run/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/server/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/run/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/server/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/whisper/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/whisper/src/main/java" charset="UTF-8" />

View File

@@ -9,6 +9,11 @@ import java.util.Collection;
*/ */
public interface SubtitleCollection { public interface SubtitleCollection {
/**
* @return The whole text of the subtitles
*/
String text();
/** /**
* @return The subtitles * @return The subtitles
*/ */

View File

@@ -1,20 +0,0 @@
package com.github.gtache.autosubtitle.subtitle;
/**
* Converts subtitles to a specific format (e.g. srt, ssa, ass, ...)
*/
public interface SubtitleConverter {
/**
* Converts the subtitle collection
*
* @param collection The collection
* @return The converted subtitles as the content of a file
*/
String convert(final SubtitleCollection collection);
/**
* @return The name of the format
*/
String formatName();
}

View File

@@ -0,0 +1,19 @@
package com.github.gtache.autosubtitle.subtitle.converter;
/**
* Exception thrown when an error occurs during subtitle parsing
*/
public class ParseException extends Exception {
public ParseException(final String message) {
super(message);
}
public ParseException(final String message, final Throwable cause) {
super(message, cause);
}
public ParseException(final Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,62 @@
package com.github.gtache.autosubtitle.subtitle.converter;
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
/**
* Converts subtitles to a specific format (e.g. srt, ssa, ass, ...) and vice-versa
*/
public interface SubtitleConverter {
/**
* Converts the subtitle collection
*
* @param collection The collection
* @return The converted subtitles as the content of a file
*/
String format(final SubtitleCollection collection);
/**
* Parses a subtitle collection
*
* @param file The path to the file
* @return The subtitle collection
* @throws ParseException If an error occurred
*/
default SubtitleCollection parse(final Path file) throws ParseException {
try {
final var content = Files.readString(file);
return parse(content);
} catch (final IOException e) {
throw new ParseException(e);
}
}
/**
* Parses a subtitle collection
*
* @param content The content of the file
* @return The subtitle collection
* @throws ParseException If an error occurred
*/
SubtitleCollection parse(String content) throws ParseException;
/**
* Check if the parser can parse the given file
*
* @param file The path to the file
* @return True if the parser can parse the file
*/
default boolean canParse(final Path file) {
final var fileName = file.getFileName().toString();
return fileName.substring(fileName.lastIndexOf('.') + 1).equals(formatName());
}
/**
* @return The name of the format
*/
String formatName();
}

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.subtitle; package com.github.gtache.autosubtitle.subtitle.extractor;
/** /**
* Events that can be triggered by {@link SubtitleExtractor} * Events that can be triggered by {@link SubtitleExtractor}

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.subtitle; package com.github.gtache.autosubtitle.subtitle.extractor;
/** /**
* Exception thrown when an error occurs during subtitle extraction * Exception thrown when an error occurs during subtitle extraction

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.subtitle; package com.github.gtache.autosubtitle.subtitle.extractor;
/** /**
* An extraction model * An extraction model

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.subtitle; package com.github.gtache.autosubtitle.subtitle.extractor;
import java.util.List; import java.util.List;

View File

@@ -1,8 +1,9 @@
package com.github.gtache.autosubtitle.subtitle; package com.github.gtache.autosubtitle.subtitle.extractor;
import com.github.gtache.autosubtitle.Audio; import com.github.gtache.autosubtitle.Audio;
import com.github.gtache.autosubtitle.Language; import com.github.gtache.autosubtitle.Language;
import com.github.gtache.autosubtitle.Video; import com.github.gtache.autosubtitle.Video;
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
/** /**
* Extracts subtitles from a video or audio * Extracts subtitles from a video or audio

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.subtitle; package com.github.gtache.autosubtitle.subtitle.extractor;
/** /**
* Listener for {@link SubtitleExtractor} * Listener for {@link SubtitleExtractor}

View File

@@ -6,4 +6,6 @@ module com.github.gtache.autosubtitle.api {
exports com.github.gtache.autosubtitle.process; exports com.github.gtache.autosubtitle.process;
exports com.github.gtache.autosubtitle.setup; exports com.github.gtache.autosubtitle.setup;
exports com.github.gtache.autosubtitle.subtitle; exports com.github.gtache.autosubtitle.subtitle;
exports com.github.gtache.autosubtitle.subtitle.extractor;
exports com.github.gtache.autosubtitle.subtitle.converter;
} }

View File

@@ -3,16 +3,17 @@ package com.github.gtache.autosubtitle.modules.cli;
import com.github.gtache.autosubtitle.modules.deepl.DeepLModule; import com.github.gtache.autosubtitle.modules.deepl.DeepLModule;
import com.github.gtache.autosubtitle.modules.ffmpeg.FFmpegModule; import com.github.gtache.autosubtitle.modules.ffmpeg.FFmpegModule;
import com.github.gtache.autosubtitle.modules.impl.CoreModule; import com.github.gtache.autosubtitle.modules.impl.CoreModule;
import com.github.gtache.autosubtitle.modules.subtitles.impl.ConverterModule; import com.github.gtache.autosubtitle.modules.subtitle.extractor.whisper.WhisperExtractorModule;
import com.github.gtache.autosubtitle.modules.whisper.WhisperModule; import com.github.gtache.autosubtitle.modules.subtitle.impl.SubtitleModule;
import com.github.gtache.autosubtitle.subtitle.SubtitleConverter; import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
import dagger.Component; import dagger.Component;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.util.Map;
@Component(modules = {ConverterModule.class, CoreModule.class, DeepLModule.class, FFmpegModule.class, WhisperModule.class}) @Component(modules = {SubtitleModule.class, CoreModule.class, DeepLModule.class, FFmpegModule.class, WhisperExtractorModule.class})
@Singleton @Singleton
public interface CliComponent { public interface CliComponent {
SubtitleConverter getSubtitleConverter(); Map<String, SubtitleConverter> getSubtitleConverters();
} }

21
client/pom.xml Normal file
View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.gtache.autosubtitle</groupId>
<artifactId>autosubtitle</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>autosubtitle-client</artifactId>
<dependencies>
<dependency>
<groupId>com.github.gtache.autosubtitle</groupId>
<artifactId>autosubtitle-core</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,6 @@
/**
* Module for autosubtitle client
*/
module com.github.gtache.autosubtitle.client {
requires transitive com.github.gtache.autosubtitle.core;
}

View File

@@ -0,0 +1,20 @@
package com.github.gtache.autosubtitle.modules.subtitle.impl;
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
import com.github.gtache.autosubtitle.subtitle.converter.impl.SRTSubtitleConverter;
import dagger.Binds;
import dagger.Module;
import dagger.multibindings.IntoMap;
import dagger.multibindings.StringKey;
/**
* Dagger module for subtitles
*/
@Module
public interface SubtitleModule {
@Binds
@IntoMap
@StringKey("srt")
SubtitleConverter bindsSubtitleConverter(final SRTSubtitleConverter converter);
}

View File

@@ -1,16 +0,0 @@
package com.github.gtache.autosubtitle.modules.subtitles.impl;
import com.github.gtache.autosubtitle.subtitle.SubtitleConverter;
import com.github.gtache.autosubtitle.subtitle.impl.SRTSubtitleConverter;
import dagger.Binds;
import dagger.Module;
/**
* Dagger module for subtitle converter
*/
@Module
public interface ConverterModule {
@Binds
SubtitleConverter bindsSubtitleConverter(final SRTSubtitleConverter converter);
}

View File

@@ -0,0 +1,79 @@
package com.github.gtache.autosubtitle.subtitle.converter.impl;
import com.github.gtache.autosubtitle.Translator;
import com.github.gtache.autosubtitle.subtitle.Subtitle;
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
import com.github.gtache.autosubtitle.subtitle.converter.ParseException;
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleCollectionImpl;
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleImpl;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Arrays;
import java.util.Comparator;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static java.util.Objects.requireNonNull;
/**
* Converts subtitles to SRT format
*/
@Singleton
public class SRTSubtitleConverter implements SubtitleConverter {
private final Translator translator;
@Inject
SRTSubtitleConverter(final Translator translator) {
this.translator = requireNonNull(translator);
}
public String format(final SubtitleCollection collection) {
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);
return (i + 1) + "\n" +
subtitle.start() + " --> " + subtitle.end() + "\n" +
subtitle.content();
}).collect(Collectors.joining("\n\n"));
}
@Override
public SubtitleCollection parse(final String content) throws ParseException {
try {
final var elements = content.split("\n\n");
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 startTimeStr = timeSplit[0];
final var endTimeStr = timeSplit[1];
final var start = parseTime(startTimeStr);
final var end = parseTime(endTimeStr);
final var text = String.join(" ", Arrays.stream(lines).skip(2).toList());
return new SubtitleImpl(text, start, end, null, null);
}).toList();
final var text = subtitles.stream().map(Subtitle::content).collect(Collectors.joining(" "));
return new SubtitleCollectionImpl(content, subtitles, translator.getLanguage(text));
} catch (final Exception e) {
throw new ParseException(e);
}
}
private static long parseTime(final String timeStr) {
final var split = timeStr.split(":");
final var hours = Integer.parseInt(split[0]);
final var minutes = Integer.parseInt(split[1]);
final var secondsSplit = split[2].split(",");
final var seconds = Integer.parseInt(secondsSplit[0]);
final var millis = Integer.parseInt(secondsSplit[1]);
return (hours * 3600L + minutes * 60L + seconds) * 1000 + millis;
}
@Override
public String formatName() {
return "srt";
}
}

View File

@@ -1,8 +1,8 @@
package com.github.gtache.autosubtitle.subtitle.impl; package com.github.gtache.autosubtitle.subtitle.extractor.impl;
import com.github.gtache.autosubtitle.subtitle.ExtractEvent; import com.github.gtache.autosubtitle.subtitle.extractor.ExtractEvent;
import com.github.gtache.autosubtitle.subtitle.SubtitleExtractor; import com.github.gtache.autosubtitle.subtitle.extractor.SubtitleExtractor;
import com.github.gtache.autosubtitle.subtitle.SubtitleExtractorListener; import com.github.gtache.autosubtitle.subtitle.extractor.SubtitleExtractorListener;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;

View File

@@ -1,10 +1,10 @@
package com.github.gtache.autosubtitle.subtitle.impl; package com.github.gtache.autosubtitle.subtitle.extractor.impl;
import com.github.gtache.autosubtitle.subtitle.ExtractEvent; import com.github.gtache.autosubtitle.subtitle.extractor.ExtractEvent;
/** /**
* Implementation of {@link ExtractEvent} * Implementation of {@link ExtractEvent}
*/ */
public record ExtractEventImpl(String message, double progress) implements ExtractEvent { public record ExtractEventImpl(String message, double progress) implements ExtractEvent {
} }

View File

@@ -1,37 +0,0 @@
package com.github.gtache.autosubtitle.subtitle.impl;
import com.github.gtache.autosubtitle.subtitle.Subtitle;
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
import com.github.gtache.autosubtitle.subtitle.SubtitleConverter;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Comparator;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* Converts subtitles to SRT format
*/
@Singleton
public class SRTSubtitleConverter implements SubtitleConverter {
@Inject
SRTSubtitleConverter() {
}
public String convert(final SubtitleCollection collection) {
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);
return (i + 1) + "\n" +
subtitle.start() + " --> " + subtitle.end() + "\n" +
subtitle.content();
}).collect(Collectors.joining("\n\n"));
}
@Override
public String formatName() {
return "srt";
}
}

View File

@@ -14,5 +14,7 @@ module com.github.gtache.autosubtitle.core {
exports com.github.gtache.autosubtitle.modules.impl; exports com.github.gtache.autosubtitle.modules.impl;
exports com.github.gtache.autosubtitle.modules.setup.impl; exports com.github.gtache.autosubtitle.modules.setup.impl;
exports com.github.gtache.autosubtitle.modules.subtitles.impl; exports com.github.gtache.autosubtitle.subtitle.extractor.impl;
exports com.github.gtache.autosubtitle.subtitle.converter.impl;
exports com.github.gtache.autosubtitle.modules.subtitle.impl;
} }

View File

@@ -12,7 +12,7 @@ import com.github.gtache.autosubtitle.modules.ffmpeg.FFmpegBundledPath;
import com.github.gtache.autosubtitle.modules.ffmpeg.FFmpegSystemPath; import com.github.gtache.autosubtitle.modules.ffmpeg.FFmpegSystemPath;
import com.github.gtache.autosubtitle.process.impl.AbstractProcessRunner; import com.github.gtache.autosubtitle.process.impl.AbstractProcessRunner;
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection; import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
import com.github.gtache.autosubtitle.subtitle.SubtitleConverter; import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.SequencedMap; import java.util.SequencedMap;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@@ -40,10 +41,10 @@ public class FFmpegVideoConverter extends AbstractProcessRunner implements Video
private final SubtitleConverter subtitleConverter; private final SubtitleConverter subtitleConverter;
@Inject @Inject
FFmpegVideoConverter(@FFmpegBundledPath final Path bundledPath, @FFmpegSystemPath final Path systemPath, final SubtitleConverter subtitleConverter) { FFmpegVideoConverter(@FFmpegBundledPath final Path bundledPath, @FFmpegSystemPath final Path systemPath, final Map<String, SubtitleConverter> subtitleConverters) {
this.bundledPath = requireNonNull(bundledPath); this.bundledPath = requireNonNull(bundledPath);
this.systemPath = requireNonNull(systemPath); this.systemPath = requireNonNull(systemPath);
this.subtitleConverter = requireNonNull(subtitleConverter); this.subtitleConverter = requireNonNull(subtitleConverters.get("srt"));
} }
@Override @Override
@@ -143,7 +144,7 @@ public class FFmpegVideoConverter extends AbstractProcessRunner implements Video
private Path dumpSubtitles(final SubtitleCollection subtitles) throws IOException { private Path dumpSubtitles(final SubtitleCollection subtitles) throws IOException {
final var path = getTempFile("ass"); final var path = getTempFile("ass");
Files.writeString(path, subtitleConverter.convert(subtitles)); Files.writeString(path, subtitleConverter.format(subtitles));
return path; return path;
} }

21
gui/api/pom.xml Normal file
View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.gtache.autosubtitle</groupId>
<artifactId>autosubtitle-gui</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>autosubtitle-gui-api</artifactId>
<dependencies>
<dependency>
<groupId>com.github.gtache.autosubtitle</groupId>
<artifactId>autosubtitle-api</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1,7 +1,7 @@
package com.github.gtache.autosubtitle.gui; package com.github.gtache.autosubtitle.gui;
import com.github.gtache.autosubtitle.subtitle.ExtractionModel;
import com.github.gtache.autosubtitle.subtitle.OutputFormat; import com.github.gtache.autosubtitle.subtitle.OutputFormat;
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModel;
import java.util.List; import java.util.List;

View File

@@ -19,6 +19,20 @@ public interface WorkController {
*/ */
void loadVideo(final Path file); void loadVideo(final Path file);
/**
* Saves the subtitles to the given path
*
* @param file The output path
*/
void saveSubtitles(final Path file);
/**
* Loads a subtitles file
*
* @param file The path to the file
*/
void loadSubtitles(final Path file);
/** /**
* @return The model * @return The model
*/ */

View File

@@ -3,8 +3,8 @@ package com.github.gtache.autosubtitle.gui;
import com.github.gtache.autosubtitle.Language; import com.github.gtache.autosubtitle.Language;
import com.github.gtache.autosubtitle.Video; import com.github.gtache.autosubtitle.Video;
import com.github.gtache.autosubtitle.subtitle.EditableSubtitle; import com.github.gtache.autosubtitle.subtitle.EditableSubtitle;
import com.github.gtache.autosubtitle.subtitle.ExtractionModel;
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection; import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModel;
import java.util.List; import java.util.List;

View File

@@ -0,0 +1,7 @@
/**
* GUI module for auto-subtitle
*/
module com.github.gtache.autosubtitle.gui.api {
requires transitive com.github.gtache.autosubtitle.api;
exports com.github.gtache.autosubtitle.gui;
}

29
gui/core/pom.xml Normal file
View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.gtache.autosubtitle</groupId>
<artifactId>autosubtitle-gui</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>autosubtitle-gui-core</artifactId>
<dependencies>
<dependency>
<groupId>com.github.gtache.autosubtitle</groupId>
<artifactId>autosubtitle-gui-api</artifactId>
</dependency>
<dependency>
<groupId>com.github.gtache.autosubtitle</groupId>
<artifactId>autosubtitle-core</artifactId>
</dependency>
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.gui; package com.github.gtache.autosubtitle.gui.impl;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.gui.spi; package com.github.gtache.autosubtitle.gui.impl.spi;
import java.util.spi.ResourceBundleProvider; import java.util.spi.ResourceBundleProvider;

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.gui.spi; package com.github.gtache.autosubtitle.gui.impl.spi;
import java.util.spi.AbstractResourceBundleProvider; import java.util.spi.AbstractResourceBundleProvider;

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.gui.spi; package com.github.gtache.autosubtitle.gui.impl.spi;
import java.util.spi.ResourceBundleProvider; import java.util.spi.ResourceBundleProvider;

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.gui.spi; package com.github.gtache.autosubtitle.gui.impl.spi;
import java.util.spi.AbstractResourceBundleProvider; import java.util.spi.AbstractResourceBundleProvider;

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.gui.spi; package com.github.gtache.autosubtitle.gui.impl.spi;
import java.util.spi.ResourceBundleProvider; import java.util.spi.ResourceBundleProvider;

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.gui.spi; package com.github.gtache.autosubtitle.gui.impl.spi;
import java.util.spi.AbstractResourceBundleProvider; import java.util.spi.AbstractResourceBundleProvider;

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.gui.spi; package com.github.gtache.autosubtitle.gui.impl.spi;
import java.util.spi.ResourceBundleProvider; import java.util.spi.ResourceBundleProvider;

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.gui.spi; package com.github.gtache.autosubtitle.gui.impl.spi;
import java.util.spi.AbstractResourceBundleProvider; import java.util.spi.AbstractResourceBundleProvider;

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.modules.gui; package com.github.gtache.autosubtitle.modules.gui.impl;
import javax.inject.Qualifier; import javax.inject.Qualifier;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.modules.gui; package com.github.gtache.autosubtitle.modules.gui.impl;
import javax.inject.Qualifier; import javax.inject.Qualifier;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;

View File

@@ -1,6 +1,6 @@
package com.github.gtache.autosubtitle.modules.gui; package com.github.gtache.autosubtitle.modules.gui.impl;
import com.github.gtache.autosubtitle.gui.CombinedResourceBundle; import com.github.gtache.autosubtitle.gui.impl.CombinedResourceBundle;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
@@ -13,22 +13,22 @@ import java.util.ResourceBundle;
* Dagger module for GUI * Dagger module for GUI
*/ */
@Module @Module
public class GuiModule { public class GuiCoreModule {
@Provides @Provides
@Singleton @Singleton
static ResourceBundle providesBundle() { static ResourceBundle providesBundle() {
return new CombinedResourceBundle(ResourceBundle.getBundle("com.github.gtache.autosubtitle.gui.MainBundle"), return new CombinedResourceBundle(ResourceBundle.getBundle("com.github.gtache.autosubtitle.gui.impl.MainBundle"),
ResourceBundle.getBundle("com.github.gtache.autosubtitle.gui.SetupBundle"), ResourceBundle.getBundle("com.github.gtache.autosubtitle.gui.impl.SetupBundle"),
ResourceBundle.getBundle("com.github.gtache.autosubtitle.gui.WorkBundle"), ResourceBundle.getBundle("com.github.gtache.autosubtitle.gui.impl.WorkBundle"),
ResourceBundle.getBundle("com.github.gtache.autosubtitle.gui.ParametersBundle"), ResourceBundle.getBundle("com.github.gtache.autosubtitle.gui.impl.ParametersBundle"),
ResourceBundle.getBundle("com.github.gtache.autosubtitle.gui.MediaBundle")); ResourceBundle.getBundle("com.github.gtache.autosubtitle.gui.impl.MediaBundle"));
} }
@Provides @Provides
@Singleton @Singleton
@Play @Play
static byte[] providesPlayImage() { static byte[] providesPlayImage() {
try (final var in = GuiModule.class.getResourceAsStream("/com/github/gtache/autosubtitle/gui/play_64.png")) { try (final var in = GuiCoreModule.class.getResourceAsStream("/com/github/gtache/autosubtitle/gui/impl/play_64.png")) {
return in.readAllBytes(); return in.readAllBytes();
} catch (final IOException e) { } catch (final IOException e) {
throw new UncheckedIOException(e); throw new UncheckedIOException(e);
@@ -39,7 +39,7 @@ public class GuiModule {
@Singleton @Singleton
@Pause @Pause
static byte[] providesPauseImage() { static byte[] providesPauseImage() {
try (final var in = GuiModule.class.getResourceAsStream("/com/github/gtache/autosubtitle/gui/pause_64.png")) { try (final var in = GuiCoreModule.class.getResourceAsStream("/com/github/gtache/autosubtitle/gui/impl/pause_64.png")) {
return in.readAllBytes(); return in.readAllBytes();
} catch (final IOException e) { } catch (final IOException e) {
throw new UncheckedIOException(e); throw new UncheckedIOException(e);

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.modules.gui; package com.github.gtache.autosubtitle.modules.gui.impl;
import javax.inject.Qualifier; import javax.inject.Qualifier;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.modules.gui; package com.github.gtache.autosubtitle.modules.gui.impl;
import javax.inject.Qualifier; import javax.inject.Qualifier;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;

View File

@@ -0,0 +1,24 @@
import com.github.gtache.autosubtitle.gui.impl.spi.MainBundleProvider;
import com.github.gtache.autosubtitle.gui.impl.spi.MainBundleProviderImpl;
import com.github.gtache.autosubtitle.gui.impl.spi.ParametersBundleProvider;
import com.github.gtache.autosubtitle.gui.impl.spi.ParametersBundleProviderImpl;
import com.github.gtache.autosubtitle.gui.impl.spi.SetupBundleProvider;
import com.github.gtache.autosubtitle.gui.impl.spi.SetupBundleProviderImpl;
import com.github.gtache.autosubtitle.gui.impl.spi.WorkBundleProvider;
import com.github.gtache.autosubtitle.gui.impl.spi.WorkBundleProviderImpl;
/**
* Core gui module for autosubtitle
*/
module com.github.gtache.autosubtitle.gui.core {
requires transitive com.github.gtache.autosubtitle.gui.api;
requires transitive com.github.gtache.autosubtitle.core;
exports com.github.gtache.autosubtitle.gui.impl;
exports com.github.gtache.autosubtitle.gui.impl.spi;
exports com.github.gtache.autosubtitle.modules.gui.impl;
provides MainBundleProvider with MainBundleProviderImpl;
provides ParametersBundleProvider with ParametersBundleProviderImpl;
provides SetupBundleProvider with SetupBundleProviderImpl;
provides WorkBundleProvider with WorkBundleProviderImpl;
}

View File

@@ -4,14 +4,22 @@ work.button.export.soft.label=Export video...
work.button.export.soft.tooltip=Adds the subtitles to the video. This allows a video to have multiple subtitles and to enable them at will. work.button.export.soft.tooltip=Adds the subtitles to the video. This allows a video to have multiple subtitles and to enable them at will.
work.button.extract.label=Extract subtitles work.button.extract.label=Extract subtitles
work.button.file.label=Open video... work.button.file.label=Open video...
work.button.load.label=Load subtitles...
work.button.reset.label=Reset subtitles work.button.reset.label=Reset subtitles
work.button.subtitles.save.label=Save subtitles...
work.export.error.label=Error during the export : {0} work.export.error.label=Error during the export : {0}
work.export.error.title=Error exporting work.export.error.title=Error exporting
work.extract.error.label=Error extracting subtitles : {0} work.extract.error.label=Error extracting subtitles : {0}
work.extract.error.title=Error extracting work.extract.error.title=Error extracting
work.language.label=Video language work.language.label=Video language
work.load.error.label=Error loading video : {0} work.load.subtitles.error.label=Error loading subtitles : {0}
work.load.error.title=Error loading work.load.subtitles.error.title=Error loading
work.load.video.error.label=Error loading video : {0}
work.load.video.error.title=Error loading
work.save.subtitles.error.label=Error saving subtitles : {0}
work.save.subtitles.error.title=Error saving
work.save.subtitles.missing.converter.label=No converter found for {0}
work.save.subtitles.missing.converter.title=No converter found
work.status.exporting.label=Exporting... work.status.exporting.label=Exporting...
work.status.extracting.label=Extracting... work.status.extracting.label=Extracting...
work.status.idle.label=Idle work.status.idle.label=Idle

View File

@@ -4,14 +4,20 @@ work.button.export.soft.label=Exporter la vid\u00E9o...
work.button.export.soft.tooltip=Ajoute les sous-titres \u00E0 la vid\u00E9o. Cela permet d'avoir plusieurs pistes de sous-titres dans une m\u00EAme vid\u00E9o et de les activer comme d\u00E9sir\u00E9. work.button.export.soft.tooltip=Ajoute les sous-titres \u00E0 la vid\u00E9o. Cela permet d'avoir plusieurs pistes de sous-titres dans une m\u00EAme vid\u00E9o et de les activer comme d\u00E9sir\u00E9.
work.button.extract.label=Extraire les sous-titres work.button.extract.label=Extraire les sous-titres
work.button.file.label=Ouvrir une vid\u00E9o... work.button.file.label=Ouvrir une vid\u00E9o...
work.button.load.label=Charger des sous-titres...
work.button.reset.label=R\u00E9initialiser les sous-titres work.button.reset.label=R\u00E9initialiser les sous-titres
work.button.subtitles.save.label=Sauvegarder les sous-titres...
work.export.error.label=Erreur durant l''export : {0} work.export.error.label=Erreur durant l''export : {0}
work.export.error.title=Erreur d'export work.export.error.title=Erreur d'export
work.extract.error.label=Erreur durant l''extraction des sous-titres : {0} work.extract.error.label=Erreur durant l''extraction des sous-titres : {0}
work.extract.error.title=Erreur d'extraction work.extract.error.title=Erreur d'extraction
work.language.label=Language de la vid\u00E9o work.language.label=Language de la vid\u00E9o
work.load.error.label=Erreur lors du chargement de la vid\u00E9o : {0} work.load.subtitles.error.label=Erreur de chargement des sous-titres : {0}
work.load.error.title=Erreur de chargement work.load.subtitles.error.title=Erreur de chargement
work.load.video.error.label=Erreur lors du chargement de la vid\u00E9o : {0}
work.load.video.error.title=Erreur de chargement
work.save.subtitles.missing.converter.label=Aucun convertisseur trouv\u00E9 pour {0}
work.save.subtitles.missing.converter.title=Aucun convertisseur trouv\u00E9
work.status.exporting.label=Exportation en cours... work.status.exporting.label=Exportation en cours...
work.status.extracting.label=Extraction en cours... work.status.extracting.label=Extraction en cours...
work.status.idle.label=Idle work.status.idle.label=Idle

View File

@@ -5,24 +5,21 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>com.github.gtache.autosubtitle</groupId> <groupId>com.github.gtache.autosubtitle</groupId>
<artifactId>autosubtitle</artifactId> <artifactId>autosubtitle-gui</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</parent> </parent>
<artifactId>autosubtitle-fx</artifactId> <artifactId>autosubtitle-fx</artifactId>
<properties> <properties>
<controlsfx.version>11.2.1</controlsfx.version>
<javafx.version>22.0.1</javafx.version> <javafx.version>22.0.1</javafx.version>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.github.gtache.autosubtitle</groupId> <groupId>com.github.gtache.autosubtitle</groupId>
<artifactId>autosubtitle-gui</artifactId> <artifactId>autosubtitle-gui-core</artifactId>
</dependency>
<dependency>
<groupId>com.github.gtache.autosubtitle</groupId>
<artifactId>autosubtitle-core</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.dagger</groupId> <groupId>com.google.dagger</groupId>
@@ -45,7 +42,7 @@
<dependency> <dependency>
<groupId>org.controlsfx</groupId> <groupId>org.controlsfx</groupId>
<artifactId>controlsfx</artifactId> <artifactId>controlsfx</artifactId>
<version>11.2.1</version> <version>${controlsfx.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -3,23 +3,28 @@ package com.github.gtache.autosubtitle.gui.fx;
import com.github.gtache.autosubtitle.gui.MediaController; import com.github.gtache.autosubtitle.gui.MediaController;
import com.github.gtache.autosubtitle.gui.TimeFormatter; import com.github.gtache.autosubtitle.gui.TimeFormatter;
import com.github.gtache.autosubtitle.impl.FileVideoImpl; import com.github.gtache.autosubtitle.impl.FileVideoImpl;
import com.github.gtache.autosubtitle.modules.gui.Pause; import com.github.gtache.autosubtitle.modules.gui.impl.Pause;
import com.github.gtache.autosubtitle.modules.gui.Play; import com.github.gtache.autosubtitle.modules.gui.impl.Play;
import com.github.gtache.autosubtitle.subtitle.Subtitle; import com.github.gtache.autosubtitle.subtitle.Subtitle;
import com.github.gtache.autosubtitle.subtitle.fx.SubtitleLabel; import com.github.gtache.autosubtitle.subtitle.gui.fx.SubtitleLabel;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.scene.Cursor; import javafx.scene.Cursor;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.Slider; import javafx.scene.control.Slider;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
import javafx.scene.media.Media; import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer; import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView; import javafx.scene.media.MediaView;
import javafx.scene.paint.Color;
import javafx.util.Duration; import javafx.util.Duration;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@@ -102,9 +107,11 @@ public class FXMediaController implements MediaController {
player.currentTimeProperty().addListener((ignored, oldTime, newTime) -> { player.currentTimeProperty().addListener((ignored, oldTime, newTime) -> {
final var millis = newTime.toMillis(); final var millis = newTime.toMillis();
playSlider.setValue(millis); playSlider.setValue(millis);
stackPane.getChildren().removeIf(Label.class::isInstance);
model.subtitles().forEach(s -> { model.subtitles().forEach(s -> {
//TODO optimize //TODO optimize using e.g. direction of playback
if (s.start() <= millis && s.end() >= millis) { if (s.start() <= millis && s.end() >= millis) {
logger.info("Adding label {} at {}", s, millis);
final var label = createDraggableLabel(s); final var label = createDraggableLabel(s);
stackPane.getChildren().add(label); stackPane.getChildren().add(label);
} }
@@ -184,6 +191,8 @@ public class FXMediaController implements MediaController {
private static SubtitleLabel createDraggableLabel(final Subtitle subtitle) { private static SubtitleLabel createDraggableLabel(final Subtitle subtitle) {
final var label = new SubtitleLabel(subtitle); final var label = new SubtitleLabel(subtitle);
label.setOpacity(0.8); label.setOpacity(0.8);
label.setBackground(new Background(new BackgroundFill(Color.BLACK, CornerRadii.EMPTY, Insets.EMPTY)));
label.setTextFill(Color.WHITE);
label.setOnMousePressed(mouseEvent -> { label.setOnMousePressed(mouseEvent -> {
final var x = label.getLayoutX() - mouseEvent.getSceneX(); final var x = label.getLayoutX() - mouseEvent.getSceneX();
final var y = label.getLayoutY() - mouseEvent.getSceneY(); final var y = label.getLayoutY() - mouseEvent.getSceneY();

View File

@@ -1,9 +1,9 @@
package com.github.gtache.autosubtitle.gui.fx; package com.github.gtache.autosubtitle.gui.fx;
import com.github.gtache.autosubtitle.gui.ParametersController; import com.github.gtache.autosubtitle.gui.ParametersController;
import com.github.gtache.autosubtitle.subtitle.ExtractionModel;
import com.github.gtache.autosubtitle.subtitle.ExtractionModelProvider;
import com.github.gtache.autosubtitle.subtitle.OutputFormat; import com.github.gtache.autosubtitle.subtitle.OutputFormat;
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModel;
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModelProvider;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter; import javafx.scene.control.TextFormatter;

View File

@@ -1,11 +1,11 @@
package com.github.gtache.autosubtitle.gui.fx; package com.github.gtache.autosubtitle.gui.fx;
import com.github.gtache.autosubtitle.gui.ParametersModel; import com.github.gtache.autosubtitle.gui.ParametersModel;
import com.github.gtache.autosubtitle.modules.gui.FontFamily; import com.github.gtache.autosubtitle.modules.gui.impl.FontFamily;
import com.github.gtache.autosubtitle.modules.gui.FontSize; import com.github.gtache.autosubtitle.modules.gui.impl.FontSize;
import com.github.gtache.autosubtitle.subtitle.ExtractionModel;
import com.github.gtache.autosubtitle.subtitle.ExtractionModelProvider;
import com.github.gtache.autosubtitle.subtitle.OutputFormat; import com.github.gtache.autosubtitle.subtitle.OutputFormat;
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModel;
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModelProvider;
import javafx.beans.property.IntegerProperty; import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleIntegerProperty;

View File

@@ -8,12 +8,14 @@ import com.github.gtache.autosubtitle.gui.TimeFormatter;
import com.github.gtache.autosubtitle.gui.WorkController; import com.github.gtache.autosubtitle.gui.WorkController;
import com.github.gtache.autosubtitle.gui.WorkStatus; import com.github.gtache.autosubtitle.gui.WorkStatus;
import com.github.gtache.autosubtitle.subtitle.EditableSubtitle; import com.github.gtache.autosubtitle.subtitle.EditableSubtitle;
import com.github.gtache.autosubtitle.subtitle.ExtractEvent;
import com.github.gtache.autosubtitle.subtitle.ExtractException;
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection; import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
import com.github.gtache.autosubtitle.subtitle.SubtitleExtractor; import com.github.gtache.autosubtitle.subtitle.converter.ParseException;
import com.github.gtache.autosubtitle.subtitle.SubtitleExtractorListener; import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
import com.github.gtache.autosubtitle.subtitle.fx.ObservableSubtitleImpl; import com.github.gtache.autosubtitle.subtitle.extractor.ExtractEvent;
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractException;
import com.github.gtache.autosubtitle.subtitle.extractor.SubtitleExtractor;
import com.github.gtache.autosubtitle.subtitle.extractor.SubtitleExtractorListener;
import com.github.gtache.autosubtitle.subtitle.gui.fx.ObservableSubtitleImpl;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;
@@ -37,9 +39,11 @@ import org.controlsfx.control.PrefixSelectionComboBox;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException; import java.util.concurrent.CompletionException;
@@ -63,6 +67,8 @@ public class FXWorkController extends AbstractFXController implements WorkContro
@FXML @FXML
private TextField fileField; private TextField fileField;
@FXML @FXML
private Button loadSubtitlesButton;
@FXML
private Button extractButton; private Button extractButton;
@FXML @FXML
private Button resetButton; private Button resetButton;
@@ -81,6 +87,8 @@ public class FXWorkController extends AbstractFXController implements WorkContro
@FXML @FXML
private FXMediaController mediaController; private FXMediaController mediaController;
@FXML @FXML
private Button saveSubtitlesButton;
@FXML
private Button addSubtitleButton; private Button addSubtitleButton;
@FXML @FXML
private PrefixSelectionComboBox<Language> languageCombobox; private PrefixSelectionComboBox<Language> languageCombobox;
@@ -98,22 +106,27 @@ public class FXWorkController extends AbstractFXController implements WorkContro
private final FXWorkModel model; private final FXWorkModel model;
private final FXWorkBinder binder; private final FXWorkBinder binder;
private final SubtitleExtractor subtitleExtractor; private final SubtitleExtractor subtitleExtractor;
private final Map<String, SubtitleConverter> subtitleConvertersMap;
private final VideoConverter videoConverter; private final VideoConverter videoConverter;
private final VideoLoader videoLoader; private final VideoLoader videoLoader;
private final Translator translator; private final Translator translator;
private final TimeFormatter timeFormatter; private final TimeFormatter timeFormatter;
private final List<String> subtitleExtensions;
@Inject @Inject
FXWorkController(final FXWorkModel model, final FXWorkBinder binder, final SubtitleExtractor subtitleExtractor, final VideoLoader videoLoader, FXWorkController(final FXWorkModel model, final FXWorkBinder binder, final SubtitleExtractor subtitleExtractor,
final Map<String, SubtitleConverter> subtitleConvertersMap, final VideoLoader videoLoader,
final VideoConverter videoConverter, final Translator translator, final TimeFormatter timeFormatter) { final VideoConverter videoConverter, final Translator translator, final TimeFormatter timeFormatter) {
this.model = requireNonNull(model); this.model = requireNonNull(model);
this.binder = requireNonNull(binder); this.binder = requireNonNull(binder);
this.subtitleExtractor = requireNonNull(subtitleExtractor); this.subtitleExtractor = requireNonNull(subtitleExtractor);
this.subtitleConvertersMap = requireNonNull(subtitleConvertersMap);
this.videoConverter = requireNonNull(videoConverter); this.videoConverter = requireNonNull(videoConverter);
this.videoLoader = requireNonNull(videoLoader); this.videoLoader = requireNonNull(videoLoader);
this.translator = requireNonNull(translator); this.translator = requireNonNull(translator);
this.timeFormatter = requireNonNull(timeFormatter); this.timeFormatter = requireNonNull(timeFormatter);
this.subtitleExtensions = subtitleConvertersMap.values().stream().map(c -> "*." + c.formatName()).sorted().toList();
} }
@FXML @FXML
@@ -126,10 +139,12 @@ public class FXWorkController extends AbstractFXController implements WorkContro
Bindings.bindContent(model.translations(), translationsCombobox.getCheckModel().getCheckedItems()); Bindings.bindContent(model.translations(), translationsCombobox.getCheckModel().getCheckedItems());
extractButton.disableProperty().bind(model.videoProperty().isNull().or(model.statusProperty().isNotEqualTo(WorkStatus.IDLE))); extractButton.disableProperty().bind(model.videoProperty().isNull().or(model.statusProperty().isNotEqualTo(WorkStatus.IDLE)));
resetButton.disableProperty().bind(Bindings.isEmpty(model.subtitles())); loadSubtitlesButton.disableProperty().bind(model.videoProperty().isNull().or(model.statusProperty().isNotEqualTo(WorkStatus.IDLE)));
resetButton.disableProperty().bind(Bindings.isEmpty(model.subtitles()).or(model.statusProperty().isNotEqualTo(WorkStatus.IDLE)));
exportSoftButton.disableProperty().bind(Bindings.isEmpty(model.subtitles()).or(model.statusProperty().isNotEqualTo(WorkStatus.IDLE))); exportSoftButton.disableProperty().bind(Bindings.isEmpty(model.subtitles()).or(model.statusProperty().isNotEqualTo(WorkStatus.IDLE)));
exportHardButton.disableProperty().bind(Bindings.isEmpty(model.subtitles()).or(model.statusProperty().isNotEqualTo(WorkStatus.IDLE))); exportHardButton.disableProperty().bind(Bindings.isEmpty(model.subtitles()).or(model.statusProperty().isNotEqualTo(WorkStatus.IDLE)));
addSubtitleButton.disableProperty().bind(model.videoProperty().isNull()); addSubtitleButton.disableProperty().bind(Bindings.isEmpty(model.subtitles()).or(model.statusProperty().isNotEqualTo(WorkStatus.IDLE)));
loadSubtitlesButton.disableProperty().bind(Bindings.isEmpty(model.subtitles()).or(model.statusProperty().isNotEqualTo(WorkStatus.IDLE)));
subtitlesTable.setItems(model.subtitles()); subtitlesTable.setItems(model.subtitles());
subtitlesTable.setOnKeyPressed(e -> { subtitlesTable.setOnKeyPressed(e -> {
@@ -150,6 +165,7 @@ public class FXWorkController extends AbstractFXController implements WorkContro
final var subtitle = e.getRowValue(); final var subtitle = e.getRowValue();
subtitle.setStart(e.getNewValue()); subtitle.setStart(e.getNewValue());
subtitlesTable.refresh(); subtitlesTable.refresh();
subtitlesTable.requestFocus();
}); });
endColumn.setCellFactory(TextFieldTableCell.forTableColumn(new TimeStringConverter(timeFormatter))); endColumn.setCellFactory(TextFieldTableCell.forTableColumn(new TimeStringConverter(timeFormatter)));
endColumn.setCellValueFactory(param -> new SimpleObjectProperty<>(param.getValue() == null ? null : param.getValue().end())); endColumn.setCellValueFactory(param -> new SimpleObjectProperty<>(param.getValue() == null ? null : param.getValue().end()));
@@ -157,6 +173,7 @@ public class FXWorkController extends AbstractFXController implements WorkContro
final var subtitle = e.getRowValue(); final var subtitle = e.getRowValue();
subtitle.setEnd(e.getNewValue()); subtitle.setEnd(e.getNewValue());
subtitlesTable.refresh(); subtitlesTable.refresh();
subtitlesTable.requestFocus();
}); });
textColumn.setCellFactory(TextFieldTableCell.forTableColumn()); textColumn.setCellFactory(TextFieldTableCell.forTableColumn());
textColumn.setCellValueFactory(param -> new SimpleStringProperty(param.getValue() == null ? null : param.getValue().content())); textColumn.setCellValueFactory(param -> new SimpleStringProperty(param.getValue() == null ? null : param.getValue().content()));
@@ -164,6 +181,7 @@ public class FXWorkController extends AbstractFXController implements WorkContro
final var subtitle = e.getRowValue(); final var subtitle = e.getRowValue();
subtitle.setContent(e.getNewValue()); subtitle.setContent(e.getNewValue());
subtitlesTable.refresh(); subtitlesTable.refresh();
subtitlesTable.requestFocus();
}); });
subtitlesTable.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> model.selectedSubtitleProperty().set(newValue)); subtitlesTable.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> model.selectedSubtitleProperty().set(newValue));
@@ -222,12 +240,7 @@ public class FXWorkController extends AbstractFXController implements WorkContro
private void manageExtractResult(final SubtitleCollection newCollection, final Throwable t) { private void manageExtractResult(final SubtitleCollection newCollection, final Throwable t) {
if (t == null) { if (t == null) {
final var newSubtitles = newCollection.subtitles().stream().map(ObservableSubtitleImpl::new).toList(); loadCollection(newCollection);
final var subtitlesCopy = newSubtitles.stream().map(ObservableSubtitleImpl::new).toList();
model.subtitles().setAll(newSubtitles);
model.originalSubtitles().clear();
model.originalSubtitles().addAll(subtitlesCopy);
model.videoLanguageProperty().set(newCollection.language());
} else { } else {
logger.error("Error extracting subtitles", t); logger.error("Error extracting subtitles", t);
showErrorDialog(resources.getString("work.extract.error.title"), MessageFormat.format(resources.getString("work.extract.error.label"), t.getMessage())); showErrorDialog(resources.getString("work.extract.error.title"), MessageFormat.format(resources.getString("work.extract.error.label"), t.getMessage()));
@@ -243,10 +256,50 @@ public class FXWorkController extends AbstractFXController implements WorkContro
model.videoProperty().set(loadedVideo); model.videoProperty().set(loadedVideo);
} catch (final IOException e) { } catch (final IOException e) {
logger.error("Error loading video {}", file, e); logger.error("Error loading video {}", file, e);
showErrorDialog(resources.getString("work.load.error.title"), MessageFormat.format(resources.getString("work.load.error.label"), e.getMessage())); showErrorDialog(resources.getString("work.load.video.error.title"), MessageFormat.format(resources.getString("work.load.video.error.label"), e.getMessage()));
} }
} }
@Override
public void saveSubtitles(final Path file) {
final var fileName = file.getFileName().toString();
final var converter = subtitleConvertersMap.get(fileName.substring(fileName.lastIndexOf('.') + 1));
if (converter == null) {
logger.warn("No converter for {}", file);
showErrorDialog(resources.getString("work.save.subtitles.missing.converter.title"), MessageFormat.format(resources.getString("work.save.subtitles.missing.converter.label"), file.getFileName()));
} else {
final var string = converter.format(model.subtitleCollection());
try {
Files.writeString(file, string);
} catch (final IOException e) {
logger.error("Error saving subtitles {}", file, e);
showErrorDialog(resources.getString("work.save.subtitles.error.title"), MessageFormat.format(resources.getString("work.save.subtitles.error.label"), e.getMessage()));
}
}
}
@Override
public void loadSubtitles(final Path file) {
final var fileName = file.getFileName().toString();
final var parser = subtitleConvertersMap.get(fileName.substring(fileName.lastIndexOf('.') + 1));
if (parser != null) {
try {
final var collection = parser.parse(file);
loadCollection(collection);
} catch (final ParseException e) {
logger.error("Error loading subtitles {}", file, e);
showErrorDialog(resources.getString("work.load.subtitles.error.title"), MessageFormat.format(resources.getString("work.load.subtitles.error.label"), e.getMessage()));
}
}
}
private void loadCollection(final SubtitleCollection collection) {
model.subtitles().setAll(collection.subtitles().stream().map(ObservableSubtitleImpl::new).toList());
model.originalSubtitles().clear();
model.originalSubtitles().addAll(collection.subtitles().stream().map(ObservableSubtitleImpl::new).toList());
model.videoLanguageProperty().set(collection.language());
}
@FXML @FXML
private void exportSoftPressed() { private void exportSoftPressed() {
final var filePicker = new FileChooser(); final var filePicker = new FileChooser();
@@ -329,4 +382,26 @@ public class FXWorkController extends AbstractFXController implements WorkContro
progressDetailLabel.setText(event.message()); progressDetailLabel.setText(event.message());
}); });
} }
@FXML
private void loadSubtitlesPressed() {
final var filePicker = new FileChooser();
final var extensionFilter = new FileChooser.ExtensionFilter("All supported", subtitleExtensions);
filePicker.getExtensionFilters().add(extensionFilter);
filePicker.setSelectedExtensionFilter(extensionFilter);
final var file = filePicker.showOpenDialog(window());
loadSubtitles(file.toPath());
}
@FXML
private void saveSubtitlesPressed() {
final var filePicker = new FileChooser();
final var extensionFilter = new FileChooser.ExtensionFilter("All supported", subtitleExtensions);
filePicker.getExtensionFilters().add(extensionFilter);
filePicker.setSelectedExtensionFilter(extensionFilter);
final var file = filePicker.showSaveDialog(window());
if (file != null) {
saveSubtitles(file.toPath());
}
}
} }

View File

@@ -5,8 +5,8 @@ import com.github.gtache.autosubtitle.Video;
import com.github.gtache.autosubtitle.gui.WorkModel; import com.github.gtache.autosubtitle.gui.WorkModel;
import com.github.gtache.autosubtitle.gui.WorkStatus; import com.github.gtache.autosubtitle.gui.WorkStatus;
import com.github.gtache.autosubtitle.subtitle.EditableSubtitle; import com.github.gtache.autosubtitle.subtitle.EditableSubtitle;
import com.github.gtache.autosubtitle.subtitle.ExtractionModel;
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection; import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModel;
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleCollectionImpl; import com.github.gtache.autosubtitle.subtitle.impl.SubtitleCollectionImpl;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.property.DoubleProperty; import javafx.beans.property.DoubleProperty;

View File

@@ -7,8 +7,8 @@ import com.github.gtache.autosubtitle.gui.fx.FXMediaController;
import com.github.gtache.autosubtitle.gui.fx.FXParametersController; import com.github.gtache.autosubtitle.gui.fx.FXParametersController;
import com.github.gtache.autosubtitle.gui.fx.FXSetupController; import com.github.gtache.autosubtitle.gui.fx.FXSetupController;
import com.github.gtache.autosubtitle.gui.fx.FXWorkController; import com.github.gtache.autosubtitle.gui.fx.FXWorkController;
import com.github.gtache.autosubtitle.modules.gui.Pause; import com.github.gtache.autosubtitle.modules.gui.impl.Pause;
import com.github.gtache.autosubtitle.modules.gui.Play; import com.github.gtache.autosubtitle.modules.gui.impl.Play;
import dagger.Binds; import dagger.Binds;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.subtitle.fx; package com.github.gtache.autosubtitle.subtitle.gui.fx;
import com.github.gtache.autosubtitle.subtitle.Bounds; import com.github.gtache.autosubtitle.subtitle.Bounds;
import com.github.gtache.autosubtitle.subtitle.EditableSubtitle; import com.github.gtache.autosubtitle.subtitle.EditableSubtitle;

View File

@@ -1,4 +1,4 @@
package com.github.gtache.autosubtitle.subtitle.fx; package com.github.gtache.autosubtitle.subtitle.gui.fx;
import com.github.gtache.autosubtitle.subtitle.Subtitle; import com.github.gtache.autosubtitle.subtitle.Subtitle;
import javafx.scene.control.Label; import javafx.scene.control.Label;
@@ -16,6 +16,7 @@ public class SubtitleLabel extends Label {
public SubtitleLabel(final Subtitle subtitle) { public SubtitleLabel(final Subtitle subtitle) {
this.subtitle = Objects.requireNonNull(subtitle); this.subtitle = Objects.requireNonNull(subtitle);
this.delta = new Delta(); this.delta = new Delta();
setText(subtitle.content());
} }
public Subtitle subtitle() { public Subtitle subtitle() {

View File

@@ -1,13 +1,9 @@
import com.github.gtache.autosubtitle.gui.spi.MainBundleProvider;
import com.github.gtache.autosubtitle.gui.spi.SetupBundleProvider;
import com.github.gtache.autosubtitle.gui.spi.WorkBundleProvider;
/** /**
* FX module for auto-subtitle * FX module for auto-subtitle
*/ */
module com.github.gtache.autosubtitle.fx { module com.github.gtache.autosubtitle.fx {
requires transitive com.github.gtache.autosubtitle.core; requires transitive com.github.gtache.autosubtitle.core;
requires transitive com.github.gtache.autosubtitle.gui; requires transitive com.github.gtache.autosubtitle.gui.core;
requires transitive javafx.controls; requires transitive javafx.controls;
requires transitive javafx.media; requires transitive javafx.media;
requires transitive javafx.fxml; requires transitive javafx.fxml;
@@ -17,11 +13,6 @@ module com.github.gtache.autosubtitle.fx {
requires transitive java.prefs; requires transitive java.prefs;
exports com.github.gtache.autosubtitle.gui.fx; exports com.github.gtache.autosubtitle.gui.fx;
opens com.github.gtache.autosubtitle.gui.fx to javafx.fxml;
exports com.github.gtache.autosubtitle.modules.gui.fx; exports com.github.gtache.autosubtitle.modules.gui.fx;
opens com.github.gtache.autosubtitle.gui.fx to javafx.fxml;
uses MainBundleProvider;
uses SetupBundleProvider;
uses WorkBundleProvider;
} }

View File

@@ -22,8 +22,14 @@
<TextField fx:id="fileField" editable="false" GridPane.columnIndex="1"/> <TextField fx:id="fileField" editable="false" GridPane.columnIndex="1"/>
<Button mnemonicParsing="false" onAction="#fileButtonPressed" text="%work.button.file.label" <Button mnemonicParsing="false" onAction="#fileButtonPressed" text="%work.button.file.label"
GridPane.columnIndex="2"/> GridPane.columnIndex="2"/>
<Button fx:id="extractButton" mnemonicParsing="false" onAction="#extractPressed" <HBox spacing="10.0" GridPane.columnIndex="1" GridPane.rowIndex="2">
text="%work.button.extract.label" GridPane.columnIndex="1" GridPane.rowIndex="2"/> <children>
<Button fx:id="loadSubtitlesButton" mnemonicParsing="false" onAction="#loadSubtitlesPressed"
text="%work.button.load.label"/>
<Button fx:id="extractButton" mnemonicParsing="false" onAction="#extractPressed"
text="%work.button.extract.label"/>
</children>
</HBox>
<HBox alignment="CENTER_RIGHT" spacing="10.0" GridPane.columnIndex="2" GridPane.rowIndex="2"> <HBox alignment="CENTER_RIGHT" spacing="10.0" GridPane.columnIndex="2" GridPane.rowIndex="2">
<children> <children>
<Button fx:id="exportSoftButton" mnemonicParsing="false" onAction="#exportSoftPressed" <Button fx:id="exportSoftButton" mnemonicParsing="false" onAction="#exportSoftPressed"
@@ -51,12 +57,20 @@
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/> <TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/>
</columnResizePolicy> </columnResizePolicy>
</TableView> </TableView>
<Button fx:id="resetButton" mnemonicParsing="false" onAction="#resetButtonPressed" <HBox spacing="10.0" GridPane.rowIndex="2">
text="%work.button.reset.label" GridPane.rowIndex="2"/> <children>
<Button fx:id="resetButton" mnemonicParsing="false" onAction="#resetButtonPressed"
text="%work.button.reset.label"/>
<Button fx:id="saveSubtitlesButton" mnemonicParsing="false" onAction="#saveSubtitlesPressed"
text="%work.button.subtitles.save.label"/>
<Button fx:id="addSubtitleButton" mnemonicParsing="false" onAction="#addSubtitlePressed" text="+"/>
</children>
<GridPane.margin>
<Insets/>
</GridPane.margin>
</HBox>
<fx:include fx:id="media" source="mediaView.fxml" GridPane.columnIndex="1" GridPane.columnSpan="2147483647" <fx:include fx:id="media" source="mediaView.fxml" GridPane.columnIndex="1" GridPane.columnSpan="2147483647"
GridPane.rowIndex="1"/> GridPane.rowIndex="1"/>
<Button fx:id="addSubtitleButton" mnemonicParsing="false" onAction="#addSubtitlePressed" text="+"
GridPane.halignment="RIGHT" GridPane.rowIndex="2"/>
<HBox alignment="CENTER_LEFT" spacing="10.0"> <HBox alignment="CENTER_LEFT" spacing="10.0">
<children> <children>
<Label text="%work.language.label"/> <Label text="%work.language.label"/>

View File

@@ -8,19 +8,33 @@
<artifactId>autosubtitle</artifactId> <artifactId>autosubtitle</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</parent> </parent>
<packaging>pom</packaging>
<modules>
<module>api</module>
<module>core</module>
<module>fx</module>
<module>run</module>
</modules>
<artifactId>autosubtitle-gui</artifactId> <artifactId>autosubtitle-gui</artifactId>
<dependencies> <dependencyManagement>
<dependency> <dependencies>
<groupId>com.github.gtache.autosubtitle</groupId> <dependency>
<artifactId>autosubtitle-api</artifactId> <groupId>com.github.gtache.autosubtitle</groupId>
</dependency> <artifactId>autosubtitle-gui-api</artifactId>
<version>${project.version}</version>
<dependency> </dependency>
<groupId>com.google.dagger</groupId> <dependency>
<artifactId>dagger</artifactId> <groupId>com.github.gtache.autosubtitle</groupId>
</dependency> <artifactId>autosubtitle-gui-core</artifactId>
</dependencies> <version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.github.gtache.autosubtitle</groupId>
<artifactId>autosubtitle-fx</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project> </project>

View File

@@ -5,11 +5,11 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>com.github.gtache.autosubtitle</groupId> <groupId>com.github.gtache.autosubtitle</groupId>
<artifactId>autosubtitle</artifactId> <artifactId>autosubtitle-gui</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</parent> </parent>
<artifactId>autosubtitle-run</artifactId> <artifactId>autosubtitle-gui-run</artifactId>
<dependencies> <dependencies>
<dependency> <dependency>

View File

@@ -1,12 +1,12 @@
package com.github.gtache.autosubtitle.modules.run; package com.github.gtache.autosubtitle.modules.run;
import com.github.gtache.autosubtitle.modules.ffmpeg.FFmpegModule; import com.github.gtache.autosubtitle.modules.ffmpeg.FFmpegModule;
import com.github.gtache.autosubtitle.modules.gui.GuiModule;
import com.github.gtache.autosubtitle.modules.gui.fx.FXModule; import com.github.gtache.autosubtitle.modules.gui.fx.FXModule;
import com.github.gtache.autosubtitle.modules.gui.impl.GuiCoreModule;
import com.github.gtache.autosubtitle.modules.impl.CoreModule; import com.github.gtache.autosubtitle.modules.impl.CoreModule;
import com.github.gtache.autosubtitle.modules.setup.ffmpeg.FFmpegSetupModule; import com.github.gtache.autosubtitle.modules.setup.ffmpeg.FFmpegSetupModule;
import com.github.gtache.autosubtitle.modules.setup.whisper.WhisperSetupModule; import com.github.gtache.autosubtitle.modules.setup.whisper.WhisperSetupModule;
import com.github.gtache.autosubtitle.modules.subtitles.impl.ConverterModule; import com.github.gtache.autosubtitle.modules.subtitle.impl.SubtitleModule;
import com.github.gtache.autosubtitle.modules.whisper.WhisperModule; import com.github.gtache.autosubtitle.modules.whisper.WhisperModule;
import dagger.Component; import dagger.Component;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
@@ -17,8 +17,8 @@ import javax.inject.Singleton;
* Main component * Main component
*/ */
@Singleton @Singleton
@Component(modules = {CoreModule.class, GuiModule.class, FXModule.class, FFmpegModule.class, FFmpegSetupModule.class, @Component(modules = {CoreModule.class, GuiCoreModule.class, FXModule.class, FFmpegModule.class, FFmpegSetupModule.class,
ConverterModule.class, WhisperModule.class, WhisperSetupModule.class, MissingComponentsModule.class}) SubtitleModule.class, WhisperModule.class, WhisperSetupModule.class, MissingComponentsModule.class})
public interface RunComponent { public interface RunComponent {
/** /**

Some files were not shown because too many files have changed in this diff Show More