From 93f3542cf1e4f5f4b4fac4aa0cf2cf5af2574141 Mon Sep 17 00:00:00 2001 From: RatzzFatzz Date: Wed, 30 Mar 2022 19:00:24 +0200 Subject: [PATCH] Add new file update process --- .../AttributeUpdaterKernel.java | 20 -- .../impl/ConfigProcessorOld.java | 203 ------------------ .../impl/MkvFileProcessor.java | 80 +++++-- .../model/FileAttribute.java | 48 +---- .../model/FileInfoDto.java | 22 +- 5 files changed, 87 insertions(+), 286 deletions(-) delete mode 100644 src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/impl/ConfigProcessorOld.java diff --git a/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/AttributeUpdaterKernel.java b/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/AttributeUpdaterKernel.java index 42883d9..f82553c 100644 --- a/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/AttributeUpdaterKernel.java +++ b/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/AttributeUpdaterKernel.java @@ -2,8 +2,6 @@ package at.pcgamingfreaks.mkvaudiosubtitlechanger; import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.FileCollector; import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.FileProcessor; -import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.AttributeConfig; -import at.pcgamingfreaks.mkvaudiosubtitlechanger.impl.ConfigProcessorOld; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileAttribute; import at.pcgamingfreaks.mkvaudiosubtitlechanger.config.Config; import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.FileInfoDto; @@ -53,24 +51,6 @@ public class AttributeUpdaterKernel { System.out.printf("Runtime: %ss%n", runtime / 1000); } - private void processOld(File file) { - List attributes = processor.loadAttributes(file); - boolean fileHasChanged = false; - - if (attributes.isEmpty()) return; - for(AttributeConfig config : Config.getInstance().getAttributeConfig()){ - fileHasChanged = new ConfigProcessorOld(config).processConfig(file, attributes); - if(fileHasChanged) break; - } - if(!fileHasChanged){ - log.info("File didn't change: {}", file.getName()); - filesNotChangedAmount++; - } else { - filesChangedAmount++; - } - System.out.print("."); - } - private void process(File file) { List attributes = processor.loadAttributes(file); FileInfoDto fileInfo = processor.filterAttributes(attributes); diff --git a/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/impl/ConfigProcessorOld.java b/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/impl/ConfigProcessorOld.java deleted file mode 100644 index 44c2dab..0000000 --- a/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/impl/ConfigProcessorOld.java +++ /dev/null @@ -1,203 +0,0 @@ -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.MkvToolNix; -import lombok.Getter; -import lombok.Setter; -import lombok.extern.log4j.Log4j2; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import static java.lang.String.format; - -@Log4j2 -public class ConfigProcessorOld { - private int audioDefault = - 1; - private int subtitleDefault = - 1; - private final AttributeConfig config; - - public ConfigProcessorOld(AttributeConfig config) { - this.config = config; - } - - /** - * Processes the config lists and apply the changes if the combination matches - * - * @param file is the file, which will be updated - * @param attributes has the metadata for the transferred file - * @return If the current configuration matched and changes applied or not - */ - public boolean processConfig(File file, List attributes) { - // check if size is bigger or equal 2 to make sure that there is at least one audio and subtitle line - // TODO: implement empty audio or subtitle line - List attributesCopy = new ArrayList<>(attributes); - if(attributesCopy.size() >= 2){ - TransferObject transfer = filterAttributes(attributesCopy); - if(! attributesCopy.isEmpty()){ - return updateFile(file, attributesCopy, transfer); - } - } - return false; - } - - /* - * Filters the attributes that only those are remaining which are needed in the current configuration. - * Also analyzes which tracks were default before. - */ - private TransferObject filterAttributes(List attributes) { - TransferObject transfer = new TransferObject(); - Iterator iterator = attributes.iterator(); - while(iterator.hasNext()){ - FileAttribute elem = iterator.next(); - if("audio".equals(elem.getType())){ - if(elem.isDefaultTrack()){ - audioDefault = elem.getId(); - } - if(config.getAudioLanguage().contains("OFF")){ - transfer.setAudioOn(false); - transfer.setAudioIndex(- 2); - } - if(! config.getAudioLanguage().contains(elem.getLanguage())){ - iterator.remove(); - } - }else if("subtitles".equals(elem.getType())){ - if(elem.isDefaultTrack()){ - subtitleDefault = elem.getId(); - } - if(config.getSubtitleLanguage().contains("OFF")){ - transfer.setSubtitleOn(false); - transfer.setSubtitleIndex(- 2); - } - if(! config.getSubtitleLanguage().contains(elem.getLanguage())){ - iterator.remove(); - } - } - } - return transfer; - } - - /** - * Creates the command which will be executed if the attributes of the current file fit the current {@link AttributeConfig} - * - * @param file is the file, which will be updated - * @param attributes has the metadata for the transferred file - * @return if the current file was updated or not. Returns true if the file already has the correct metadata set - */ - private boolean updateFile(File file, List attributes, TransferObject transfer) { - StringBuilder stringBuffer = new StringBuilder(); - if(System.getProperty("os.name").toLowerCase().contains("windows")){ - stringBuffer.append(format("\"%s\" \"%s\" ", - Config.getInstance().getPathFor(MkvToolNix.MKV_PROP_EDIT), - file.getAbsolutePath())); - }else{ - stringBuffer.append(format("%s %s ", - Config.getInstance().getPathFor(MkvToolNix.MKV_PROP_EDIT), - file.getAbsolutePath())); - } - if(audioDefault != - 1){ - stringBuffer.append(format("--edit track:=%s --set flag-default=0 ", audioDefault)); - } - if(subtitleDefault != - 1){ - stringBuffer.append(format("--edit track:=%s --set flag-default=0 ", subtitleDefault)); - } - collectLines(attributes, transfer); - if(transfer.isValid){ - if(transfer.isAudioOn){ - stringBuffer.append(format("--edit track:=%s --set flag-default=1 ", transfer.getAudioIndex())); - } - if(transfer.isSubtitleOn){ - stringBuffer.append(format("--edit track:=%s --set flag-default=1 ", transfer.getSubtitleIndex())); - } - if(subtitleDefault == transfer.getSubtitleIndex() && audioDefault == transfer.getAudioIndex()){ - /* - * In this case the file would be change to the exact same audio and subtitle lines and we want to - * avoid unnecessary changes to the file - */ - log.info("File already fits config: {}", file.getName()); - return true; - } - try{ - if(!Config.getInstance().isSafeMode()) { - Runtime.getRuntime().exec(stringBuffer.toString()); - } - }catch(IOException e){ - log.error("Couldn't make changes to file"); - } - /* - * We return true even if there was an error. If there was an error, the chances that this file is still - * busy later. - */ - log.info("Updated {}", file.getName()); - return true; - }else{ - return false; - } - } - - /** - * Analyzes the left over attributes and decides which is the most wanted for audio and subtitle - * - * @param attributes contains all the leftover attributes - * @return is an object, which contains information about which audio and subtitle line is the best suitable for - * the entered config. Also transfers a boolean which contains information about if the other two values - * were set - */ - private TransferObject collectLines(List attributes, TransferObject transfer) { - int subtitleListIndex = - 1; - int audioListIndex = - 1; - for(FileAttribute elem : attributes){ -// if("audio".equals(elem.getType())){ -// for(int i = 0; i < config.getAudio().size(); i++){ -// audioListIndex = findIndex("audio", elem, audioListIndex, config.getAudio(), transfer); -// } -// }else if("subtitles".equals(elem.getType())){ -// for(int i = 0; i < config.getSubtitle().size(); i++){ -// subtitleListIndex = findIndex("subtitles", elem, subtitleListIndex, config.getSubtitle(), transfer); -// } -// } - } - - transfer.analyzeIfValid(); - return transfer; - } - - private int findIndex(String type, FileAttribute elem, int index, List config, TransferObject transfer) { - for(int i = 0; i < config.size(); i++){ - if(config.get(i).equals(elem.getLanguage()) && (index == - 1 || i < index)){ - switch(type){ - case "audio": - transfer.setAudioIndex(elem.getId()); - break; - case "subtitles": - transfer.setSubtitleIndex(elem.getId()); - break; - } - return i; - } - } - return index; - } - - @Getter - @Setter - private static class TransferObject { - private boolean isValid; - private int audioIndex = - 1; - private int subtitleIndex = - 1; - private boolean isSubtitleOn = true; - private boolean isAudioOn = true; - - TransferObject() { - } - - private void analyzeIfValid() { - isValid = audioIndex != - 1 && subtitleIndex != - 1; - } - } -} diff --git a/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/impl/MkvFileProcessor.java b/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/impl/MkvFileProcessor.java index c13eb1c..2da348a 100644 --- a/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/impl/MkvFileProcessor.java +++ b/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/impl/MkvFileProcessor.java @@ -5,29 +5,31 @@ import at.pcgamingfreaks.mkvaudiosubtitlechanger.model.*; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.core.util.IOUtils; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.Map; +import java.io.*; +import java.util.*; import java.util.stream.Collectors; import static at.pcgamingfreaks.mkvaudiosubtitlechanger.model.LaneType.AUDIO; import static at.pcgamingfreaks.mkvaudiosubtitlechanger.model.LaneType.SUBTITLES; +import static java.lang.String.format; @Log4j2 public class MkvFileProcessor implements FileProcessor { private final ObjectMapper mapper = new ObjectMapper(); + private final String[] forcedKeywords = new String[]{"forced", "signs"}; + 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_FORCED_TRACK = "--edit track:%s --set flag-forced=1 "; + @Override public List loadAttributes(File file) { Map jsonMap; List fileAttributes = new ArrayList<>(); try { - String command = String.format("\"%s\"", Config.getInstance().getPathFor(MkvToolNix.MKV_MERGER)); + String command = format("\"%s\"", Config.getInstance().getPathFor(MkvToolNix.MKV_MERGER)); String[] arguments = new String[]{ command, "--identify", @@ -40,7 +42,7 @@ public class MkvFileProcessor implements FileProcessor { jsonMap = mapper.readValue(inputStream, Map.class); List> tracks = (List>) jsonMap.get("tracks"); if (tracks == null) { - log.warn("Couldn't retrieve information of {}", file.getAbsoluteFile().toString()); + log.warn("Couldn't retrieve information of {}", file.getAbsolutePath()); return new ArrayList<>(); } for (Map attribute : tracks) { @@ -65,24 +67,40 @@ public class MkvFileProcessor implements FileProcessor { @Override public FileInfoDto filterAttributes(List attributes) { FileInfoDto info = new FileInfoDto(); + List nonForcedTracks = attributes.stream() + .filter(elem -> !StringUtils.containsAnyIgnoreCase(elem.getTrackName(), forcedKeywords)) + .collect(Collectors.toList()); + + detectCurrentConfiguration(attributes, info, nonForcedTracks); + detectDesiredConfiguration(info, nonForcedTracks); + + return info; + } + + private void detectCurrentConfiguration(List attributes, FileInfoDto info, List nonForcedTracks) { + Set detectedForcedSubtitleLanes = new HashSet<>(); for (FileAttribute attribute: attributes) { if (attribute.isDefaultTrack() && AUDIO.equals(attribute.getType())) info.setDefaultAudioLane(attribute); - if (attribute.isForcedTrack() && AUDIO.equals(attribute.getType())) info.setForcedAudioLane(attribute); - if (attribute.isDefaultTrack() && SUBTITLES.equals(attribute.getType())) info.setDefaultSubtitleLane(attribute); - if (attribute.isForcedTrack() && SUBTITLES.equals(attribute.getType())) info.setForcedSubtitleLane(attribute); + if (attribute.isForcedTrack() && SUBTITLES.equals(attribute.getType())) detectedForcedSubtitleLanes.add(attribute); } - List nonForcedTracks = attributes.stream() - .filter(elem -> !StringUtils.containsIgnoreCase(elem.getTrackName(), "forced")) - .collect(Collectors.toList()); + + info.setDesiredForcedSubtitleLanes(attributes.stream() + .filter(e -> !nonForcedTracks.contains(e)) + .filter(e -> !detectedForcedSubtitleLanes.contains(e)) + .collect(Collectors.toSet()) + ); + } + + private void detectDesiredConfiguration(FileInfoDto info, List nonForcedTracks) { for (AttributeConfig config: Config.getInstance().getAttributeConfig()) { FileAttribute desiredAudio = null; FileAttribute desiredSubtitle = null; for (FileAttribute attribute: nonForcedTracks) { if ( attribute.getLanguage().equals(config.getAudioLanguage()) - && AUDIO.equals(attribute.getType())) desiredAudio = attribute; + && AUDIO.equals(attribute.getType())) desiredAudio = attribute; if ( attribute.getLanguage().equals(config.getSubtitleLanguage()) - && SUBTITLES.equals(attribute.getType())) desiredSubtitle = attribute; + && SUBTITLES.equals(attribute.getType())) desiredSubtitle = attribute; } if (desiredAudio != null && desiredSubtitle != null) { info.setDesiredAudioLane(desiredAudio); @@ -90,11 +108,37 @@ public class MkvFileProcessor implements FileProcessor { break; } } - return info; } @Override public void update(File file, FileInfoDto fileInfo) { + StringBuffer sb = new StringBuffer(); + sb.append(format("\"%s\" ", Config.getInstance().getPathFor(MkvToolNix.MKV_PROP_EDIT))); + sb.append(format("\"%s\" ", file.getAbsolutePath())); + if (fileInfo.isAudioDifferent()) { + if (fileInfo.getDefaultAudioLane() != null) { + sb.append(format(DISABLE_DEFAULT_TRACK, fileInfo.getDefaultAudioLane().getId())); + } + sb.append(format(ENABLE_DEFAULT_TRACK, fileInfo.getDesiredAudioLane().getId())); + } + if (fileInfo.isSubtitleDifferent()) { + if (fileInfo.getDefaultSubtitleLane() != null) { + sb.append(format(DISABLE_DEFAULT_TRACK, fileInfo.getDefaultSubtitleLane().getId())); + } + sb.append(format(ENABLE_DEFAULT_TRACK, fileInfo.getDesiredSubtitleLane().getId())); + } + if (fileInfo.areForcedTracksDifferent()) { + for (FileAttribute attribute: fileInfo.getDesiredForcedSubtitleLanes()) { + sb.append(format(ENABLE_FORCED_TRACK, attribute.getId())); + } + } + try { + InputStream inputstream = Runtime.getRuntime().exec(sb.toString()).getInputStream(); + log.debug(IOUtils.toString(new InputStreamReader(inputstream))); + } catch (IOException e) { + log.warn("File couldn't be updated: {}", file.getAbsoluteFile()); + } } + } diff --git a/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/model/FileAttribute.java b/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/model/FileAttribute.java index 0932c0c..4f2090d 100644 --- a/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/model/FileAttribute.java +++ b/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/model/FileAttribute.java @@ -3,27 +3,17 @@ package at.pcgamingfreaks.mkvaudiosubtitlechanger.model; import lombok.Getter; import lombok.extern.log4j.Log4j2; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - @Log4j2 @Getter public class FileAttribute { - private int id; - private String language; - private String trackName; - private boolean defaultTrack; - private boolean forcedTrack; - private LaneType type; + 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 FileAttribute(int id, String language, String trackName, boolean defaultTrack, boolean forcedTrack, - LaneType type) { + public FileAttribute(int id, String language, String trackName, boolean defaultTrack, boolean forcedTrack, LaneType type) { this.id = id; this.language = language; this.trackName = trackName; @@ -31,28 +21,4 @@ public class FileAttribute { this.forcedTrack = forcedTrack; this.type = type; } - - public static boolean pathIsValid(String path) { - File file = new File(path); - if(file.isFile()){ - return file.getAbsolutePath().endsWith(".mkv"); - } - if(file.isDirectory()){ - try(Stream paths = Files.walk(Paths.get(path))){ - List allPaths = paths - .filter(Files::isRegularFile) - .map(f -> f.toAbsolutePath().toString()) - .collect(Collectors.toList()); - for(String filePath : allPaths){ - if(! filePath.endsWith(".mkv")){ - return false; - } - } - }catch(IOException e){ - log.error("Couldn't find file or directory!", e); - } - return true; - } - return false; - } } diff --git a/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/model/FileInfoDto.java b/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/model/FileInfoDto.java index 9b8592e..81f4123 100644 --- a/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/model/FileInfoDto.java +++ b/src/main/java/at/pcgamingfreaks/mkvaudiosubtitlechanger/model/FileInfoDto.java @@ -3,18 +3,32 @@ package at.pcgamingfreaks.mkvaudiosubtitlechanger.model; import lombok.Getter; import lombok.Setter; +import java.util.Set; + @Getter @Setter public class FileInfoDto { private FileAttribute defaultAudioLane; private FileAttribute defaultSubtitleLane; - private FileAttribute forcedAudioLane; - private FileAttribute forcedSubtitleLane; + private Set desiredForcedSubtitleLanes; private FileAttribute desiredAudioLane; private FileAttribute desiredSubtitleLane; public boolean isChangeNecessary() { - return defaultAudioLane.getId() != desiredAudioLane.getId() - || defaultSubtitleLane.getId() != desiredSubtitleLane.getId(); + return isAudioDifferent() || isSubtitleDifferent() || areForcedTracksDifferent(); + } + + public boolean isAudioDifferent() { + return desiredAudioLane != null && + (defaultAudioLane == null || defaultAudioLane.getId() != desiredAudioLane.getId()); + } + + public boolean isSubtitleDifferent() { + return desiredSubtitleLane != null && + (defaultSubtitleLane == null || defaultSubtitleLane.getId() != desiredSubtitleLane.getId()); + } + + public boolean areForcedTracksDifferent() { + return desiredForcedSubtitleLanes.size() > 0; } }