Implement OFF for audio tracks

This commit is contained in:
RatzzFatzz
2025-10-16 17:10:11 +02:00
parent 37c65df60c
commit b0f927dfa8
16 changed files with 257 additions and 168 deletions

View File

@@ -5,7 +5,6 @@ import picocli.CommandLine;
import java.util.regex.Pattern;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.LanguageValidatorUtil.isAudioLanguageValid;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.util.LanguageValidatorUtil.isLanguageValid;
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
*/
private static void validateResult(AttributeConfig attr) {
if (!isAudioLanguageValid(attr.getAudioLanguage()))
if (!isLanguageValid(attr.getAudioLanguage()))
throw new CommandLine.TypeConversionException("Audio language invalid: " + attr.getAudioLanguage());
if (!isLanguageValid(attr.getSubtitleLanguage()))
throw new CommandLine.TypeConversionException("Subtitle language invalid: " + attr.getSubtitleLanguage());

View File

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

View File

@@ -3,7 +3,7 @@ package at.pcgamingfreaks.mkvaudiosubtitlechanger.impl;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.exceptions.MkvToolNixException;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.AttributeConfig;
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.IOException;
@@ -25,7 +25,7 @@ public interface FileProcessor {
* @param attributes Track information of FileInfoDto
* @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.
@@ -33,7 +33,7 @@ public interface FileProcessor {
* @param nonForcedTracks List of all non-forced 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);
List<FileAttribute> retrieveNonForcedTracks(List<FileAttribute> attributes);
@@ -43,9 +43,9 @@ public interface FileProcessor {
/**
* Update the file.
* @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 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

@@ -81,15 +81,15 @@ public class MkvFileProcessor implements FileProcessor {
* {@inheritDoc}
*/
@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) {
if (AUDIO.equals(attribute.getType())) {
if (attribute.isDefaultTrack()) info.getExistingDefaultAudioLanes().add(attribute);
if (attribute.isForcedTrack()) info.getExistingForcedAudioLanes().add(attribute);
} else if (SUBTITLES.equals(attribute.getType())) {
if (attribute.isDefaultTrack()) info.getExistingDefaultSubtitleLanes().add(attribute);
if (AUDIO.equals(attribute.type())) {
if (attribute.defaultTrack()) info.getExistingDefaultAudioLanes().add(attribute);
if (attribute.forcedTrack()) info.getExistingForcedAudioLanes().add(attribute);
} else if (SUBTITLES.equals(attribute.type())) {
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);
}
}
@@ -99,19 +99,20 @@ public class MkvFileProcessor implements FileProcessor {
* {@inheritDoc}
*/
@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) {
Set<FileAttribute> tracks = SetUtils.retainOf(nonForcedTracks, nonCommentaryTracks);
Set<FileAttribute> audioTracks = tracks.stream().filter(a -> AUDIO.equals(a.getType())).collect(Collectors.toSet());
Set<FileAttribute> subtitleTracks = tracks.stream().filter(a -> SUBTITLES.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.type())).collect(Collectors.toSet());
for (AttributeConfig config : configs) {
Optional<FileAttribute> desiredAudio = detectDesiredTrack(config.getAudioLanguage(), audioTracks).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.setDesiredDefaultAudioLane(desiredAudio.get());
info.setDesiredDefaultAudioLane(desiredAudio.orElse(null));
info.setDesiredDefaultSubtitleLane(desiredSubtitle.orElse(null));
break;
}
@@ -119,7 +120,7 @@ public class MkvFileProcessor implements FileProcessor {
}
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) {
@@ -130,16 +131,16 @@ public class MkvFileProcessor implements FileProcessor {
@Override
public List<FileAttribute> retrieveNonForcedTracks(List<FileAttribute> attributes) {
return attributes.stream()
.filter(elem -> !StringUtils.containsAnyIgnoreCase(elem.getTrackName(),
.filter(elem -> !StringUtils.containsAnyIgnoreCase(elem.trackName(),
Config.getInstance().getForcedKeywords().toArray(new CharSequence[0])))
.filter(elem -> !elem.isForcedTrack())
.filter(elem -> !elem.forcedTrack())
.collect(Collectors.toList());
}
@Override
public List<FileAttribute> retrieveNonCommentaryTracks(List<FileAttribute> attributes) {
return attributes.stream()
.filter(elem -> !StringUtils.containsAnyIgnoreCase(elem.getTrackName(),
.filter(elem -> !StringUtils.containsAnyIgnoreCase(elem.trackName(),
Config.getInstance().getCommentaryKeywords().toArray(new CharSequence[0])))
.collect(Collectors.toList());
}
@@ -148,40 +149,28 @@ public class MkvFileProcessor implements FileProcessor {
* {@inheritDoc}
*/
@Override
public void update(File file, FileInfoDto fileInfo) throws IOException, MkvToolNixException {
public void update(File file, FileInfo fileInfo) throws IOException, MkvToolNixException {
List<String> command = new ArrayList<>();
command.add(Config.getInstance().getPathFor(MkvToolNix.MKV_PROP_EDIT));
command.add(String.format(file.getAbsolutePath()));
if (fileInfo.isAudioDifferent()) {
if (fileInfo.getExistingDefaultAudioLanes() != null && !fileInfo.getExistingDefaultAudioLanes().isEmpty()) {
for (FileAttribute track : fileInfo.getExistingDefaultAudioLanes()) {
command.addAll(format(DISABLE_DEFAULT_TRACK, track.getId()));
}
}
command.addAll(format(ENABLE_DEFAULT_TRACK, fileInfo.getDesiredDefaultAudioLane().getId()));
removeExistingAndAddDesiredLanes(fileInfo.getExistingDefaultAudioLanes(), fileInfo.getDesiredDefaultAudioLane(), command);
}
if (!fileInfo.getExistingForcedAudioLanes().isEmpty()) {
for (FileAttribute track : fileInfo.getExistingForcedAudioLanes()) {
command.addAll(format(DISABLE_FORCED_TRACK, track.getId()));
command.addAll(format(DISABLE_FORCED_TRACK, track.id()));
}
}
if (fileInfo.isSubtitleDifferent()) {
if (fileInfo.getExistingDefaultSubtitleLanes() != null && !fileInfo.getExistingDefaultSubtitleLanes().isEmpty()) {
for (FileAttribute track : fileInfo.getExistingDefaultSubtitleLanes()) {
command.addAll(format(DISABLE_DEFAULT_TRACK, track.getId()));
}
}
if (fileInfo.getDesiredDefaultSubtitleLane() != null) {
command.addAll(format(ENABLE_DEFAULT_TRACK, fileInfo.getDesiredDefaultSubtitleLane().getId()));
}
removeExistingAndAddDesiredLanes(fileInfo.getExistingDefaultSubtitleLanes(), fileInfo.getDesiredDefaultSubtitleLane(), command);
}
if (fileInfo.areForcedTracksDifferent()) {
for (FileAttribute track : fileInfo.getDesiredForcedSubtitleLanes()) {
command.addAll(format(ENABLE_FORCED_TRACK, track.getId()));
command.addAll(format(ENABLE_FORCED_TRACK, track.id()));
}
}
@@ -192,6 +181,17 @@ public class MkvFileProcessor implements FileProcessor {
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) {
int result = 0;
if (StringUtils.containsAnyIgnoreCase(track1.getTrackName(), preferredSubtitles)) {
if (StringUtils.containsAnyIgnoreCase(track1.trackName(), preferredSubtitles)) {
result++;
}
if (StringUtils.containsAnyIgnoreCase(track2.getTrackName(), preferredSubtitles)) {
if (StringUtils.containsAnyIgnoreCase(track2.trackName(), preferredSubtitles)) {
result--;
}
if (result == 0) {
if (track1.isDefaultTrack()) result++;
if (track2.isDefaultTrack()) result--;
if (track1.defaultTrack()) result++;
if (track2.defaultTrack()) 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.model.AttributeConfig;
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.util.DateUtils;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.util.ProjectUtil;
@@ -96,7 +96,7 @@ public abstract class AttributeUpdaterKernel {
* @param file file or directory to update
*/
void process(File file) {
FileInfoDto fileInfo = new FileInfoDto(file);
FileInfo fileInfo = new FileInfo(file);
List<FileAttribute> attributes = processor.loadAttributes(file);
if (attributes == null || attributes.isEmpty()) {
@@ -119,14 +119,14 @@ public abstract class AttributeUpdaterKernel {
/**
* 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();
switch (fileInfoDto.getStatus()) {
switch (fileInfo.getStatus()) {
case CHANGE_NECESSARY:
statistic.shouldChange();
commitChange(fileInfoDto);
commitChange(fileInfo);
break;
case NO_SUITABLE_CONFIG:
statistic.noSuitableConfigFound();
@@ -141,7 +141,7 @@ public abstract class AttributeUpdaterKernel {
}
}
private void commitChange(FileInfoDto fileInfo) {
private void commitChange(FileInfo fileInfo) {
if (Config.getInstance().isSafeMode()) {
return;
}

View File

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

View File

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

View File

@@ -7,11 +7,12 @@ 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 FileInfoDto {
public class FileInfo {
private final File file;
private Set<FileAttribute> existingDefaultAudioLanes = new HashSet<>();
@@ -26,27 +27,28 @@ public class FileInfoDto {
private AttributeConfig matchedConfig;
public boolean isAudioDifferent() {
return desiredDefaultAudioLane != null &&
(existingDefaultAudioLanes == null || !existingDefaultAudioLanes.contains(desiredDefaultAudioLane) || existingDefaultAudioLanes.size() > 1);
return isMatchDifferent(existingDefaultAudioLanes, desiredDefaultAudioLane)
|| isLaneOff(existingDefaultAudioLanes, desiredDefaultAudioLane, AttributeConfig::getAudioLanguage);
}
public boolean isSubtitleDifferent() {
return isSubtitleMatchDifferent() || isSubtitleOFF();
return isMatchDifferent(existingDefaultSubtitleLanes, desiredDefaultSubtitleLane)
|| isLaneOff(existingDefaultSubtitleLanes, desiredDefaultSubtitleLane, AttributeConfig::getSubtitleLanguage);
}
private boolean isSubtitleMatchDifferent() {
return desiredDefaultSubtitleLane != null
&& (existingDefaultSubtitleLanes == null || !existingDefaultSubtitleLanes.contains(desiredDefaultSubtitleLane) || existingDefaultSubtitleLanes.size() > 1);
private boolean isMatchDifferent(Set<FileAttribute> existingDefault, FileAttribute desiredDefault) {
return desiredDefault != null &&
(existingDefault == null || !existingDefault.contains(desiredDefault) || existingDefault.size() > 1);
}
private boolean isSubtitleOFF() {
return desiredDefaultSubtitleLane == null
&& (matchedConfig != null && "OFF".equals(matchedConfig.getSubtitleLanguage()))
&& (existingDefaultSubtitleLanes != null && !existingDefaultSubtitleLanes.isEmpty());
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();
return !desiredForcedSubtitleLanes.isEmpty() && !existingForcedSubtitleLanes.containsAll(desiredForcedSubtitleLanes);
}
public FileStatus getStatus() {
@@ -57,11 +59,12 @@ public class FileInfoDto {
}
private boolean isUnableToApplyConfig() {
return desiredDefaultAudioLane == null && desiredDefaultSubtitleLane == null;
return desiredDefaultAudioLane == null && !"OFF".equals(matchedConfig.getAudioLanguage())
&& desiredDefaultSubtitleLane == null && !"OFF".equals(matchedConfig.getSubtitleLanguage());
}
private boolean isAlreadySuited() {
return existingDefaultAudioLanes.contains(desiredDefaultAudioLane)
return (desiredDefaultAudioLane == null || existingDefaultAudioLanes.contains(desiredDefaultAudioLane))
&& (desiredDefaultSubtitleLane == null || existingDefaultSubtitleLanes.contains(desiredDefaultSubtitleLane));
}

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) {
return ISO3_LANGUAGES.contains(language);
}

View File

@@ -22,7 +22,7 @@ class ConfigTest {
"--commentary-keywords", "testCommentary",
"--preferred-subtitles", "testPreferred"
};
CommandLine.populateCommand(Config.getInstance(), sut);
CommandLine.populateCommand(Config.getInstance(true), sut);
assertTrue(Config.getInstance().getLibraryPath().exists());
assertEquals(List.of(new AttributeConfig("ger", "ger"), new AttributeConfig("eng", "eng")),
@@ -41,6 +41,5 @@ class ConfigTest {
assertTrue(Config.getInstance().getPreferredSubtitles().contains("testPreferred"));
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.ConfigProperty;
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 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,
ValidationResult result) {
ValidationResult result) {
return Arguments.of(property, required, defaultValue, yaml, cmd, result);
}
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);
}
public static FileInfoDto createFileInfo(Set<FileAttribute> defaultAudio, FileAttribute desiredAudio) {
FileInfoDto fileInfoDto = new FileInfoDto(null);
fileInfoDto.setExistingDefaultAudioLanes(defaultAudio);
fileInfoDto.setDesiredDefaultAudioLane(desiredAudio);
return fileInfoDto;
public static FileInfo createFileInfoAudio(Set<FileAttribute> defaultAudio, FileAttribute desiredAudio, AttributeConfig config) {
FileInfo fileInfo = new FileInfo(null);
fileInfo.setExistingDefaultAudioLanes(defaultAudio);
fileInfo.setDesiredDefaultAudioLane(desiredAudio);
fileInfo.setMatchedConfig(config);
return fileInfo;
}
public static FileInfoDto createFileInfo(Set<FileAttribute> defaultSubtitle, FileAttribute desiredSubtitle, AttributeConfig config) {
FileInfoDto fileInfoDto = new FileInfoDto(null);
fileInfoDto.setExistingDefaultSubtitleLanes(defaultSubtitle);
fileInfoDto.setDesiredDefaultSubtitleLane(desiredSubtitle);
fileInfoDto.setMatchedConfig(config);
return fileInfoDto;
public static FileInfo createFileInfoSubs(Set<FileAttribute> defaultSubtitle, FileAttribute desiredSubtitle, AttributeConfig config) {
FileInfo fileInfo = new FileInfo(null);
fileInfo.setExistingDefaultSubtitleLanes(defaultSubtitle);
fileInfo.setDesiredDefaultSubtitleLane(desiredSubtitle);
fileInfo.setMatchedConfig(config);
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) {