Prepare for coherent feature by restructuring AttributeUpdaterKernel

This commit is contained in:
2023-02-26 18:55:17 +01:00
parent 143206b08c
commit 73be93a4b6
18 changed files with 340 additions and 166 deletions

16
pom.xml
View File

@@ -136,22 +136,6 @@
<artifactId>log4j-slf4j-impl</artifactId> <artifactId>log4j-slf4j-impl</artifactId>
<version>2.17.1</version> <version>2.17.1</version>
</dependency> </dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.28</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.28</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.28</version>
</dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId> <groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId> <artifactId>jackson-dataformat-yaml</artifactId>

View File

@@ -1,92 +0,0 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.Config;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.FileCollector;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.FileProcessor;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileAttribute;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileInfoDto;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.ResultStatistic;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import me.tongfei.progressbar.ProgressBar;
import me.tongfei.progressbar.ProgressBarBuilder;
import me.tongfei.progressbar.ProgressBarStyle;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Log4j2
public class AttributeUpdaterKernel {
private final ExecutorService executor = Executors.newFixedThreadPool(Config.getInstance().getThreads());
private final FileCollector collector;
private final FileProcessor processor;
private final ResultStatistic statistic = new ResultStatistic();
public AttributeUpdaterKernel(FileCollector collector, FileProcessor processor) {
this.collector = collector;
this.processor = processor;
}
@SneakyThrows
public void execute() {
statistic.startTimer();
try (ProgressBar progressBar = pbBuilder().build()) {
List<File> excludedFiles = Config.getInstance().getExcludedDirectories().stream()
.map(collector::loadFiles)
.flatMap(Collection::stream)
.collect(Collectors.toList());
List<File> files = collector.loadFiles(Config.getInstance().getLibraryPath().getAbsolutePath()).stream()
.filter(file -> !excludedFiles.contains(file))
.collect(Collectors.toList());
progressBar.maxHint(files.size());
files.forEach(file -> executor.submit(() -> process(file, progressBar)));
executor.shutdown();
executor.awaitTermination(1, TimeUnit.DAYS);
}
statistic.stopTimer();
System.out.println(statistic);
log.info(statistic);
}
private void process(File file, ProgressBar progressBar) {
List<FileAttribute> attributes = processor.loadAttributes(file);
FileInfoDto fileInfo = processor.filterAttributes(attributes);
statistic.total();
if (fileInfo.isChangeNecessary()) {
statistic.shouldChange();
if (!Config.getInstance().isSafeMode()) {
try {
processor.update(file, fileInfo);
statistic.success();
log.info("Updated {}", file.getAbsolutePath());
} catch (IOException | RuntimeException e) {
statistic.failedChanging();
log.warn("File couldn't be updated: '{}', Error: {}", file.getAbsoluteFile(), e.getMessage().replaceAll("\\r|\\n", " "));
}
}
} else if (fileInfo.isUnableToApplyConfig()) {
statistic.noSuitableConfigFound();
} else if (fileInfo.isAlreadySuitable()){
statistic.alreadyFits();
} else {
statistic.failure();
}
progressBar.step();
}
private static ProgressBarBuilder pbBuilder() {
return new ProgressBarBuilder()
.setStyle(ProgressBarStyle.ASCII)
.setUpdateIntervalMillis(250)
.setMaxRenderedLength(75);
}
}

View File

@@ -1,16 +1,17 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger; package at.pcgamingfreaks.mkvaudiosubtitlechanger;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.Config;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.ConfigLoader; import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.ConfigLoader;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.kernel.AttributeUpdaterKernel;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.kernel.DefaultAttributeUpdaterKernel;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.MkvFileCollector; import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.MkvFileCollector;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.MkvFileProcessor; import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.MkvFileProcessor;
import lombok.extern.log4j.Log4j2; import lombok.extern.slf4j.Slf4j;
@Log4j2 @Slf4j
public class Main { public class Main {
public static void main(String[] args) { public static void main(String[] args) {
ConfigLoader.initConfig(args); ConfigLoader.initConfig(args);
AttributeUpdaterKernel kernel = new AttributeUpdaterKernel(new MkvFileCollector(), new MkvFileProcessor()); AttributeUpdaterKernel kernel = new DefaultAttributeUpdaterKernel(new MkvFileCollector(), new MkvFileProcessor());
kernel.execute(); kernel.execute();
} }
} }

View File

@@ -6,7 +6,7 @@ import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.extern.log4j.Log4j2; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.HelpFormatter;
@@ -15,7 +15,7 @@ import java.io.File;
import java.util.*; import java.util.*;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@Log4j2 @Slf4j
@Getter @Getter
@Setter @Setter
@NoArgsConstructor(access = AccessLevel.PRIVATE) @NoArgsConstructor(access = AccessLevel.PRIVATE)

View File

@@ -27,7 +27,7 @@ public class ConfigLoader {
new PatternValidator(INCLUDE_PATTERN, false, Pattern.compile(".*")), new PatternValidator(INCLUDE_PATTERN, false, Pattern.compile(".*")),
new SetValidator(FORCED_KEYWORDS, false, true), new SetValidator(FORCED_KEYWORDS, false, true),
new SetValidator(COMMENTARY_KEYWORDS, false, true), new SetValidator(COMMENTARY_KEYWORDS, false, true),
new SetValidator(EXCLUDE_DIRECTORY, false, true), new SetValidator(EXCLUDED_DIRECTORY, false, true),
new AttributeConfigValidator() new AttributeConfigValidator()
); );
@@ -55,7 +55,7 @@ public class ConfigLoader {
} }
} }
if (results.contains(ValidationResult.INVALID)) System.exit(1); if (results.contains(ValidationResult.INVALID) || results.contains(ValidationResult.MISSING)) System.exit(1);
System.out.println(); System.out.println();
} }

View File

@@ -0,0 +1,13 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.exceptions;
public class MkvToolNixException extends RuntimeException{
public MkvToolNixException(String message) {
super(message);
}
@Override
public String getMessage() {
return super.getMessage().replaceAll("\\r|\\n", " ");
}
}

View File

@@ -1,5 +1,6 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.impl; package at.pcgamingfreaks.mkvaudiosubtitlechanger.impl;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.exceptions.MkvToolNixException;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileAttribute; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileAttribute;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileInfoDto; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileInfoDto;
@@ -10,12 +11,35 @@ import java.util.List;
public interface FileProcessor { public interface FileProcessor {
/** /**
* Load track information from file.
*
* @param file Takes the file from which the attributes will be returned * @param file Takes the file from which the attributes will be returned
* @return list of all important attributes * @return list of all important attributes
*/ */
List<FileAttribute> loadAttributes(File file); List<FileAttribute> loadAttributes(File file);
FileInfoDto filterAttributes(List<FileAttribute> attributes); /**
* Populate FileInfoDto with the currently set default tracks.
* @param info to be populated
* @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 update(File file, FileInfoDto fileInfo) throws IOException; /**
* Populate FileInfoDto with the desired tracks, based on AttributeConfig.
* @param info to be populated
* @param nonForcedTracks List of all not forced tracks
* @param nonCommentaryTracks List of all not commentary tracks
*/
void detectDesiredTracks(FileInfoDto info, List<FileAttribute> nonForcedTracks, List<FileAttribute> nonCommentaryTracks);
/**
* Update the file.
* @param file to be updated
* @param fileInfo information to update file
* @throws IOException
* @throws MkvToolNixException when error occurs while sending query to mkvpropedit
*/
void update(File file, FileInfoDto fileInfo) throws IOException, MkvToolNixException;
} }

View File

@@ -1,6 +1,6 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.impl; package at.pcgamingfreaks.mkvaudiosubtitlechanger.impl;
import lombok.extern.log4j.Log4j2; import lombok.extern.slf4j.Slf4j;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -12,7 +12,7 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@Log4j2 @Slf4j
public class MkvFileCollector implements FileCollector { public class MkvFileCollector implements FileCollector {
private static final String[] fileExtensions = new String[]{".mkv", ".mka", ".mks", ".mk3d"}; private static final String[] fileExtensions = new String[]{".mkv", ".mka", ".mks", ".mk3d"};

View File

@@ -1,11 +1,11 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.impl; package at.pcgamingfreaks.mkvaudiosubtitlechanger.impl;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.Config; import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.Config;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.exceptions.MkvToolNixException;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.*; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.*;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.util.SetUtils; import at.pcgamingfreaks.mkvaudiosubtitlechanger.util.SetUtils;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.log4j.Log4j2; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.core.util.IOUtils; import org.apache.logging.log4j.core.util.IOUtils;
import java.io.File; import java.io.File;
@@ -19,14 +19,13 @@ import static at.pcgamingfreaks.mkvaudiosubtitlechanger.model.LaneType.AUDIO;
import static at.pcgamingfreaks.mkvaudiosubtitlechanger.model.LaneType.SUBTITLES; import static at.pcgamingfreaks.mkvaudiosubtitlechanger.model.LaneType.SUBTITLES;
import static java.lang.String.format; import static java.lang.String.format;
@Log4j2 @Slf4j
public class MkvFileProcessor implements FileProcessor { public class MkvFileProcessor implements FileProcessor {
private final ObjectMapper mapper = new ObjectMapper(); private final ObjectMapper mapper = new ObjectMapper();
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 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
public List<FileAttribute> loadAttributes(File file) { public List<FileAttribute> loadAttributes(File file) {
@@ -62,7 +61,7 @@ public class MkvFileProcessor implements FileProcessor {
} }
} }
log.debug(fileAttributes); log.debug(fileAttributes.toString());
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
log.error("File could not be found or loaded!"); log.error("File could not be found or loaded!");
@@ -70,27 +69,11 @@ public class MkvFileProcessor implements FileProcessor {
return fileAttributes; return fileAttributes;
} }
/**
* {@inheritDoc}
*/
@Override @Override
public FileInfoDto filterAttributes(List<FileAttribute> attributes) { public void detectDefaultTracks(FileInfoDto info, List<FileAttribute> attributes, List<FileAttribute> nonForcedTracks) {
FileInfoDto info = new FileInfoDto();
List<FileAttribute> nonForcedTracks = attributes.stream()
.filter(elem -> !StringUtils.containsAnyIgnoreCase(elem.getTrackName(),
Config.getInstance().getForcedKeywords().toArray(new CharSequence[0])))
.filter(elem -> !elem.isForcedTrack())
.collect(Collectors.toList());
List<FileAttribute> nonCommentaryTracks = attributes.stream()
.filter(elem -> !StringUtils.containsAnyIgnoreCase(elem.getTrackName(),
Config.getInstance().getCommentaryKeywords().toArray(new CharSequence[0])))
.collect(Collectors.toList());
detectDefaultTracks(info, attributes, nonForcedTracks);
detectDesiredTracks(info, nonForcedTracks, nonCommentaryTracks);
log.debug(info);
return info;
}
protected void detectDefaultTracks(FileInfoDto info, List<FileAttribute> attributes, List<FileAttribute> nonForcedTracks) {
Set<FileAttribute> detectedForcedSubtitleLanes = new HashSet<>(); Set<FileAttribute> detectedForcedSubtitleLanes = new HashSet<>();
for (FileAttribute attribute : attributes) { for (FileAttribute attribute : attributes) {
if (attribute.isDefaultTrack() && AUDIO.equals(attribute.getType())) if (attribute.isDefaultTrack() && AUDIO.equals(attribute.getType()))
@@ -108,7 +91,11 @@ public class MkvFileProcessor implements FileProcessor {
); );
} }
protected void detectDesiredTracks(FileInfoDto info, List<FileAttribute> nonForcedTracks, List<FileAttribute> nonCommentaryTracks) { /**
* {@inheritDoc}
*/
@Override
public void detectDesiredTracks(FileInfoDto info, List<FileAttribute> nonForcedTracks, List<FileAttribute> nonCommentaryTracks) {
for (AttributeConfig config : Config.getInstance().getAttributeConfig()) { for (AttributeConfig config : Config.getInstance().getAttributeConfig()) {
FileAttribute desiredAudio = null; FileAttribute desiredAudio = null;
FileAttribute desiredSubtitle = null; FileAttribute desiredSubtitle = null;
@@ -126,11 +113,15 @@ public class MkvFileProcessor implements FileProcessor {
} }
} }
/**
* {@inheritDoc}
*/
@Override @Override
public void update(File file, FileInfoDto fileInfo) throws IOException, RuntimeException { public void update(File file, FileInfoDto fileInfo) throws IOException, MkvToolNixException {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(format("\"%s\" ", Config.getInstance().getPathFor(MkvToolNix.MKV_PROP_EDIT))); sb.append(format("\"%s\" ", Config.getInstance().getPathFor(MkvToolNix.MKV_PROP_EDIT)));
sb.append(format("\"%s\" ", file.getAbsolutePath())); sb.append(format("\"%s\" ", file.getAbsolutePath()));
if (fileInfo.isAudioDifferent()) { if (fileInfo.isAudioDifferent()) {
if (fileInfo.getDefaultAudioLanes() != null && !fileInfo.getDefaultSubtitleLanes().isEmpty()) { if (fileInfo.getDefaultAudioLanes() != null && !fileInfo.getDefaultSubtitleLanes().isEmpty()) {
for (FileAttribute track: fileInfo.getDefaultAudioLanes()) { for (FileAttribute track: fileInfo.getDefaultAudioLanes()) {
@@ -139,6 +130,7 @@ public class MkvFileProcessor implements FileProcessor {
} }
sb.append(format(ENABLE_DEFAULT_TRACK, fileInfo.getDesiredAudioLane().getId())); sb.append(format(ENABLE_DEFAULT_TRACK, fileInfo.getDesiredAudioLane().getId()));
} }
if (fileInfo.isSubtitleDifferent()) { if (fileInfo.isSubtitleDifferent()) {
if (fileInfo.getDefaultSubtitleLanes() != null && !fileInfo.getDefaultSubtitleLanes().isEmpty()) { if (fileInfo.getDefaultSubtitleLanes() != null && !fileInfo.getDefaultSubtitleLanes().isEmpty()) {
for (FileAttribute track: fileInfo.getDefaultSubtitleLanes()) { for (FileAttribute track: fileInfo.getDefaultSubtitleLanes()) {
@@ -147,6 +139,7 @@ public class MkvFileProcessor implements FileProcessor {
} }
sb.append(format(ENABLE_DEFAULT_TRACK, fileInfo.getDesiredSubtitleLane().getId())); sb.append(format(ENABLE_DEFAULT_TRACK, fileInfo.getDesiredSubtitleLane().getId()));
} }
if (fileInfo.areForcedTracksDifferent()) { if (fileInfo.areForcedTracksDifferent()) {
for (FileAttribute attribute : fileInfo.getDesiredForcedSubtitleLanes()) { for (FileAttribute attribute : fileInfo.getDesiredForcedSubtitleLanes()) {
sb.append(format(ENABLE_FORCED_TRACK, attribute.getId())); sb.append(format(ENABLE_FORCED_TRACK, attribute.getId()));
@@ -156,6 +149,6 @@ public class MkvFileProcessor implements FileProcessor {
InputStream inputstream = Runtime.getRuntime().exec(sb.toString()).getInputStream(); InputStream inputstream = Runtime.getRuntime().exec(sb.toString()).getInputStream();
String output = IOUtils.toString(new InputStreamReader(inputstream)); String output = IOUtils.toString(new InputStreamReader(inputstream));
log.debug(output); log.debug(output);
if (output.contains("Error")) throw new RuntimeException(output); if (output.contains("Error")) throw new MkvToolNixException(output);
} }
} }

View File

@@ -0,0 +1,116 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.kernel;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.Config;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.exceptions.MkvToolNixException;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.FileCollector;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.FileProcessor;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileInfoDto;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.ResultStatistic;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import me.tongfei.progressbar.ProgressBar;
import me.tongfei.progressbar.ProgressBarBuilder;
import me.tongfei.progressbar.ProgressBarStyle;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@Slf4j
@RequiredArgsConstructor
public abstract class AttributeUpdaterKernel {
protected final FileCollector collector;
protected final FileProcessor processor;
protected final ResultStatistic statistic = new ResultStatistic();
private final ExecutorService executor = Executors.newFixedThreadPool(Config.getInstance().getThreads());
private static ProgressBarBuilder pbBuilder() {
return new ProgressBarBuilder()
.setStyle(ProgressBarStyle.ASCII)
.setUpdateIntervalMillis(250)
.setMaxRenderedLength(75);
}
@SneakyThrows
public void execute() {
statistic.startTimer();
try (ProgressBar progressBar = pbBuilder().build()) {
List<File> files = loadFiles(Config.getInstance().getLibraryPath().getAbsolutePath());
progressBar.maxHint(files.size());
files.forEach(file -> executor.submit(() -> {
process(file);
progressBar.step();
}));
executor.shutdown();
executor.awaitTermination(1, TimeUnit.DAYS);
}
statistic.stopTimer();
statistic.printResult();
}
/**
* Load files or directories to update.
* Remove excluded directories.
*
* @param path Path to library
* @return List of files to update.
*/
abstract List<File> loadFiles(String path);
/**
* Start of the file updating process.
* This method is called by the executor and its contents are executed in parallel.
*
* @param file file or directory to update
*/
abstract void process(File file);
/**
* Persist file changes.
*
* @param fileInfoDto contains information about file and desired configuration.
*/
protected void updateFile(FileInfoDto fileInfoDto) {
statistic.total();
switch (fileInfoDto.getStatus()) {
case CHANGE_NECESSARY:
statistic.shouldChange();
commitChange(fileInfoDto);
break;
case UNABLE_TO_APPLY:
statistic.noSuitableConfigFound();
break;
case ALREADY_SUITED:
statistic.alreadyFits();
break;
case UNKNOWN:
default:
statistic.failure();
break;
}
}
private void commitChange(FileInfoDto fileInfo) {
if (Config.getInstance().isSafeMode()) {
return;
}
try {
processor.update(fileInfo.getFile(), fileInfo);
statistic.success();
log.info("Updated {}", fileInfo.getFile().getAbsolutePath());
} catch (IOException | MkvToolNixException e) {
statistic.failedChanging();
log.warn("File couldn't be updated: '{}', Error: {}", fileInfo.getFile().getAbsoluteFile(), e.getMessage());
}
}
}

View File

@@ -0,0 +1,32 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.kernel;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.FileCollector;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.FileProcessor;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.util.List;
@Slf4j
public class CoherentAttributeUpdaterKernel extends AttributeUpdaterKernel{
public CoherentAttributeUpdaterKernel(FileCollector collector, FileProcessor processor) {
super(collector, processor);
}
/**
* {@inheritDoc}
*/
@Override
List<File> loadFiles(String path) {
return null;
}
/**
* {@inheritDoc}
*/
@Override
void process(File file) {
}
}

View File

@@ -0,0 +1,63 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.kernel;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.Config;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.FileCollector;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.FileProcessor;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileAttribute;
import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileInfoDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
public class DefaultAttributeUpdaterKernel extends AttributeUpdaterKernel {
public DefaultAttributeUpdaterKernel(FileCollector collector, FileProcessor processor) {
super(collector, processor);
}
/**
* {@inheritDoc}
*/
@Override
List<File> loadFiles(String path) {
List<File> excludedFiles = Config.getInstance().getExcludedDirectories().stream()
.map(collector::loadFiles)
.flatMap(Collection::stream)
.collect(Collectors.toList());
statistic.increaseTotalBy(excludedFiles.size());
statistic.increaseExcludedBy(excludedFiles.size());
return collector.loadFiles(Config.getInstance().getLibraryPath().getAbsolutePath()).stream()
.filter(file -> !excludedFiles.contains(file))
.collect(Collectors.toList());
}
/**
* {@inheritDoc}
*/
@Override
void process(File file) {
FileInfoDto fileInfo = new FileInfoDto(file);
List<FileAttribute> attributes = processor.loadAttributes(file);
// TODO: extract this to a attributeProcessor?
List<FileAttribute> nonForcedTracks = attributes.stream()
.filter(elem -> !StringUtils.containsAnyIgnoreCase(elem.getTrackName(),
Config.getInstance().getForcedKeywords().toArray(new CharSequence[0])))
.filter(elem -> !elem.isForcedTrack())
.collect(Collectors.toList());
List<FileAttribute> nonCommentaryTracks = attributes.stream()
.filter(elem -> !StringUtils.containsAnyIgnoreCase(elem.getTrackName(),
Config.getInstance().getCommentaryKeywords().toArray(new CharSequence[0])))
.collect(Collectors.toList());
processor.detectDefaultTracks(fileInfo, attributes, nonForcedTracks);
processor.detectDesiredTracks(fileInfo, nonForcedTracks, nonCommentaryTracks);
updateFile(fileInfo);
}
}

View File

@@ -2,11 +2,11 @@ package at.pcgamingfreaks.mkvaudiosubtitlechanger.model;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.extern.log4j.Log4j2; import lombok.extern.slf4j.Slf4j;
import java.util.Objects; import java.util.Objects;
@Log4j2 @Slf4j
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public class AttributeConfig { public class AttributeConfig {

View File

@@ -19,7 +19,7 @@ public enum ConfigProperty {
WINDOWS("windows", "Is operating system windows", null, 0), WINDOWS("windows", "Is operating system windows", null, 0),
THREADS("threads", "Thread count (default: 2)", "t", 1), THREADS("threads", "Thread count (default: 2)", "t", 1),
INCLUDE_PATTERN("include-pattern", "Include files matching pattern (default: \".*\")", "i", 1), INCLUDE_PATTERN("include-pattern", "Include files matching pattern (default: \".*\")", "i", 1),
EXCLUDE_DIRECTORY("exclude-directories", "Directories to be excluded, combines with config file", "e", 1), EXCLUDED_DIRECTORY("excluded-directories", "Directories to be excluded, combines with config file", "e", Option.UNLIMITED_VALUES),
FORCED_KEYWORDS("forced-keywords", "Additional keywords to identify forced tracks", "fk", Option.UNLIMITED_VALUES), FORCED_KEYWORDS("forced-keywords", "Additional keywords to identify forced tracks", "fk", Option.UNLIMITED_VALUES),
COMMENTARY_KEYWORDS("commentary-keywords", "Additional keywords to identify commentary tracks", "ck", Option.UNLIMITED_VALUES), COMMENTARY_KEYWORDS("commentary-keywords", "Additional keywords to identify commentary tracks", "ck", Option.UNLIMITED_VALUES),
ARGUMENTS("arguments", "List of arguments", null, 0), ARGUMENTS("arguments", "List of arguments", null, 0),

View File

@@ -2,9 +2,9 @@ package at.pcgamingfreaks.mkvaudiosubtitlechanger.model;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.extern.log4j.Log4j2; import lombok.extern.slf4j.Slf4j;
@Log4j2 @Slf4j
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public class FileAttribute { public class FileAttribute {

View File

@@ -1,32 +1,24 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.model; package at.pcgamingfreaks.mkvaudiosubtitlechanger.model;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter; import lombok.Setter;
import java.io.File;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@Getter @Getter
@Setter @Setter
@RequiredArgsConstructor
public class FileInfoDto { public class FileInfoDto {
private final File file;
private Set<FileAttribute> defaultAudioLanes = new HashSet<>(); private Set<FileAttribute> defaultAudioLanes = new HashSet<>();
private Set<FileAttribute> defaultSubtitleLanes = new HashSet<>(); private Set<FileAttribute> defaultSubtitleLanes = new HashSet<>();
private Set<FileAttribute> desiredForcedSubtitleLanes; private Set<FileAttribute> desiredForcedSubtitleLanes;
private FileAttribute desiredAudioLane; private FileAttribute desiredAudioLane;
private FileAttribute desiredSubtitleLane; private FileAttribute desiredSubtitleLane;
public boolean isUnableToApplyConfig() {
return desiredAudioLane == null && desiredSubtitleLane == null;
}
public boolean isAlreadySuitable() {
return defaultAudioLanes.contains(desiredAudioLane) && defaultSubtitleLanes.contains(desiredSubtitleLane);
}
public boolean isChangeNecessary() {
return isAudioDifferent() || isSubtitleDifferent() || areForcedTracksDifferent();
}
public boolean isAudioDifferent() { public boolean isAudioDifferent() {
return desiredAudioLane != null && return desiredAudioLane != null &&
(defaultAudioLanes == null || !defaultAudioLanes.contains(desiredAudioLane)); (defaultAudioLanes == null || !defaultAudioLanes.contains(desiredAudioLane));
@@ -41,6 +33,25 @@ public class FileInfoDto {
return desiredForcedSubtitleLanes.size() > 0; return desiredForcedSubtitleLanes.size() > 0;
} }
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 desiredAudioLane == null && desiredSubtitleLane == null;
}
private boolean isAlreadySuitable() {
return defaultAudioLanes.contains(desiredAudioLane) && defaultSubtitleLanes.contains(desiredSubtitleLane);
}
private boolean isChangeNecessary() {
return isAudioDifferent() || isSubtitleDifferent() || areForcedTracksDifferent();
}
@Override @Override
public String toString() { public String toString() {
return "[" + "defaultAudioLanes=" + defaultAudioLanes + return "[" + "defaultAudioLanes=" + defaultAudioLanes +

View File

@@ -0,0 +1,8 @@
package at.pcgamingfreaks.mkvaudiosubtitlechanger.model;
public enum FileStatus {
CHANGE_NECESSARY,
UNABLE_TO_APPLY,
ALREADY_SUITED,
UNKNOWN;
}

View File

@@ -2,10 +2,13 @@ package at.pcgamingfreaks.mkvaudiosubtitlechanger.model;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@Getter @Getter
@Slf4j
public class ResultStatistic { public class ResultStatistic {
private static final String result = "Total files: %s%n" + private static final String result = "Total files: %s%n" +
"├─ Excluded: %s%n" +
"├─ Should change: %s%n" + "├─ Should change: %s%n" +
"│ ├─ Failed changing: %s%n" + "│ ├─ Failed changing: %s%n" +
"│ └─ Successfully changed: %s%n" + "│ └─ Successfully changed: %s%n" +
@@ -15,6 +18,7 @@ public class ResultStatistic {
"Runtime: %s"; "Runtime: %s";
private int filesTotal = 0; private int filesTotal = 0;
private int excluded = 0;
private int shouldChange = 0; private int shouldChange = 0;
private int failedChanging = 0; private int failedChanging = 0;
@@ -28,10 +32,22 @@ public class ResultStatistic {
private long startTime = 0; private long startTime = 0;
private long runtime = 0; private long runtime = 0;
public void increaseTotalBy(int amount) {
filesTotal += amount;
}
public synchronized void total() { public synchronized void total() {
filesTotal++; filesTotal++;
} }
public void increaseExcludedBy(int amount) {
excluded += amount;
}
public synchronized void excluded() {
excluded++;
}
public synchronized void shouldChange() { public synchronized void shouldChange() {
shouldChange++; shouldChange++;
} }
@@ -64,6 +80,11 @@ public class ResultStatistic {
runtime = System.currentTimeMillis() - startTime; runtime = System.currentTimeMillis() - startTime;
} }
public void printResult() {
System.out.println(this);
log.info(this.toString());
}
private String formatTimer() { private String formatTimer() {
int seconds = (int) (runtime / 1000); int seconds = (int) (runtime / 1000);
int minutes = seconds / 60; int minutes = seconds / 60;
@@ -83,7 +104,7 @@ public class ResultStatistic {
@Override @Override
public String toString() { public String toString() {
return String.format(result, filesTotal, shouldChange, failedChanging, successfullyChanged, return String.format(result, filesTotal, excluded, shouldChange, failedChanging, successfullyChanged,
noSuitableConfigFound, alreadyFits, failed, formatTimer()); noSuitableConfigFound, alreadyFits, failed, formatTimer());
} }
} }