15 Commits

Author SHA1 Message Date
RatzzFatzz
b0f927dfa8 Implement OFF for audio tracks 2025-10-16 17:10:33 +02:00
RatzzFatzz
37c65df60c Update dependencies && Fix status reporting if no subs are available for file 2025-10-16 00:30:54 +02:00
0e9d008c7e Fix formatting in README.md 2025-05-12 16:00:19 +02:00
3205969d3b Update readme 2025-05-02 03:33:14 +02:00
d24aedb0af Fix mkvpropedit call & improve logging 2025-05-02 03:27:24 +02:00
b86c7b98a5 Fix logging for portable 2025-05-01 22:55:11 +02:00
Michael
69c192c08b Update README.md 2025-02-22 20:37:04 +01:00
Michael
7dd01234b6 Merge pull request #57 from RatzzFatzz/dev
Fix execution on linux
2025-02-18 19:23:08 +01:00
RatzzFatzz
8f38abcf3a Fix execution on linux 2025-02-18 19:15:02 +01:00
Michael
fc4e80ead0 Merge pull request #55 from RatzzFatzz/dev
Release v4.0
2025-02-06 22:27:06 +01:00
RatzzFatzz
e81b06f6fa Improve logging 2025-02-06 00:18:49 +01:00
RatzzFatzz
dc770c9325 Fix file count if no info was found 2025-02-06 00:00:28 +01:00
RatzzFatzz
471255a09b Fix windows installer build 2025-02-05 23:32:01 +01:00
RatzzFatzz
9c8315aec7 Remove config-template 2025-02-05 23:13:54 +01:00
Michael
a075dfb27c Remove forced audio tracks & minor refactoring 2024-05-27 22:31:34 +02:00
32 changed files with 422 additions and 339 deletions

View File

@@ -92,11 +92,11 @@ jobs:
with: with:
timezoneWindows: "Berlin Standard Time" timezoneWindows: "Berlin Standard Time"
- name: Set up JDK 17 - name: Set up JDK 21
uses: actions/setup-java@v4.7.0 uses: actions/setup-java@v4.7.0
with: with:
distribution: temurin distribution: temurin
java-version: 17 java-version: 21
- name: Setup workspace - name: Setup workspace
run: mkdir artifacts run: mkdir artifacts

View File

@@ -10,20 +10,21 @@ A streamlined solution for managing MKV files, this program leverages MKVToolNix
- mkvtoolnix installation - mkvtoolnix installation
## Execution ## Execution
### Minimal usage Portable:
Portable: `java -jar mkvaudiosubtitlechanger-<version>.jar --library "X:/Files" --attribute-config eng:ger eng:OFF` ```
java -jar mkvaudiosubtitlechanger-<version>.jar --library "X:/Files" --attribute-config eng:ger eng:OFF
```
Windows & Linux (installed):
```
mkvaudiosubtitlechanger --library "X:/Files" --attribute-config eng:ger eng:OFF
```
Windows (installed): `mkvaudiosubtitlechanger.jar --library "X:/Files" --attribute-config eng:ger eng:OFF` Add `--safe-mode` oder `-s` to not change any files. This is recommended for the first executions.
### Safe usage (best for testing before applying to whole library) Attribute-config must be entered in pairs: `audio:subtitle`; Example: `jpn:eng`. More about this topic
Portable: `java -jar mkvaudiosubtitlechanger-<version>.jar --library "X:/Files" --attribute-config eng:ger eng:OFF --safe-mode` [here](https://github.com/RatzzFatzz/MKVAudioSubtitleChanger/wiki/Attribute-Config).
Windows (installed): `mkvaudiosubtitlechanger.jar --library "X:/Files" --attribute-config eng:ger eng:OFF --safe-mode` ### Available parameters
**Attribute-config must be entered in pairs: `audio:subtitle`; Example: `jpn:eng`. More about this topic
[here](https://github.com/RatzzFatzz/MKVAudioSubtitleChanger/wiki/Attribute-Config).**
## Available parameters
``` ```
-a, --attribute-config=<attributeConfig>... -a, --attribute-config=<attributeConfig>...
List of audio:subtitle pairs used to match in order and update files accordingly (e.g. jpn:eng jpn:ger) List of audio:subtitle pairs used to match in order and update files accordingly (e.g. jpn:eng jpn:ger)
@@ -33,6 +34,7 @@ Windows (installed): `mkvaudiosubtitlechanger.jar --library "X:/Files" --attribu
Keywords to identify commentary tracks (Defaults will be overwritten; Default: commentary, director) Keywords to identify commentary tracks (Defaults will be overwritten; Default: commentary, director)
-d, --filter-date=<filterDate> -d, --filter-date=<filterDate>
only consider files created newer than entered date (format: "dd.MM.yyyy-HH:mm:ss") only consider files created newer than entered date (format: "dd.MM.yyyy-HH:mm:ss")
--debug Enable debug logging
-e, --excluded-directory=<excludedDirectories>... -e, --excluded-directory=<excludedDirectories>...
Directories to be excluded, combines with config file Directories to be excluded, combines with config file
--forced-keywords=<forcedKeywords>[, <forcedKeywords>...]... --forced-keywords=<forcedKeywords>[, <forcedKeywords>...]...

View File

@@ -1,34 +0,0 @@
mkvtoolnix: C:\Program Files\MKVToolNix
library: X:/Files
attribute-config:
1:
audio: ger
subtitle: OFF
2:
audio: eng
subtitle: ger
# Recommendations for data stored on HDDs, increase when using SSDs
#threads: 2
#forced-keywords: ["forced", "signs"]
#commentary-keywords: ["commentary", "director"]
#preferred-subtitles: ["unstyled"]
#exclude-directories:
# - "D:/Path/To/File.mkv"
# - "D:/Path/To/Directory"
# If pattern is negated, can be used to exclude files
#include-pattern: "regex"
# Only files newer than
#filter-date: 20.03.2021-10:11:12
safe-mode:
#coherent:
#force-coherent:
#only-new-files:

View File

@@ -14,10 +14,6 @@
<destName>${project.artifactId}.jar</destName> <destName>${project.artifactId}.jar</destName>
<outputDirectory>/</outputDirectory> <outputDirectory>/</outputDirectory>
</file> </file>
<file>
<source>${project.basedir}/config-template.yaml</source>
<outputDirectory>/</outputDirectory>
</file>
<file> <file>
<source></source> <source></source>
</file> </file>

36
pom.xml
View File

@@ -6,17 +6,18 @@
<groupId>at.pcgamingfreaks</groupId> <groupId>at.pcgamingfreaks</groupId>
<artifactId>MKVAudioSubtitleChanger</artifactId> <artifactId>MKVAudioSubtitleChanger</artifactId>
<version>4.0.0</version> <version>4.0.4</version>
<properties> <properties>
<mainClass>at.pcgamingfreaks.mkvaudiosubtitlechanger.Main</mainClass> <mainClass>at.pcgamingfreaks.mkvaudiosubtitlechanger.Main</mainClass>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.maintainer>RatzzFatzz</project.maintainer> <project.maintainer>RatzzFatzz</project.maintainer>
<project.maintainer.mail>github.contact@ratzloeffel.de</project.maintainer.mail> <project.maintainer.mail>github.contact@ratzloeffel.de</project.maintainer.mail>
<project.description>Command-line utility for batch-managing default audio and subtitle tracks in MKV files.</project.description> <project.description>Command-line utility for batch-managing default audio and subtitle tracks in MKV files.</project.description>
<java-version>17</java-version> <java-version>17</java-version>
<lombok-version>1.18.36</lombok-version> <lombok-version>1.18.42</lombok-version>
</properties> </properties>
<profiles> <profiles>
@@ -27,8 +28,7 @@
<resource> <resource>
<directory>src/main/resources</directory> <directory>src/main/resources</directory>
<includes> <includes>
<include>log4j2.yml</include> <include>log4j2.yaml</include>
<include>log4j2-debug.yml</include>
</includes> </includes>
</resource> </resource>
</resources> </resources>
@@ -111,7 +111,7 @@
<plugin> <plugin>
<groupId>org.panteleyev</groupId> <groupId>org.panteleyev</groupId>
<artifactId>jpackage-maven-plugin</artifactId> <artifactId>jpackage-maven-plugin</artifactId>
<version>1.6.5</version> <version>1.7.1</version>
<configuration> <configuration>
<name>${project.artifactId}</name> <name>${project.artifactId}</name>
<vendor>RatzzFatzz</vendor> <vendor>RatzzFatzz</vendor>
@@ -308,7 +308,7 @@
<path> <path>
<groupId>info.picocli</groupId> <groupId>info.picocli</groupId>
<artifactId>picocli-codegen</artifactId> <artifactId>picocli-codegen</artifactId>
<version>4.7.6</version> <version>4.7.7</version>
</path> </path>
</annotationProcessorPaths> </annotationProcessorPaths>
</configuration> </configuration>
@@ -342,7 +342,7 @@
<dependency> <dependency>
<groupId>info.picocli</groupId> <groupId>info.picocli</groupId>
<artifactId>picocli</artifactId> <artifactId>picocli</artifactId>
<version>4.7.6</version> <version>4.7.7</version>
</dependency> </dependency>
<!-- Hibernate Validator --> <!-- Hibernate Validator -->
@@ -358,7 +358,7 @@
<dependency> <dependency>
<groupId>jakarta.el</groupId> <groupId>jakarta.el</groupId>
<artifactId>jakarta.el-api</artifactId> <artifactId>jakarta.el-api</artifactId>
<version>6.0.1</version> <version>6.1.0-M1</version>
</dependency> </dependency>
<dependency> <dependency>
@@ -372,7 +372,7 @@
<dependency> <dependency>
<groupId>jakarta.validation</groupId> <groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId> <artifactId>jakarta.validation-api</artifactId>
<version>3.0.2</version> <version>3.1.1</version>
</dependency> </dependency>
<!-- region logging --> <!-- region logging -->
@@ -400,26 +400,26 @@
<dependency> <dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId> <groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId> <artifactId>jackson-dataformat-yaml</artifactId>
<version>2.18.2</version> <version>2.20.0</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
<version>2.18.2</version> <version>2.20.0</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/commons-cli/commons-cli --> <!-- https://mvnrepository.com/artifact/commons-cli/commons-cli -->
<dependency> <dependency>
<groupId>commons-cli</groupId> <groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId> <artifactId>commons-cli</artifactId>
<version>1.9.0</version> <version>1.10.0</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 --> <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
<version>3.17.0</version> <version>3.19.0</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/me.tongfei/progressbar --> <!-- https://mvnrepository.com/artifact/me.tongfei/progressbar -->
<dependency> <dependency>
@@ -433,28 +433,28 @@
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId> <artifactId>junit-jupiter-api</artifactId>
<version>5.11.4</version> <version>6.0.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine --> <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine -->
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId> <artifactId>junit-jupiter-engine</artifactId>
<version>5.11.4</version> <version>6.0.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core --> <!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
<dependency> <dependency>
<groupId>org.mockito</groupId> <groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId> <artifactId>mockito-core</artifactId>
<version>5.15.2</version> <version>5.20.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-params --> <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-params -->
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId> <artifactId>junit-jupiter-params</artifactId>
<version>5.11.4</version> <version>6.0.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
@@ -468,7 +468,7 @@
<dependency> <dependency>
<groupId>net.harawata</groupId> <groupId>net.harawata</groupId>
<artifactId>appdirs</artifactId> <artifactId>appdirs</artifactId>
<version>1.3.0</version> <version>1.5.0</version>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -12,6 +12,8 @@ import jakarta.validation.Validation;
import jakarta.validation.Validator; import jakarta.validation.Validator;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator;
import picocli.CommandLine; import picocli.CommandLine;
import java.util.Set; import java.util.Set;
@@ -39,6 +41,9 @@ public class Main implements Runnable {
@Override @Override
public void run() { public void run() {
if (config.isDebug()) {
Configurator.setRootLevel(Level.DEBUG);
}
validate(); validate();
Config.setInstance(config); Config.setInstance(config);
AttributeUpdaterKernel kernel = Config.getInstance().getCoherent() != null AttributeUpdaterKernel kernel = Config.getInstance().getCoherent() != null

View File

@@ -5,7 +5,6 @@ import picocli.CommandLine;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.LanguageValidatorUtil.isAudioLanguageValid;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.LanguageValidatorUtil.isLanguageValid; import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.LanguageValidatorUtil.isLanguageValid;
public class AttributeConfigConverter implements CommandLine.ITypeConverter<AttributeConfig> { public class AttributeConfigConverter implements CommandLine.ITypeConverter<AttributeConfig> {
@@ -50,7 +49,7 @@ public class AttributeConfigConverter implements CommandLine.ITypeConverter<Attr
* @throws CommandLine.TypeConversionException if either language code is invalid * @throws CommandLine.TypeConversionException if either language code is invalid
*/ */
private static void validateResult(AttributeConfig attr) { private static void validateResult(AttributeConfig attr) {
if (!isAudioLanguageValid(attr.getAudioLanguage())) if (!isLanguageValid(attr.getAudioLanguage()))
throw new CommandLine.TypeConversionException("Audio language invalid: " + attr.getAudioLanguage()); throw new CommandLine.TypeConversionException("Audio language invalid: " + attr.getAudioLanguage());
if (!isLanguageValid(attr.getSubtitleLanguage())) if (!isLanguageValid(attr.getSubtitleLanguage()))
throw new CommandLine.TypeConversionException("Subtitle language invalid: " + attr.getSubtitleLanguage()); throw new CommandLine.TypeConversionException("Subtitle language invalid: " + attr.getSubtitleLanguage());

View File

@@ -20,7 +20,7 @@ import java.util.regex.Pattern;
@Getter @Getter
@Setter @Setter
@NoArgsConstructor @NoArgsConstructor
public class Config { public class Config implements CommandLine.IVersionProvider {
@Getter(AccessLevel.NONE) @Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE) @Setter(AccessLevel.NONE)
private static Config config = null; private static Config config = null;
@@ -72,6 +72,9 @@ public class Config {
description = "Keywords to prefer specific subtitle tracks (Defaults will be overwritten; Default: ${DEFAULT-VALUE})") description = "Keywords to prefer specific subtitle tracks (Defaults will be overwritten; Default: ${DEFAULT-VALUE})")
private Set<String> preferredSubtitles; private Set<String> preferredSubtitles;
@CommandLine.Option(names = {"--debug"}, description = "Enable debug logging")
private boolean debug;
@CommandLine.Option(names = {"-l", "--library"}, required = true, description = "path to library") @CommandLine.Option(names = {"-l", "--library"}, required = true, description = "path to library")
public void setLibraryPath(File libraryPath) { public void setLibraryPath(File libraryPath) {
if (!libraryPath.exists()) throw new CommandLine.ParameterException(spec.commandLine(), "Path does not exist: " + libraryPath.getAbsolutePath()); if (!libraryPath.exists()) throw new CommandLine.ParameterException(spec.commandLine(), "Path does not exist: " + libraryPath.getAbsolutePath());
@@ -148,5 +151,10 @@ public class Config {
.add("attributeConfig=" + attributeConfig) .add("attributeConfig=" + attributeConfig)
.toString(); .toString();
} }
@Override
public String[] getVersion() throws Exception {
return new String[0];
}
} }

View File

@@ -10,7 +10,6 @@ import java.util.List;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.LanguageValidatorUtil.isAudioLanguageValid;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.LanguageValidatorUtil.isLanguageValid; import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.LanguageValidatorUtil.isLanguageValid;
@Deprecated @Deprecated
@@ -80,7 +79,7 @@ public class AttributeConfigValidator extends ConfigValidator<List<AttributeConf
} }
boolean isValid; boolean isValid;
for (AttributeConfig attributeConfig : result) { for (AttributeConfig attributeConfig : result) {
isValid = isAudioLanguageValid(attributeConfig.getAudioLanguage()) isValid = isLanguageValid(attributeConfig.getAudioLanguage())
&& isLanguageValid(attributeConfig.getSubtitleLanguage()); && isLanguageValid(attributeConfig.getSubtitleLanguage());
if (!isValid) return false; if (!isValid) return false;
} }

View File

@@ -40,7 +40,7 @@ public class DateValidator extends ConfigValidator<Date> {
YAML yaml = new YAML(lastExecutionFile); YAML yaml = new YAML(lastExecutionFile);
return parse(yaml.getString(Config.getInstance().getNormalizedLibraryPath(), DateUtils.convert(DEFAULT_DATE))); return parse(yaml.getString(Config.getInstance().getNormalizedLibraryPath(), DateUtils.convert(DEFAULT_DATE)));
} catch (YamlInvalidContentException | IOException e) { } catch (YamlInvalidContentException | IOException e) {
log.error("Couldn't open last-execution.properties"); log.error("Couldn't open last-execution.properties", e);
return INVALID_DATE; return INVALID_DATE;
} }
} }

View File

@@ -41,7 +41,7 @@ public class FileFilter {
BasicFileAttributes attributes = Files.readAttributes(pathName.toPath(), BasicFileAttributes.class); BasicFileAttributes attributes = Files.readAttributes(pathName.toPath(), BasicFileAttributes.class);
return isNewer(DateUtils.convert(attributes.creationTime().toMillis())); return isNewer(DateUtils.convert(attributes.creationTime().toMillis()));
} catch (IOException e) { } catch (IOException e) {
log.warn("File attributes could not be read.", e); log.warn("File attributes could not be read", e);
} }
return true; return true;
} }

View File

@@ -3,7 +3,7 @@ package at.pcgamingfreaks.mkvaudiosubtitlechanger.impl;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.exceptions.MkvToolNixException; import at.pcgamingfreaks.mkvaudiosubtitlechanger.exceptions.MkvToolNixException;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.AttributeConfig; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.AttributeConfig;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileAttribute; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileAttribute;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileInfoDto; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileInfo;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -25,7 +25,7 @@ public interface FileProcessor {
* @param attributes Track information of FileInfoDto * @param attributes Track information of FileInfoDto
* @param nonForcedTracks List of all not forced tracks * @param nonForcedTracks List of all not forced tracks
*/ */
void detectDefaultTracks(FileInfoDto info, List<FileAttribute> attributes, List<FileAttribute> nonForcedTracks); void detectDefaultTracks(FileInfo info, List<FileAttribute> attributes, List<FileAttribute> nonForcedTracks);
/** /**
* Populate FileInfoDto with the desired tracks, based on AttributeConfig. * Populate FileInfoDto with the desired tracks, based on AttributeConfig.
@@ -33,7 +33,7 @@ public interface FileProcessor {
* @param nonForcedTracks List of all non-forced tracks * @param nonForcedTracks List of all non-forced tracks
* @param nonCommentaryTracks List of all non-commentary tracks * @param nonCommentaryTracks List of all non-commentary tracks
*/ */
void detectDesiredTracks(FileInfoDto info, List<FileAttribute> nonForcedTracks, List<FileAttribute> nonCommentaryTracks, void detectDesiredTracks(FileInfo info, List<FileAttribute> nonForcedTracks, List<FileAttribute> nonCommentaryTracks,
AttributeConfig... configs); AttributeConfig... configs);
List<FileAttribute> retrieveNonForcedTracks(List<FileAttribute> attributes); List<FileAttribute> retrieveNonForcedTracks(List<FileAttribute> attributes);
@@ -43,9 +43,9 @@ public interface FileProcessor {
/** /**
* Update the file. * Update the file.
* @param file to be updated * @param file to be updated
* @param fileInfo information to update file * @param fileInfo information used to update file
* @throws IOException when error occurs accessing file retrieving information * @throws IOException when error occurs accessing file retrieving information
* @throws MkvToolNixException when error occurs while sending query to mkvpropedit * @throws MkvToolNixException when error occurs while sending query to mkvpropedit
*/ */
void update(File file, FileInfoDto fileInfo) throws IOException, MkvToolNixException; void update(File file, FileInfo fileInfo) throws IOException, MkvToolNixException;
} }

View File

@@ -28,10 +28,10 @@ public class MkvFileProcessor implements FileProcessor {
private static final SubtitleTrackComparator subtitleTrackComparator = private static final SubtitleTrackComparator subtitleTrackComparator =
new SubtitleTrackComparator(Config.getInstance().getPreferredSubtitles().toArray(new String[0])); new SubtitleTrackComparator(Config.getInstance().getPreferredSubtitles().toArray(new String[0]));
private static final String DISABLE_DEFAULT_TRACK = "--edit track:%s --set flag-default=0 "; private static final String DISABLE_DEFAULT_TRACK = "--edit track:%s --set flag-default=0";
private static final String ENABLE_DEFAULT_TRACK = "--edit track:%s --set flag-default=1 "; private static final String ENABLE_DEFAULT_TRACK = "--edit track:%s --set flag-default=1";
private static final String DISABLE_FORCED_TRACK = "--edit track:%s --set flag-forced=0 "; private static final String DISABLE_FORCED_TRACK = "--edit track:%s --set flag-forced=0";
private static final String ENABLE_FORCED_TRACK = "--edit track:%s --set flag-forced=1 "; private static final String ENABLE_FORCED_TRACK = "--edit track:%s --set flag-forced=1";
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
@@ -39,16 +39,17 @@ public class MkvFileProcessor implements FileProcessor {
Map<String, Object> jsonMap; Map<String, Object> jsonMap;
List<FileAttribute> fileAttributes = new ArrayList<>(); List<FileAttribute> fileAttributes = new ArrayList<>();
try { try {
String command = format("\"%s\"", Config.getInstance().getPathFor(MkvToolNix.MKV_MERGE)); String[] command = new String[]{
String[] arguments = new String[]{ Config.getInstance().getPathFor(MkvToolNix.MKV_MERGE),
command,
"--identify", "--identify",
"--identification-format", "--identification-format",
"json", "json",
file.getAbsoluteFile().toString() file.getAbsolutePath()
}; };
InputStream inputStream = Runtime.getRuntime().exec(arguments).getInputStream(); log.debug("Executing '{}': {}", file.getAbsolutePath(), String.join(" ", command));
InputStream inputStream = Runtime.getRuntime().exec(command)
.getInputStream();
jsonMap = mapper.readValue(inputStream, Map.class); jsonMap = mapper.readValue(inputStream, Map.class);
List<Map<String, Object>> tracks = (List<Map<String, Object>>) jsonMap.get("tracks"); List<Map<String, Object>> tracks = (List<Map<String, Object>>) jsonMap.get("tracks");
if (tracks == null) { if (tracks == null) {
@@ -68,7 +69,7 @@ public class MkvFileProcessor implements FileProcessor {
} }
} }
log.debug(fileAttributes.toString()); log.debug("File attributes of '{}': {}", file.getAbsolutePath(), fileAttributes.toString());
} catch (IOException e) { } catch (IOException e) {
log.error("File could not be found or loaded: ", e); log.error("File could not be found or loaded: ", e);
System.out.println("File could not be found or loaded: " + file.getAbsolutePath()); System.out.println("File could not be found or loaded: " + file.getAbsolutePath());
@@ -80,15 +81,15 @@ public class MkvFileProcessor implements FileProcessor {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public void detectDefaultTracks(FileInfoDto info, List<FileAttribute> attributes, List<FileAttribute> nonForcedTracks) { public void detectDefaultTracks(FileInfo info, List<FileAttribute> attributes, List<FileAttribute> nonForcedTracks) {
for (FileAttribute attribute : attributes) { for (FileAttribute attribute : attributes) {
if (AUDIO.equals(attribute.getType())) { if (AUDIO.equals(attribute.type())) {
if (attribute.isDefaultTrack()) info.getExistingDefaultAudioLanes().add(attribute); if (attribute.defaultTrack()) info.getExistingDefaultAudioLanes().add(attribute);
if (attribute.isForcedTrack()) info.getExistingForcedAudioLanes().add(attribute); if (attribute.forcedTrack()) info.getExistingForcedAudioLanes().add(attribute);
} else if (SUBTITLES.equals(attribute.getType())) { } else if (SUBTITLES.equals(attribute.type())) {
if (attribute.isDefaultTrack()) info.getExistingDefaultSubtitleLanes().add(attribute); if (attribute.defaultTrack()) info.getExistingDefaultSubtitleLanes().add(attribute);
if (attribute.isForcedTrack()) info.getExistingForcedSubtitleLanes().add(attribute); if (attribute.forcedTrack()) info.getExistingForcedSubtitleLanes().add(attribute);
else if (!nonForcedTracks.contains(attribute)) info.getDesiredForcedSubtitleLanes().add(attribute); else if (!nonForcedTracks.contains(attribute)) info.getDesiredForcedSubtitleLanes().add(attribute);
} }
} }
@@ -98,19 +99,20 @@ public class MkvFileProcessor implements FileProcessor {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public void detectDesiredTracks(FileInfoDto info, List<FileAttribute> nonForcedTracks, List<FileAttribute> nonCommentaryTracks, public void detectDesiredTracks(FileInfo info, List<FileAttribute> nonForcedTracks, List<FileAttribute> nonCommentaryTracks,
AttributeConfig... configs) { AttributeConfig... configs) {
Set<FileAttribute> tracks = SetUtils.retainOf(nonForcedTracks, nonCommentaryTracks); Set<FileAttribute> tracks = SetUtils.retainOf(nonForcedTracks, nonCommentaryTracks);
Set<FileAttribute> audioTracks = tracks.stream().filter(a -> AUDIO.equals(a.getType())).collect(Collectors.toSet()); Set<FileAttribute> audioTracks = tracks.stream().filter(a -> AUDIO.equals(a.type())).collect(Collectors.toSet());
Set<FileAttribute> subtitleTracks = tracks.stream().filter(a -> SUBTITLES.equals(a.getType())).collect(Collectors.toSet()); Set<FileAttribute> subtitleTracks = tracks.stream().filter(a -> SUBTITLES.equals(a.type())).collect(Collectors.toSet());
for (AttributeConfig config : configs) { for (AttributeConfig config : configs) {
Optional<FileAttribute> desiredAudio = detectDesiredTrack(config.getAudioLanguage(), audioTracks).findFirst(); Optional<FileAttribute> desiredAudio = detectDesiredTrack(config.getAudioLanguage(), audioTracks).findFirst();
Optional<FileAttribute> desiredSubtitle = detectDesiredSubtitleTrack(config.getSubtitleLanguage(), subtitleTracks).findFirst(); Optional<FileAttribute> desiredSubtitle = detectDesiredSubtitleTrack(config.getSubtitleLanguage(), subtitleTracks).findFirst();
if (desiredAudio.isPresent() && ("OFF".equals(config.getSubtitleLanguage()) || desiredSubtitle.isPresent())) { if (("OFF".equals(config.getAudioLanguage()) || desiredAudio.isPresent())
&& ("OFF".equals(config.getSubtitleLanguage()) || desiredSubtitle.isPresent())) {
info.setMatchedConfig(config); info.setMatchedConfig(config);
info.setDesiredDefaultAudioLane(desiredAudio.get()); info.setDesiredDefaultAudioLane(desiredAudio.orElse(null));
info.setDesiredDefaultSubtitleLane(desiredSubtitle.orElse(null)); info.setDesiredDefaultSubtitleLane(desiredSubtitle.orElse(null));
break; break;
} }
@@ -118,7 +120,7 @@ public class MkvFileProcessor implements FileProcessor {
} }
private Stream<FileAttribute> detectDesiredTrack(String language, Set<FileAttribute> tracks) { private Stream<FileAttribute> detectDesiredTrack(String language, Set<FileAttribute> tracks) {
return tracks.stream().filter(track -> language.equals(track.getLanguage())); return tracks.stream().filter(track -> language.equals(track.language()));
} }
private Stream<FileAttribute> detectDesiredSubtitleTrack(String language, Set<FileAttribute> tracks) { private Stream<FileAttribute> detectDesiredSubtitleTrack(String language, Set<FileAttribute> tracks) {
@@ -129,16 +131,16 @@ public class MkvFileProcessor implements FileProcessor {
@Override @Override
public List<FileAttribute> retrieveNonForcedTracks(List<FileAttribute> attributes) { public List<FileAttribute> retrieveNonForcedTracks(List<FileAttribute> attributes) {
return attributes.stream() return attributes.stream()
.filter(elem -> !StringUtils.containsAnyIgnoreCase(elem.getTrackName(), .filter(elem -> !StringUtils.containsAnyIgnoreCase(elem.trackName(),
Config.getInstance().getForcedKeywords().toArray(new CharSequence[0]))) Config.getInstance().getForcedKeywords().toArray(new CharSequence[0])))
.filter(elem -> !elem.isForcedTrack()) .filter(elem -> !elem.forcedTrack())
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
@Override @Override
public List<FileAttribute> retrieveNonCommentaryTracks(List<FileAttribute> attributes) { public List<FileAttribute> retrieveNonCommentaryTracks(List<FileAttribute> attributes) {
return attributes.stream() return attributes.stream()
.filter(elem -> !StringUtils.containsAnyIgnoreCase(elem.getTrackName(), .filter(elem -> !StringUtils.containsAnyIgnoreCase(elem.trackName(),
Config.getInstance().getCommentaryKeywords().toArray(new CharSequence[0]))) Config.getInstance().getCommentaryKeywords().toArray(new CharSequence[0])))
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
@@ -147,47 +149,50 @@ public class MkvFileProcessor implements FileProcessor {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public void update(File file, FileInfoDto fileInfo) throws IOException, MkvToolNixException { public void update(File file, FileInfo fileInfo) throws IOException, MkvToolNixException {
StringBuilder sb = new StringBuilder(); List<String> command = new ArrayList<>();
sb.append(format("\"%s\" ", Config.getInstance().getPathFor(MkvToolNix.MKV_PROP_EDIT))); command.add(Config.getInstance().getPathFor(MkvToolNix.MKV_PROP_EDIT));
sb.append(format("\"%s\" ", file.getAbsolutePath())); command.add(String.format(file.getAbsolutePath()));
if (fileInfo.isAudioDifferent()) { if (fileInfo.isAudioDifferent()) {
if (fileInfo.getExistingDefaultAudioLanes() != null && !fileInfo.getExistingDefaultAudioLanes().isEmpty()) { removeExistingAndAddDesiredLanes(fileInfo.getExistingDefaultAudioLanes(), fileInfo.getDesiredDefaultAudioLane(), command);
for (FileAttribute track: fileInfo.getExistingDefaultAudioLanes()) {
sb.append(format(DISABLE_DEFAULT_TRACK, track.getId()));
}
}
sb.append(format(ENABLE_DEFAULT_TRACK, fileInfo.getDesiredDefaultAudioLane().getId()));
} }
if (!fileInfo.getExistingForcedAudioLanes().isEmpty()) { if (!fileInfo.getExistingForcedAudioLanes().isEmpty()) {
for (FileAttribute track: fileInfo.getExistingForcedAudioLanes()) { for (FileAttribute track : fileInfo.getExistingForcedAudioLanes()) {
sb.append(format(DISABLE_FORCED_TRACK, track.getId())); command.addAll(format(DISABLE_FORCED_TRACK, track.id()));
} }
} }
if (fileInfo.isSubtitleDifferent()) { if (fileInfo.isSubtitleDifferent()) {
if (fileInfo.getExistingDefaultSubtitleLanes() != null && !fileInfo.getExistingDefaultSubtitleLanes().isEmpty()) { removeExistingAndAddDesiredLanes(fileInfo.getExistingDefaultSubtitleLanes(), fileInfo.getDesiredDefaultSubtitleLane(), command);
for (FileAttribute track: fileInfo.getExistingDefaultSubtitleLanes()) {
sb.append(format(DISABLE_DEFAULT_TRACK, track.getId()));
}
}
if (fileInfo.getDesiredDefaultSubtitleLane() != null) {
sb.append(format(ENABLE_DEFAULT_TRACK, fileInfo.getDesiredDefaultSubtitleLane().getId()));
}
} }
if (fileInfo.areForcedTracksDifferent()) { if (fileInfo.areForcedTracksDifferent()) {
for (FileAttribute attribute : fileInfo.getDesiredForcedSubtitleLanes()) { for (FileAttribute track : fileInfo.getDesiredForcedSubtitleLanes()) {
sb.append(format(ENABLE_FORCED_TRACK, attribute.getId())); command.addAll(format(ENABLE_FORCED_TRACK, track.id()));
} }
} }
log.info(sb.toString()); log.debug("Executing '{}'", String.join(" ", command));
InputStream inputstream = Runtime.getRuntime().exec(sb.toString()).getInputStream(); InputStream inputstream = Runtime.getRuntime().exec(command.toArray(new String[0])).getInputStream();
String output = IOUtils.toString(new InputStreamReader(inputstream)); String output = IOUtils.toString(new InputStreamReader(inputstream));
log.debug(output); log.debug("Result: {}", output);
if (output.contains("Error")) throw new MkvToolNixException(output); if (output.contains("Error")) throw new MkvToolNixException(output);
} }
private void removeExistingAndAddDesiredLanes(Set<FileAttribute> existingDefaultLanes, FileAttribute desiredDefaultLanes, List<String> command) {
if (existingDefaultLanes != null && !existingDefaultLanes.isEmpty()) {
for (FileAttribute track : existingDefaultLanes) {
command.addAll(format(DISABLE_DEFAULT_TRACK, track.id()));
}
}
if (desiredDefaultLanes != null) {
command.addAll(format(ENABLE_DEFAULT_TRACK, desiredDefaultLanes.id()));
}
}
private List<String> format(String format, Object... args) {
return Arrays.asList(String.format(format, args).split(" "));
}
} }

View File

@@ -17,16 +17,16 @@ public class SubtitleTrackComparator implements Comparator<FileAttribute> {
public int compare(FileAttribute track1, FileAttribute track2) { public int compare(FileAttribute track1, FileAttribute track2) {
int result = 0; int result = 0;
if (StringUtils.containsAnyIgnoreCase(track1.getTrackName(), preferredSubtitles)) { if (StringUtils.containsAnyIgnoreCase(track1.trackName(), preferredSubtitles)) {
result++; result++;
} }
if (StringUtils.containsAnyIgnoreCase(track2.getTrackName(), preferredSubtitles)) { if (StringUtils.containsAnyIgnoreCase(track2.trackName(), preferredSubtitles)) {
result--; result--;
} }
if (result == 0) { if (result == 0) {
if (track1.isDefaultTrack()) result++; if (track1.defaultTrack()) result++;
if (track2.isDefaultTrack()) result--; if (track2.defaultTrack()) result--;
} }
return result; return result;

View File

@@ -6,7 +6,7 @@ import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.FileCollector;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.FileProcessor; import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.FileProcessor;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.AttributeConfig; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.AttributeConfig;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileAttribute; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileAttribute;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileInfoDto; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileInfo;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.ResultStatistic; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.ResultStatistic;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.util.DateUtils; import at.pcgamingfreaks.mkvaudiosubtitlechanger.util.DateUtils;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.util.ProjectUtil; import at.pcgamingfreaks.mkvaudiosubtitlechanger.util.ProjectUtil;
@@ -19,7 +19,6 @@ import me.tongfei.progressbar.ProgressBar;
import me.tongfei.progressbar.ProgressBarBuilder; import me.tongfei.progressbar.ProgressBarBuilder;
import me.tongfei.progressbar.ProgressBarStyle; import me.tongfei.progressbar.ProgressBarStyle;
import net.harawata.appdirs.AppDirsFactory; import net.harawata.appdirs.AppDirsFactory;
import picocli.CommandLine;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -97,9 +96,16 @@ public abstract class AttributeUpdaterKernel {
* @param file file or directory to update * @param file file or directory to update
*/ */
void process(File file) { void process(File file) {
FileInfoDto fileInfo = new FileInfoDto(file); FileInfo fileInfo = new FileInfo(file);
List<FileAttribute> attributes = processor.loadAttributes(file); List<FileAttribute> attributes = processor.loadAttributes(file);
if (attributes == null || attributes.isEmpty()) {
log.warn("No attributes found for file {}", file);
statistic.total();
statistic.failure();
return;
}
List<FileAttribute> nonForcedTracks = processor.retrieveNonForcedTracks(attributes); List<FileAttribute> nonForcedTracks = processor.retrieveNonForcedTracks(attributes);
List<FileAttribute> nonCommentaryTracks = processor.retrieveNonCommentaryTracks(attributes); List<FileAttribute> nonCommentaryTracks = processor.retrieveNonCommentaryTracks(attributes);
@@ -113,16 +119,16 @@ public abstract class AttributeUpdaterKernel {
/** /**
* Persist file changes. * Persist file changes.
* *
* @param fileInfoDto contains information about file and desired configuration. * @param fileInfo contains information about file and desired configuration.
*/ */
protected void updateFile(FileInfoDto fileInfoDto) { protected void updateFile(FileInfo fileInfo) {
statistic.total(); statistic.total();
switch (fileInfoDto.getStatus()) { switch (fileInfo.getStatus()) {
case CHANGE_NECESSARY: case CHANGE_NECESSARY:
statistic.shouldChange(); statistic.shouldChange();
commitChange(fileInfoDto); commitChange(fileInfo);
break; break;
case UNABLE_TO_APPLY: case NO_SUITABLE_CONFIG:
statistic.noSuitableConfigFound(); statistic.noSuitableConfigFound();
break; break;
case ALREADY_SUITED: case ALREADY_SUITED:
@@ -135,7 +141,7 @@ public abstract class AttributeUpdaterKernel {
} }
} }
private void commitChange(FileInfoDto fileInfo) { private void commitChange(FileInfo fileInfo) {
if (Config.getInstance().isSafeMode()) { if (Config.getInstance().isSafeMode()) {
return; return;
} }
@@ -143,10 +149,10 @@ public abstract class AttributeUpdaterKernel {
try { try {
processor.update(fileInfo.getFile(), fileInfo); processor.update(fileInfo.getFile(), fileInfo);
statistic.success(); statistic.success();
log.info("Updated {}", fileInfo.getFile().getAbsolutePath()); log.info("Commited {} to '{}'", fileInfo.getMatchedConfig().toStringShort(), fileInfo.getFile().getAbsolutePath());
} catch (IOException | MkvToolNixException e) { } catch (IOException | MkvToolNixException e) {
statistic.failedChanging(); statistic.failedChanging();
log.warn("File couldn't be updated: '{}', Error: {}", fileInfo.getFile().getAbsoluteFile(), e.getMessage()); log.warn("Couldn't commit {} to '{}'", fileInfo.getMatchedConfig().toStringShort(), fileInfo.getFile().getAbsoluteFile(), e);
} }
} }

View File

@@ -5,7 +5,7 @@ import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.FileCollector;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.FileProcessor; import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.FileProcessor;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.AttributeConfig; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.AttributeConfig;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileAttribute; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileAttribute;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileInfoDto; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileInfo;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import me.tongfei.progressbar.ProgressBarBuilder; import me.tongfei.progressbar.ProgressBarBuilder;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@@ -67,13 +67,13 @@ public class CoherentAttributeUpdaterKernel extends AttributeUpdaterKernel {
void process(File file, int depth) { void process(File file, int depth) {
// TODO: Implement level crawl if coherence is not possible on user entered depth // TODO: Implement level crawl if coherence is not possible on user entered depth
// IMPL idea: recursive method call, cache needs to be implemented // IMPL idea: recursive method call, cache needs to be implemented
List<FileInfoDto> fileInfos = collector.loadFiles(file.getAbsolutePath()).stream() List<FileInfo> fileInfos = collector.loadFiles(file.getAbsolutePath()).stream()
.map(FileInfoDto::new) .map(FileInfo::new)
.collect(Collectors.toList()); .collect(Collectors.toList());
for (AttributeConfig config : Config.getInstance().getAttributeConfig()) { for (AttributeConfig config : Config.getInstance().getAttributeConfig()) {
for (FileInfoDto fileInfo : fileInfos) { for (FileInfo fileInfo : fileInfos) {
List<FileAttribute> attributes = processor.loadAttributes(fileInfo.getFile()); List<FileAttribute> attributes = processor.loadAttributes(fileInfo.getFile());
List<FileAttribute> nonForcedTracks = processor.retrieveNonForcedTracks(attributes); List<FileAttribute> nonForcedTracks = processor.retrieveNonForcedTracks(attributes);
@@ -85,7 +85,7 @@ public class CoherentAttributeUpdaterKernel extends AttributeUpdaterKernel {
if (fileInfos.stream().allMatch(elem -> ("OFF".equals(config.getSubtitleLanguage()) || elem.getDesiredDefaultSubtitleLane() != null) if (fileInfos.stream().allMatch(elem -> ("OFF".equals(config.getSubtitleLanguage()) || elem.getDesiredDefaultSubtitleLane() != null)
&& elem.getDesiredDefaultAudioLane() != null)) { && elem.getDesiredDefaultAudioLane() != null)) {
log.info("Found {}/{} match for {}", config.getAudioLanguage(), config.getSubtitleLanguage(), file.getAbsolutePath()); log.info("Found {} match for {}", config.toStringShort(), file.getAbsolutePath());
fileInfos.forEach(this::updateFile); fileInfos.forEach(this::updateFile);
return; // match found, end process here return; // match found, end process here
} }
@@ -98,7 +98,7 @@ public class CoherentAttributeUpdaterKernel extends AttributeUpdaterKernel {
log.info("No coherent match found for {}", file.getAbsoluteFile()); log.info("No coherent match found for {}", file.getAbsoluteFile());
for (FileInfoDto fileInfo : fileInfos) { for (FileInfo fileInfo : fileInfos) {
if (!Config.getInstance().isForceCoherent()) { if (!Config.getInstance().isForceCoherent()) {
super.process(fileInfo.getFile()); super.process(fileInfo.getFile());
} else { } else {

View File

@@ -26,6 +26,10 @@ public class AttributeConfig {
return Objects.hash(audioLanguage, subtitleLanguage); return Objects.hash(audioLanguage, subtitleLanguage);
} }
public String toStringShort() {
return audioLanguage + ":" + subtitleLanguage;
}
@Override @Override
public String toString() { public String toString() {
return "AttributeConfig{" return "AttributeConfig{"

View File

@@ -1,22 +1,12 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.model; package at.pcgamingfreaks.mkvaudiosubtitlechanger.model;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.util.Objects; import java.util.Objects;
@Slf4j @Slf4j
@Getter public record FileAttribute(int id, String language, String trackName, boolean defaultTrack, boolean forcedTrack,
@AllArgsConstructor LaneType type) {
public class FileAttribute {
private final int id;
private final String language;
private final String trackName;
private final boolean defaultTrack;
private final boolean forcedTrack;
private final LaneType type;
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;
@@ -30,11 +20,6 @@ public class FileAttribute {
&& type == attribute.type; && type == attribute.type;
} }
@Override
public int hashCode() {
return Objects.hash(id, language, trackName, defaultTrack, forcedTrack, type);
}
@Override @Override
public String toString() { public String toString() {
return "[" + "id=" + id + return "[" + "id=" + id +

View File

@@ -0,0 +1,84 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.model;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Function;
@Getter
@Setter
@RequiredArgsConstructor
public class FileInfo {
private final File file;
private Set<FileAttribute> existingDefaultAudioLanes = new HashSet<>();
private Set<FileAttribute> existingForcedAudioLanes = new HashSet<>();
private Set<FileAttribute> existingDefaultSubtitleLanes = new HashSet<>();
private Set<FileAttribute> existingForcedSubtitleLanes = new HashSet<>();
private Set<FileAttribute> desiredForcedSubtitleLanes = new HashSet<>();
private FileAttribute desiredDefaultAudioLane;
private FileAttribute desiredDefaultSubtitleLane;
private AttributeConfig matchedConfig;
public boolean isAudioDifferent() {
return isMatchDifferent(existingDefaultAudioLanes, desiredDefaultAudioLane)
|| isLaneOff(existingDefaultAudioLanes, desiredDefaultAudioLane, AttributeConfig::getAudioLanguage);
}
public boolean isSubtitleDifferent() {
return isMatchDifferent(existingDefaultSubtitleLanes, desiredDefaultSubtitleLane)
|| isLaneOff(existingDefaultSubtitleLanes, desiredDefaultSubtitleLane, AttributeConfig::getSubtitleLanguage);
}
private boolean isMatchDifferent(Set<FileAttribute> existingDefault, FileAttribute desiredDefault) {
return desiredDefault != null &&
(existingDefault == null || !existingDefault.contains(desiredDefault) || existingDefault.size() > 1);
}
private boolean isLaneOff(Set<FileAttribute> existingDefault, FileAttribute desiredDefault, Function<AttributeConfig, String> inputLane) {
return desiredDefault == null
&& (matchedConfig != null && "OFF".equals(inputLane.apply(matchedConfig)))
&& (existingDefault != null && !existingDefault.isEmpty());
}
public boolean areForcedTracksDifferent() {
return !desiredForcedSubtitleLanes.isEmpty() && !existingForcedSubtitleLanes.containsAll(desiredForcedSubtitleLanes);
}
public FileStatus getStatus() {
if (isChangeNecessary()) return FileStatus.CHANGE_NECESSARY;
if (isUnableToApplyConfig()) return FileStatus.NO_SUITABLE_CONFIG;
if (isAlreadySuited()) return FileStatus.ALREADY_SUITED;
return FileStatus.UNKNOWN;
}
private boolean isUnableToApplyConfig() {
return desiredDefaultAudioLane == null && !"OFF".equals(matchedConfig.getAudioLanguage())
&& desiredDefaultSubtitleLane == null && !"OFF".equals(matchedConfig.getSubtitleLanguage());
}
private boolean isAlreadySuited() {
return (desiredDefaultAudioLane == null || existingDefaultAudioLanes.contains(desiredDefaultAudioLane))
&& (desiredDefaultSubtitleLane == null || existingDefaultSubtitleLanes.contains(desiredDefaultSubtitleLane));
}
private boolean isChangeNecessary() {
return isAudioDifferent() || isSubtitleDifferent() || areForcedTracksDifferent() || !existingForcedAudioLanes.isEmpty();
}
@Override
public String toString() {
return "[" + "defaultAudioLanes=" + existingDefaultAudioLanes +
", defaultSubtitleLanes=" + existingDefaultSubtitleLanes +
", desiredForcedSubtitleLanes=" + desiredForcedSubtitleLanes +
", desiredAudioLane=" + desiredDefaultAudioLane +
", desiredSubtitleLane=" + desiredDefaultSubtitleLane +
']';
}
}

View File

@@ -1,79 +0,0 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.model;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
@Getter
@Setter
@RequiredArgsConstructor
public class FileInfoDto {
private final File file;
private Set<FileAttribute> existingDefaultAudioLanes = new HashSet<>();
private Set<FileAttribute> existingForcedAudioLanes = new HashSet<>();
private Set<FileAttribute> existingDefaultSubtitleLanes = new HashSet<>();
private Set<FileAttribute> existingForcedSubtitleLanes = new HashSet<>();
private Set<FileAttribute> desiredForcedSubtitleLanes = new HashSet<>();
private FileAttribute desiredDefaultAudioLane;
private FileAttribute desiredDefaultSubtitleLane;
private AttributeConfig matchedConfig;
public boolean isAudioDifferent() {
return desiredDefaultAudioLane != null &&
(existingDefaultAudioLanes == null || !existingDefaultAudioLanes.contains(desiredDefaultAudioLane) || existingDefaultAudioLanes.size() > 1);
}
public boolean isSubtitleDifferent() {
return isSubtitleMatchDifferent() || isSubtitleOFF();
}
private boolean isSubtitleMatchDifferent() {
return desiredDefaultSubtitleLane != null
&& (existingDefaultSubtitleLanes == null || !existingDefaultSubtitleLanes.contains(desiredDefaultSubtitleLane) || existingDefaultSubtitleLanes.size() > 1);
}
private boolean isSubtitleOFF() {
return desiredDefaultSubtitleLane == null && "OFF".equals(matchedConfig.getSubtitleLanguage()) &&
(existingDefaultSubtitleLanes != null && !existingDefaultSubtitleLanes.isEmpty());
}
public boolean areForcedTracksDifferent() {
return !desiredForcedSubtitleLanes.isEmpty();
}
public FileStatus getStatus() {
if (isChangeNecessary()) return FileStatus.CHANGE_NECESSARY;
if (isUnableToApplyConfig()) return FileStatus.UNABLE_TO_APPLY;
if (isAlreadySuitable()) return FileStatus.ALREADY_SUITED;
return FileStatus.UNKNOWN;
}
private boolean isUnableToApplyConfig() {
return desiredDefaultAudioLane == null && desiredDefaultSubtitleLane == null;
}
private boolean isAlreadySuitable() {
return existingDefaultAudioLanes.contains(desiredDefaultAudioLane) && existingDefaultSubtitleLanes.contains(desiredDefaultSubtitleLane);
}
private boolean isChangeNecessary() {
return isAudioDifferent() || isSubtitleDifferent() || areForcedTracksDifferent() || !existingForcedAudioLanes.isEmpty();
}
@Override
public String toString() {
return "[" + "defaultAudioLanes=" + existingDefaultAudioLanes +
", defaultSubtitleLanes=" + existingDefaultSubtitleLanes +
", desiredForcedSubtitleLanes=" + desiredForcedSubtitleLanes +
", desiredAudioLane=" + desiredDefaultAudioLane +
", desiredSubtitleLane=" + desiredDefaultSubtitleLane +
']';
}
}

View File

@@ -2,7 +2,7 @@ package at.pcgamingfreaks.mkvaudiosubtitlechanger.model;
public enum FileStatus { public enum FileStatus {
CHANGE_NECESSARY, CHANGE_NECESSARY,
UNABLE_TO_APPLY, NO_SUITABLE_CONFIG,
ALREADY_SUITED, ALREADY_SUITED,
UNKNOWN; UNKNOWN;
} }

View File

@@ -23,10 +23,6 @@ public class LanguageValidatorUtil {
} }
} }
public static boolean isAudioLanguageValid(String language) {
return !language.equals("OFF") && isLanguageValid(language);
}
public static boolean isLanguageValid(String language) { public static boolean isLanguageValid(String language) {
return ISO3_LANGUAGES.contains(language); return ISO3_LANGUAGES.contains(language);
} }

View File

@@ -3,12 +3,12 @@ Configuration:
Appenders: Appenders:
RollingFile: RollingFile:
name: FileAppender name: FileAppender
fileName: /var/log/MKVAudioSubtitleChanger/application.log fileName: ${sys:user.home}/.local/mkvaudiosubtitlechanger/logs/application.log
filePattern: /var/log/MKVAudioSubtitleChanger/archive/application-%d{yyyy-MM-dd}-%i.log.gz filePattern: ${sys:user.home}/.local/mkvaudiosubtitlechanger/logs/archive/application-%d{yyyy-MM-dd}-%i.log.gz
PatternLayout: PatternLayout:
Pattern: "%d{DEFAULT} | %-5level | %thread | %msg %n %throwable" Pattern: "%d{DEFAULT} | %-5level | %thread | %C{1} | %msg %n %throwable"
ThresholdFilter: ThresholdFilter:
level: info level: debug
Policies: Policies:
OnStartupTriggeringPolicy: OnStartupTriggeringPolicy:
minSize: 0 minSize: 0

View File

@@ -4,7 +4,7 @@ Configuration:
Console: Console:
name: Console_Out name: Console_Out
PatternLayout: PatternLayout:
Pattern: "%d{DEFAULT} | %-5level | %thread | %msg %n %throwable" Pattern: "%d{DEFAULT} | %-5level | %thread | %C{1} | %msg %n %throwable"
ThresholdFilter: ThresholdFilter:
level: debug level: debug
RollingFile: RollingFile:
@@ -12,7 +12,7 @@ Configuration:
fileName: logs/application.log fileName: logs/application.log
filePattern: logs/archive/application-%d{yyyy-MM-dd}-%i.log.gz filePattern: logs/archive/application-%d{yyyy-MM-dd}-%i.log.gz
PatternLayout: PatternLayout:
Pattern: "%d{DEFAULT} | %-5level | %thread | %msg %n %throwable" Pattern: "%d{DEFAULT} | %-5level | %thread | %C{1} | %msg %n %throwable"
ThresholdFilter: ThresholdFilter:
level: debug level: debug
Policies: Policies:

View File

@@ -6,9 +6,9 @@ Configuration:
fileName: ${sys:user.home}/AppData/Roaming/MKVAudioSubtitleChanger/logs/application.log fileName: ${sys:user.home}/AppData/Roaming/MKVAudioSubtitleChanger/logs/application.log
filePattern: ${sys:user.home}/AppData/Roaming/MKVAudioSubtitleChanger/logs/archive/application-%d{yyyy-MM-dd}-%i.log.gz filePattern: ${sys:user.home}/AppData/Roaming/MKVAudioSubtitleChanger/logs/archive/application-%d{yyyy-MM-dd}-%i.log.gz
PatternLayout: PatternLayout:
Pattern: "%d{DEFAULT} | %-5level | %thread | %msg %n %throwable" Pattern: "%d{DEFAULT} | %-5level | %thread | %C{1} | %msg %n %throwable"
ThresholdFilter: ThresholdFilter:
level: info level: debug
Policies: Policies:
OnStartupTriggeringPolicy: OnStartupTriggeringPolicy:
minSize: 0 minSize: 0

View File

@@ -6,9 +6,9 @@ Configuration:
fileName: logs/application.log fileName: logs/application.log
filePattern: logs/archive/application-%d{yyyy-MM-dd}-%i.log.gz filePattern: logs/archive/application-%d{yyyy-MM-dd}-%i.log.gz
PatternLayout: PatternLayout:
Pattern: "%d{DEFAULT} | %-5level | %thread | %msg %n %throwable" Pattern: "%d{DEFAULT} | %-5level | %thread | %C{1} | %msg %n %throwable"
ThresholdFilter: ThresholdFilter:
level: info level: debug
Policies: Policies:
OnStartupTriggeringPolicy: OnStartupTriggeringPolicy:
minSize: 0 minSize: 0

View File

@@ -22,7 +22,7 @@ class ConfigTest {
"--commentary-keywords", "testCommentary", "--commentary-keywords", "testCommentary",
"--preferred-subtitles", "testPreferred" "--preferred-subtitles", "testPreferred"
}; };
CommandLine.populateCommand(Config.getInstance(), sut); CommandLine.populateCommand(Config.getInstance(true), sut);
assertTrue(Config.getInstance().getLibraryPath().exists()); assertTrue(Config.getInstance().getLibraryPath().exists());
assertEquals(List.of(new AttributeConfig("ger", "ger"), new AttributeConfig("eng", "eng")), assertEquals(List.of(new AttributeConfig("ger", "ger"), new AttributeConfig("eng", "eng")),
@@ -41,6 +41,5 @@ class ConfigTest {
assertTrue(Config.getInstance().getPreferredSubtitles().contains("testPreferred")); assertTrue(Config.getInstance().getPreferredSubtitles().contains("testPreferred"));
assertNull(Config.getInstance().getConfigPath()); assertNull(Config.getInstance().getConfigPath());
} }
} }

View File

@@ -0,0 +1,42 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.impl;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.Config;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.AttributeConfig;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileAttribute;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileInfo;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.FileInfoTestUtil.*;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.TestUtil.createFileInfo;
import static org.junit.jupiter.api.Assertions.*;
class MkvFileProcessorTest {
private static Stream<Arguments> detectDesiredTracks() {
return Stream.of(
Arguments.of(new AttributeConfig("ger", "OFF"), List.of(AUDIO_GER, AUDIO_ENG), new AttributeConfig[] {new AttributeConfig("ger", "OFF"), new AttributeConfig("eng", "OFF")}),
Arguments.of(new AttributeConfig("eng", "OFF"), List.of(AUDIO_ENG), new AttributeConfig[] {new AttributeConfig("ger", "OFF"), new AttributeConfig("eng", "OFF")}),
Arguments.of(new AttributeConfig("eng", "ger"), List.of(AUDIO_GER, AUDIO_ENG, SUB_GER, SUB_ENG), new AttributeConfig[] {new AttributeConfig("eng", "ger"), new AttributeConfig("ger", "eng")}),
Arguments.of(new AttributeConfig("ger", "eng"), List.of(AUDIO_GER, SUB_GER, SUB_ENG), new AttributeConfig[] {new AttributeConfig("eng", "ger"), new AttributeConfig("ger", "eng")}),
Arguments.of(new AttributeConfig("OFF", "ger"), List.of(AUDIO_GER, SUB_GER, SUB_ENG), new AttributeConfig[] {new AttributeConfig("OFF", "ger"), new AttributeConfig("ger", "eng")})
);
}
@ParameterizedTest
@MethodSource
void detectDesiredTracks(AttributeConfig expectedMatch, List<FileAttribute> tracks, AttributeConfig... configs) {
Config.getInstance().setPreferredSubtitles(Set.of());
FileInfo info = new FileInfo(null);
MkvFileProcessor processor = new MkvFileProcessor();
processor.detectDesiredTracks(info, tracks, tracks, configs);
assertEquals(expectedMatch.getAudioLanguage(), info.getMatchedConfig().getAudioLanguage());
assertEquals(expectedMatch.getSubtitleLanguage(), info.getMatchedConfig().getSubtitleLanguage());
}
}

View File

@@ -1,59 +0,0 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.model;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.Set;
import java.util.stream.Stream;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.TestUtil.createFileInfo;
import static org.junit.jupiter.api.Assertions.*;
class FileInfoDtoTest {
private static final FileAttribute AUDIO_GER_DEFAULT = new FileAttribute(0, "ger", "", true, false, LaneType.AUDIO);
private static final FileAttribute AUDIO_GER = new FileAttribute(0, "ger", "", false, false, LaneType.AUDIO);
private static final FileAttribute AUDIO_ENG_DEFAULT = new FileAttribute(1, "eng", "", true, false, LaneType.AUDIO);
private static final FileAttribute AUDIO_ENG = new FileAttribute(1, "eng", "", false, false, LaneType.AUDIO);
private static final FileAttribute SUB_GER_DEFAULT = new FileAttribute(0, "ger", "", true, false, LaneType.SUBTITLES);
private static final FileAttribute SUB_GER = new FileAttribute(0, "ger", "", false, false, LaneType.SUBTITLES);
private static final FileAttribute SUB_ENG_DEFAULT = new FileAttribute(1, "eng", "", true, false, LaneType.SUBTITLES);
private static final FileAttribute SUB_ENG = new FileAttribute(1, "eng", "", false, false, LaneType.SUBTITLES);
private static Stream<Arguments> isAudioDifferent() {
return Stream.of(
Arguments.of(createFileInfo(Set.of(AUDIO_GER_DEFAULT), AUDIO_GER_DEFAULT), false),
Arguments.of(createFileInfo(Set.of(AUDIO_GER_DEFAULT), AUDIO_ENG), true),
Arguments.of(createFileInfo(Set.of(AUDIO_GER_DEFAULT, AUDIO_ENG_DEFAULT), AUDIO_GER_DEFAULT), true),
Arguments.of(createFileInfo(Set.of(), AUDIO_GER), true),
Arguments.of(createFileInfo(null, AUDIO_GER), true)
);
}
@ParameterizedTest
@MethodSource
void isAudioDifferent(FileInfoDto underTest, boolean expected) {
assertEquals(expected, underTest.isAudioDifferent());
}
private static Stream<Arguments> isSubtitleDifferent() {
return Stream.of(
Arguments.of(createFileInfo(Set.of(SUB_GER_DEFAULT), SUB_GER_DEFAULT, new AttributeConfig("", "ger")), false),
Arguments.of(createFileInfo(Set.of(SUB_GER_DEFAULT), SUB_ENG, new AttributeConfig("", "eng")), true),
Arguments.of(createFileInfo(Set.of(SUB_GER_DEFAULT, SUB_ENG_DEFAULT), SUB_ENG, new AttributeConfig("", "eng")), true),
Arguments.of(createFileInfo(Set.of(), SUB_ENG, new AttributeConfig("", "ger")), true),
Arguments.of(createFileInfo(null, SUB_GER, new AttributeConfig("", "ger")), true),
Arguments.of(createFileInfo(null, null, new AttributeConfig("", "OFF")), false),
Arguments.of(createFileInfo(Set.of(), null, new AttributeConfig("", "OFF")), false),
Arguments.of(createFileInfo(Set.of(SUB_GER_DEFAULT), null, new AttributeConfig("", "OFF")), true)
);
}
@ParameterizedTest
@MethodSource
void isSubtitleDifferent(FileInfoDto underTest, boolean expected) {
assertEquals(expected, underTest.isSubtitleDifferent());
}
}

View File

@@ -0,0 +1,87 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.model;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.Set;
import java.util.stream.Stream;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileStatus.*;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.FileInfoTestUtil.*;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.TestUtil.*;
import static org.junit.jupiter.api.Assertions.*;
class FileInfoTest {
private static Stream<Arguments> isAudioDifferent() {
return Stream.of(
Arguments.of(createFileInfoAudio(Set.of(AUDIO_GER_DEFAULT), AUDIO_GER_DEFAULT, new AttributeConfig("ger", "")), false),
Arguments.of(createFileInfoAudio(Set.of(AUDIO_GER_DEFAULT), AUDIO_ENG, new AttributeConfig("eng", "")), true),
Arguments.of(createFileInfoAudio(Set.of(AUDIO_GER_DEFAULT, AUDIO_ENG_DEFAULT), AUDIO_GER_DEFAULT, new AttributeConfig("ger", "")), true),
Arguments.of(createFileInfoAudio(Set.of(), AUDIO_GER, new AttributeConfig("ger", "")), true),
Arguments.of(createFileInfoAudio(null, AUDIO_GER, new AttributeConfig("ger", "")), true),
Arguments.of(createFileInfoAudio(Set.of(AUDIO_GER_DEFAULT), null, new AttributeConfig("OFF", "")), true),
Arguments.of(createFileInfoAudio(Set.of(), null, new AttributeConfig("OFF", "")), false),
Arguments.of(createFileInfoAudio(null, null, new AttributeConfig("OFF", "")), false)
);
}
@ParameterizedTest
@MethodSource
void isAudioDifferent(FileInfo underTest, boolean expected) {
assertEquals(expected, underTest.isAudioDifferent());
}
private static Stream<Arguments> isSubtitleDifferent() {
return Stream.of(
Arguments.of(createFileInfoSubs(Set.of(SUB_GER_DEFAULT), SUB_GER_DEFAULT, new AttributeConfig("", "ger")), false),
Arguments.of(createFileInfoSubs(Set.of(SUB_GER_DEFAULT), SUB_ENG, new AttributeConfig("", "eng")), true),
Arguments.of(createFileInfoSubs(Set.of(SUB_GER_DEFAULT, SUB_ENG_DEFAULT), SUB_ENG, new AttributeConfig("", "eng")), true),
Arguments.of(createFileInfoSubs(Set.of(), SUB_ENG, new AttributeConfig("", "ger")), true),
Arguments.of(createFileInfoSubs(null, SUB_GER, new AttributeConfig("", "ger")), true),
Arguments.of(createFileInfoSubs(null, null, new AttributeConfig("", "OFF")), false),
Arguments.of(createFileInfoSubs(Set.of(), null, new AttributeConfig("", "OFF")), false),
Arguments.of(createFileInfoSubs(Set.of(SUB_GER_DEFAULT), null, new AttributeConfig("", "OFF")), true)
);
}
@ParameterizedTest
@MethodSource
void isSubtitleDifferent(FileInfo underTest, boolean expected) {
assertEquals(expected, underTest.isSubtitleDifferent());
}
private static Stream<Arguments> getStatus() {
return Stream.of(
Arguments.of(CHANGE_NECESSARY, createFileInfo(Set.of(AUDIO_GER_DEFAULT), AUDIO_ENG, Set.of(), null, Set.of(), Set.of(), Set.of(), new AttributeConfig("eng", "OFF"))),
Arguments.of(CHANGE_NECESSARY, createFileInfo(Set.of(), null, Set.of(SUB_GER_DEFAULT), SUB_ENG, Set.of(), Set.of(), Set.of(), new AttributeConfig("OFF", "eng"))),
Arguments.of(CHANGE_NECESSARY, createFileInfo(Set.of(AUDIO_GER_DEFAULT), AUDIO_ENG, Set.of(SUB_GER_DEFAULT), SUB_ENG, Set.of(), Set.of(), Set.of(), new AttributeConfig("OFF", "eng"))),
Arguments.of(CHANGE_NECESSARY, createFileInfo(Set.of(AUDIO_GER_DEFAULT), AUDIO_GER_DEFAULT, Set.of(SUB_GER_DEFAULT), SUB_GER_DEFAULT, Set.of(AUDIO_ENG_FORCED), Set.of(), Set.of(), new AttributeConfig("ger", "ger"))),
Arguments.of(CHANGE_NECESSARY, createFileInfo(Set.of(), null, Set.of(), null, Set.of(AUDIO_ENG_FORCED), Set.of(), Set.of(), new AttributeConfig("OFF", "OFF"))),
Arguments.of(CHANGE_NECESSARY, createFileInfo(Set.of(), null, Set.of(), null, Set.of(), Set.of(), Set.of(SUB_GER_FORCED), new AttributeConfig("OFF", "OFF"))),
Arguments.of(CHANGE_NECESSARY, createFileInfo(Set.of(), null, Set.of(), null, Set.of(), Set.of(SUB_ENG_FORCED), Set.of(SUB_GER_FORCED), new AttributeConfig("OFF", "OFF"))),
Arguments.of(CHANGE_NECESSARY, createFileInfo(Set.of(), null, Set.of(), null, Set.of(AUDIO_ENG_FORCED), Set.of(SUB_ENG_FORCED), Set.of(SUB_GER_FORCED), new AttributeConfig("OFF", "OFF"))),
Arguments.of(CHANGE_NECESSARY, createFileInfo(Set.of(AUDIO_GER_DEFAULT), AUDIO_ENG, Set.of(SUB_GER_DEFAULT), SUB_ENG, Set.of(AUDIO_ENG_FORCED), Set.of(SUB_ENG_FORCED), Set.of(SUB_GER_FORCED), new AttributeConfig("eng", "eng"))),
Arguments.of(CHANGE_NECESSARY, createFileInfo(Set.of(AUDIO_GER_DEFAULT), AUDIO_GER_DEFAULT, Set.of(SUB_GER_DEFAULT), SUB_GER_DEFAULT, Set.of(), Set.of(SUB_ENG_FORCED), Set.of(SUB_ENG_FORCED, SUB_GER), new AttributeConfig("ger", "ger"))),
Arguments.of(NO_SUITABLE_CONFIG, createFileInfo(Set.of(AUDIO_ENG_DEFAULT), null, Set.of(SUB_GER_DEFAULT), null, Set.of(), Set.of(), Set.of(), new AttributeConfig("eng", "ger"))),
Arguments.of(NO_SUITABLE_CONFIG, createFileInfo(Set.of(AUDIO_ENG_DEFAULT), null, Set.of(), null, Set.of(), Set.of(), Set.of(), new AttributeConfig("eng", "ger"))),
Arguments.of(NO_SUITABLE_CONFIG, createFileInfo(Set.of(), null, Set.of(), null, Set.of(), Set.of(), Set.of(), new AttributeConfig("eng", "ger"))),
Arguments.of(ALREADY_SUITED, createFileInfo(Set.of(), null, Set.of(), null, Set.of(), Set.of(), Set.of(), new AttributeConfig("OFF", "OFF"))),
Arguments.of(ALREADY_SUITED, createFileInfo(Set.of(AUDIO_GER_DEFAULT), AUDIO_GER_DEFAULT, Set.of(), null, Set.of(), Set.of(), Set.of(), new AttributeConfig("ger", "OFF"))),
Arguments.of(ALREADY_SUITED, createFileInfo(Set.of(), null, Set.of(SUB_ENG_DEFAULT), SUB_ENG_DEFAULT, Set.of(), Set.of(), Set.of(), new AttributeConfig("OFF", "ger"))),
Arguments.of(ALREADY_SUITED, createFileInfo(Set.of(AUDIO_GER_DEFAULT), AUDIO_GER_DEFAULT, Set.of(SUB_ENG_DEFAULT), SUB_ENG_DEFAULT, Set.of(), Set.of(), Set.of(), new AttributeConfig("ger", "eng"))),
Arguments.of(ALREADY_SUITED, createFileInfo(Set.of(AUDIO_GER_DEFAULT), AUDIO_GER_DEFAULT, Set.of(SUB_ENG_DEFAULT), SUB_ENG_DEFAULT, Set.of(), Set.of(SUB_GER_FORCED), Set.of(SUB_GER_FORCED), new AttributeConfig("ger", "eng")))
);
}
@ParameterizedTest
@MethodSource
void getStatus(FileStatus expected, FileInfo underTest) {
FileStatus actual = underTest.getStatus();
assertEquals(expected, actual);
}
}

View File

@@ -0,0 +1,20 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.util;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileAttribute;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.LaneType;
public class FileInfoTestUtil {
public static final FileAttribute AUDIO_GER_DEFAULT = new FileAttribute(0, "ger", "", true, false, LaneType.AUDIO);
public static final FileAttribute AUDIO_ENG_DEFAULT = new FileAttribute(1, "eng", "", true, false, LaneType.AUDIO);
public static final FileAttribute AUDIO_GER = new FileAttribute(0, "ger", "", false, false, LaneType.AUDIO);
public static final FileAttribute AUDIO_ENG = new FileAttribute(1, "eng", "", false, false, LaneType.AUDIO);
public static final FileAttribute AUDIO_GER_FORCED = new FileAttribute(0, "ger", "", false, true, LaneType.AUDIO);
public static final FileAttribute AUDIO_ENG_FORCED = new FileAttribute(1, "eng", "", false, true, LaneType.AUDIO);
public static final FileAttribute SUB_GER_DEFAULT = new FileAttribute(0, "ger", "", true, false, LaneType.SUBTITLES);
public static final FileAttribute SUB_ENG_DEFAULT = new FileAttribute(1, "eng", "", true, false, LaneType.SUBTITLES);
public static final FileAttribute SUB_GER = new FileAttribute(0, "ger", "", false, false, LaneType.SUBTITLES);
public static final FileAttribute SUB_ENG = new FileAttribute(1, "eng", "", false, false, LaneType.SUBTITLES);
public static final FileAttribute SUB_GER_FORCED = new FileAttribute(0, "ger", "", false, true, LaneType.SUBTITLES);
public static final FileAttribute SUB_ENG_FORCED = new FileAttribute(1, "eng", "", false, true, LaneType.SUBTITLES);
}

View File

@@ -4,7 +4,7 @@ import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.ValidationResult;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.AttributeConfig; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.AttributeConfig;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.ConfigProperty; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.ConfigProperty;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileAttribute; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileAttribute;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileInfoDto; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileInfo;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import java.util.Arrays; import java.util.Arrays;
@@ -20,28 +20,46 @@ public class TestUtil {
} }
public static <T> Arguments argumentsOf(ConfigProperty property, boolean required, T defaultValue, String yaml, String[] cmd, public static <T> Arguments argumentsOf(ConfigProperty property, boolean required, T defaultValue, String yaml, String[] cmd,
ValidationResult result) { ValidationResult result) {
return Arguments.of(property, required, defaultValue, yaml, cmd, result); return Arguments.of(property, required, defaultValue, yaml, cmd, result);
} }
public static Arguments argumentsOf(ConfigProperty property, boolean required, boolean append, String yaml, String[] cmd, public static Arguments argumentsOf(ConfigProperty property, boolean required, boolean append, String yaml, String[] cmd,
ValidationResult result, int expectedSize) { ValidationResult result, int expectedSize) {
return Arguments.of(property, required, append, yaml, cmd, result, expectedSize); return Arguments.of(property, required, append, yaml, cmd, result, expectedSize);
} }
public static FileInfoDto createFileInfo(Set<FileAttribute> defaultAudio, FileAttribute desiredAudio) { public static FileInfo createFileInfoAudio(Set<FileAttribute> defaultAudio, FileAttribute desiredAudio, AttributeConfig config) {
FileInfoDto fileInfoDto = new FileInfoDto(null); FileInfo fileInfo = new FileInfo(null);
fileInfoDto.setExistingDefaultAudioLanes(defaultAudio); fileInfo.setExistingDefaultAudioLanes(defaultAudio);
fileInfoDto.setDesiredDefaultAudioLane(desiredAudio); fileInfo.setDesiredDefaultAudioLane(desiredAudio);
return fileInfoDto; fileInfo.setMatchedConfig(config);
return fileInfo;
} }
public static FileInfoDto createFileInfo(Set<FileAttribute> defaultSubtitle, FileAttribute desiredSubtitle, AttributeConfig config) { public static FileInfo createFileInfoSubs(Set<FileAttribute> defaultSubtitle, FileAttribute desiredSubtitle, AttributeConfig config) {
FileInfoDto fileInfoDto = new FileInfoDto(null); FileInfo fileInfo = new FileInfo(null);
fileInfoDto.setExistingDefaultSubtitleLanes(defaultSubtitle); fileInfo.setExistingDefaultSubtitleLanes(defaultSubtitle);
fileInfoDto.setDesiredDefaultSubtitleLane(desiredSubtitle); fileInfo.setDesiredDefaultSubtitleLane(desiredSubtitle);
fileInfoDto.setMatchedConfig(config); fileInfo.setMatchedConfig(config);
return fileInfoDto; return fileInfo;
}
public static FileInfo createFileInfo(Set<FileAttribute> defaultAudio, FileAttribute desiredAudio,
Set<FileAttribute> defaultSubtitle, FileAttribute desiredSubtitle,
Set<FileAttribute> existingForcedAudioLanes,
Set<FileAttribute> existingForcedSubs, Set<FileAttribute> desiredForcedSubs,
AttributeConfig matchedConfig) {
FileInfo fileInfo = new FileInfo(null);
fileInfo.setExistingDefaultAudioLanes(defaultAudio);
fileInfo.setDesiredDefaultAudioLane(desiredAudio);
fileInfo.setExistingDefaultSubtitleLanes(defaultSubtitle);
fileInfo.setDesiredDefaultSubtitleLane(desiredSubtitle);
fileInfo.setExistingForcedAudioLanes(existingForcedAudioLanes);
fileInfo.setExistingForcedSubtitleLanes(existingForcedSubs);
fileInfo.setDesiredForcedSubtitleLanes(desiredForcedSubs);
fileInfo.setMatchedConfig(matchedConfig);
return fileInfo;
} }
public static String[] args(String... args) { public static String[] args(String... args) {