From 4f7d080f56a1bff2fe73ade658b196f87728d86f Mon Sep 17 00:00:00 2001 From: 0xb00bface <0xboobface@gmail.com> Date: Sun, 30 Aug 2020 13:41:03 +0200 Subject: [PATCH] Add more pp steps --- .../AbstractPostProcessingPaneFactory.java | 150 +++++++++++++++++- .../settings/PostProcessingDialogFactory.java | 31 ++-- .../ui/settings/PostProcessingStepPanel.java | 15 +- .../ctbrec/recorder/postprocessing/Copy.java | 39 +++++ .../recorder/postprocessing/Renamer.java | 3 +- 5 files changed, 219 insertions(+), 19 deletions(-) create mode 100644 common/src/main/java/ctbrec/recorder/postprocessing/Copy.java diff --git a/client/src/main/java/ctbrec/ui/settings/AbstractPostProcessingPaneFactory.java b/client/src/main/java/ctbrec/ui/settings/AbstractPostProcessingPaneFactory.java index 37515cd6..76c2fdc6 100644 --- a/client/src/main/java/ctbrec/ui/settings/AbstractPostProcessingPaneFactory.java +++ b/client/src/main/java/ctbrec/ui/settings/AbstractPostProcessingPaneFactory.java @@ -4,16 +4,38 @@ import java.io.IOException; import java.util.HashSet; import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import ctbrec.recorder.postprocessing.PostProcessor; +import ctbrec.ui.controls.DirectorySelectionBox; +import ctbrec.ui.controls.ProgramSelectionBox; +import ctbrec.ui.settings.api.ExclusiveSelectionProperty; import ctbrec.ui.settings.api.Preferences; import ctbrec.ui.settings.api.PreferencesStorage; import ctbrec.ui.settings.api.Setting; +import ctbrec.ui.settings.api.SimpleDirectoryProperty; +import ctbrec.ui.settings.api.SimpleFileProperty; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.ListProperty; +import javafx.beans.property.LongProperty; import javafx.beans.property.Property; +import javafx.beans.property.StringProperty; +import javafx.geometry.Insets; import javafx.scene.Node; +import javafx.scene.control.CheckBox; +import javafx.scene.control.ComboBox; +import javafx.scene.control.Label; +import javafx.scene.control.RadioButton; import javafx.scene.control.TextField; +import javafx.scene.control.ToggleGroup; +import javafx.scene.layout.HBox; +import javafx.util.converter.NumberStringConverter; public abstract class AbstractPostProcessingPaneFactory { + private static final Logger LOG = LoggerFactory.getLogger(AbstractPostProcessingPaneFactory.class); private PostProcessor pp; Set> properties = new HashSet<>(); @@ -31,6 +53,7 @@ public abstract class AbstractPostProcessingPaneFactory { for (Property property : properties) { String key = property.getName(); Object value = preferences.getSetting(key).get().getProperty().getValue(); + LOG.debug("{}={}", key, value.toString()); pp.getConfig().put(key, value.toString()); } } @@ -40,13 +63,132 @@ public abstract class AbstractPostProcessingPaneFactory { // no op } - @SuppressWarnings("unchecked") @Override public Node createGui(Setting setting) throws Exception { - TextField input = new TextField(); - input.textProperty().bindBidirectional(setting.getProperty()); - return input; + Property prop = setting.getProperty(); + if (prop instanceof ExclusiveSelectionProperty) { + return createRadioGroup(setting); + } else if (prop instanceof SimpleDirectoryProperty) { + return createDirectorySelector(setting); + } else if (prop instanceof SimpleFileProperty) { + return createFileSelector(setting); + } else if (prop instanceof IntegerProperty) { + return createIntegerProperty(setting); + } else if (prop instanceof LongProperty) { + return createLongProperty(setting); + } else if (prop instanceof BooleanProperty) { + return createBooleanProperty(setting); + } else if (prop instanceof ListProperty) { + return createComboBox(setting); + } else if (prop instanceof StringProperty) { + return createStringProperty(setting); + } else { + return new Label("Unsupported Type for key " + setting.getKey() + ": " + setting.getProperty()); + } } + } + private Node createRadioGroup(Setting setting) { + ExclusiveSelectionProperty prop = (ExclusiveSelectionProperty) setting.getProperty(); + ToggleGroup toggleGroup = new ToggleGroup(); + RadioButton optionA = new RadioButton(prop.getOptionA()); + optionA.setSelected(prop.getValue()); + optionA.setToggleGroup(toggleGroup); + RadioButton optionB = new RadioButton(prop.getOptionB()); + optionB.setSelected(!optionA.isSelected()); + optionB.setToggleGroup(toggleGroup); + optionA.selectedProperty().bindBidirectional(prop); + HBox row = new HBox(); + row.getChildren().addAll(optionA, optionB); + HBox.setMargin(optionA, new Insets(5)); + HBox.setMargin(optionB, new Insets(5)); + return row; + } + + private Node createFileSelector(Setting setting) { + ProgramSelectionBox programSelector = new ProgramSelectionBox(""); + // programSelector.fileProperty().addListener((obs, o, n) -> saveValue(() -> { + // String path = n; + // Field field = Settings.class.getField(setting.getKey()); + // String oldValue = (String) field.get(settings); + // if (!Objects.equals(path, oldValue)) { + // field.set(settings, path); + // config.save(); + // } + // })); + StringProperty property = (StringProperty) setting.getProperty(); + programSelector.fileProperty().bindBidirectional(property); + return programSelector; + } + + private Node createDirectorySelector(Setting setting) { + DirectorySelectionBox directorySelector = new DirectorySelectionBox(""); + directorySelector.prefWidth(400); + // directorySelector.fileProperty().addListener((obs, o, n) -> saveValue(() -> { + // String path = n; + // Field field = Settings.class.getField(setting.getKey()); + // String oldValue = (String) field.get(settings); + // if (!Objects.equals(path, oldValue)) { + // field.set(settings, path); + // config.save(); + // } + // })); + StringProperty property = (StringProperty) setting.getProperty(); + directorySelector.fileProperty().bindBidirectional(property); + return directorySelector; + } + + @SuppressWarnings("unchecked") + private Node createStringProperty(Setting setting) { + TextField ctrl = new TextField(); + ctrl.textProperty().bindBidirectional(setting.getProperty()); + return ctrl; + } + + @SuppressWarnings("unchecked") + private Node createIntegerProperty(Setting setting) { + TextField ctrl = new TextField(); + Property prop = setting.getProperty(); + ctrl.textProperty().bindBidirectional(prop, new NumberStringConverter()); + return ctrl; + } + + @SuppressWarnings("unchecked") + private Node createLongProperty(Setting setting) { + TextField ctrl = new TextField(); + Property prop = setting.getProperty(); + ctrl.textProperty().bindBidirectional(prop, new NumberStringConverter()); + return ctrl; + } + + private Node createBooleanProperty(Setting setting) { + CheckBox ctrl = new CheckBox(); + BooleanProperty prop = (BooleanProperty) setting.getProperty(); + ctrl.selectedProperty().bindBidirectional(prop); + return ctrl; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private Node createComboBox(Setting setting) throws NoSuchFieldException, IllegalAccessException { + ListProperty listProp = (ListProperty) setting.getProperty(); + ComboBox comboBox = new ComboBox(listProp); + // Field field = Settings.class.getField(setting.getKey()); + // Object value = field.get(Config.getInstance().getSettings()); + // if (StringUtil.isNotBlank(value.toString())) { + // if (setting.getConverter() != null) { + // comboBox.getSelectionModel().select(setting.getConverter().convertTo(value)); + // } else { + // comboBox.getSelectionModel().select(value); + // } + // } + // comboBox.valueProperty().addListener((obs, oldV, newV) -> saveValue(() -> { + // if (setting.getConverter() != null) { + // field.set(settings, setting.getConverter().convertFrom(newV)); + // } else { + // field.set(settings, newV); + // } + // config.save(); + // })); + return comboBox; } } diff --git a/client/src/main/java/ctbrec/ui/settings/PostProcessingDialogFactory.java b/client/src/main/java/ctbrec/ui/settings/PostProcessingDialogFactory.java index 2d67dbb5..094f4c8c 100644 --- a/client/src/main/java/ctbrec/ui/settings/PostProcessingDialogFactory.java +++ b/client/src/main/java/ctbrec/ui/settings/PostProcessingDialogFactory.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import ctbrec.Config; import ctbrec.recorder.postprocessing.PostProcessor; @@ -37,15 +38,19 @@ public class PostProcessingDialogFactory { private static void openDialog(PostProcessor pp, Config config, Scene scene, ObservableList stepList, boolean newEntry) { boolean ok; try { - Preferences preferences = createPreferences(pp); - Region view = preferences.getView(false); - view.setMinWidth(600); - ok = Dialogs.showCustomInput(scene, "Configure " + pp.getName(), view); - if (ok) { - preferences.save(); - if (newEntry) { - stepList.add(pp); + Optional preferences = createPreferences(pp); + if(preferences.isPresent()) { + Region view = preferences.get().getView(false); + view.setMinWidth(600); + ok = Dialogs.showCustomInput(scene, "Configure " + pp.getName(), view); + if (ok) { + preferences.get().save(); + if (newEntry) { + stepList.add(pp); + } } + } else if (newEntry) { + stepList.add(pp); } } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException | IOException e) { @@ -53,10 +58,14 @@ public class PostProcessingDialogFactory { } } - private static Preferences createPreferences(PostProcessor pp) throws InstantiationException, IllegalAccessException, IllegalArgumentException, + private static Optional createPreferences(PostProcessor pp) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { Class paneFactoryClass = ppToDialogMap.get(pp.getClass()); - AbstractPostProcessingPaneFactory factory = (AbstractPostProcessingPaneFactory) paneFactoryClass.getDeclaredConstructor().newInstance(); - return factory.createPostProcessorPane(pp); + if (paneFactoryClass != null) { + AbstractPostProcessingPaneFactory factory = (AbstractPostProcessingPaneFactory) paneFactoryClass.getDeclaredConstructor().newInstance(); + return Optional.of(factory.createPostProcessorPane(pp)); + } else { + return Optional.empty(); + } } } diff --git a/client/src/main/java/ctbrec/ui/settings/PostProcessingStepPanel.java b/client/src/main/java/ctbrec/ui/settings/PostProcessingStepPanel.java index 121c1ba3..91e5d367 100644 --- a/client/src/main/java/ctbrec/ui/settings/PostProcessingStepPanel.java +++ b/client/src/main/java/ctbrec/ui/settings/PostProcessingStepPanel.java @@ -6,9 +6,10 @@ import java.lang.reflect.InvocationTargetException; import java.util.Optional; import ctbrec.Config; +import ctbrec.recorder.postprocessing.Copy; import ctbrec.recorder.postprocessing.PostProcessor; -import ctbrec.recorder.postprocessing.Renamer; import ctbrec.recorder.postprocessing.Remuxer; +import ctbrec.recorder.postprocessing.Renamer; import ctbrec.ui.controls.Dialogs; import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; @@ -27,7 +28,7 @@ public class PostProcessingStepPanel extends GridPane { private Config config; - private static final Class[] POST_PROCESSOR_CLASSES = new Class[] { Remuxer.class, Renamer.class }; + private static final Class[] POST_PROCESSOR_CLASSES = new Class[] { Copy.class, Remuxer.class, Renamer.class }; ListView stepListView; ObservableList stepList; @@ -121,10 +122,19 @@ public class PostProcessingStepPanel extends GridPane { Optional result = choice.showAndWait(); result.ifPresent(pp -> PostProcessingDialogFactory.openNewDialog(pp, config, getScene(), stepList)); + saveConfig(); }); return add; } + private void saveConfig() { + try { + config.save(); + } catch (IOException e) { + Dialogs.showError("Post-Processing", "Couldn't save post-processing step", e); + } + } + private PostProcessor[] createOptions() { try { PostProcessor[] options = new PostProcessor[POST_PROCESSOR_CLASSES.length]; @@ -159,6 +169,7 @@ public class PostProcessingStepPanel extends GridPane { PostProcessor selectedItem = stepListView.getSelectionModel().getSelectedItem(); PostProcessingDialogFactory.openEditDialog(selectedItem, config, getScene(), stepList); stepListView.refresh(); + saveConfig(); }); return edit; } diff --git a/common/src/main/java/ctbrec/recorder/postprocessing/Copy.java b/common/src/main/java/ctbrec/recorder/postprocessing/Copy.java new file mode 100644 index 00000000..88dcf452 --- /dev/null +++ b/common/src/main/java/ctbrec/recorder/postprocessing/Copy.java @@ -0,0 +1,39 @@ +package ctbrec.recorder.postprocessing; + +import java.io.File; +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.io.Files; + +import ctbrec.Recording; + +public class Copy extends AbstractPostProcessor { + + private static final transient Logger LOG = LoggerFactory.getLogger(Copy.class); + + @Override + public String getName() { + return "create a copy"; + } + + @Override + public void postprocess(Recording rec) throws IOException, InterruptedException { + File orig = rec.getPostProcessedFile(); + String copyFilename = getFilenameForCopy(orig); + File copy = new File(orig.getParentFile(), copyFilename); + LOG.info("Creating a copy {}", copy); + Files.copy(rec.getPostProcessedFile(), copy); + rec.setPostProcessedFile(copy); + rec.getAssociatedFiles().add(copy.getAbsolutePath()); + } + + private String getFilenameForCopy(File orig) { + String filename = orig.getName(); + String name = filename.substring(0, filename.lastIndexOf('.')); + String ext = filename.substring(filename.lastIndexOf('.') + 1); + return name + "_copy." + ext; + } +} diff --git a/common/src/main/java/ctbrec/recorder/postprocessing/Renamer.java b/common/src/main/java/ctbrec/recorder/postprocessing/Renamer.java index 291cecce..b542cb24 100644 --- a/common/src/main/java/ctbrec/recorder/postprocessing/Renamer.java +++ b/common/src/main/java/ctbrec/recorder/postprocessing/Renamer.java @@ -61,8 +61,7 @@ public class Renamer extends AbstractPostProcessor { File src = rec.getPostProcessedFile(); File target = new File(src.getParentFile(), filename); LOG.info("Renaming {} to {}", src.getName(), target.getName()); - Files.copy(rec.getPostProcessedFile(), target); - //Files.move(rec.getPostProcessedFile(), target); + Files.move(rec.getPostProcessedFile(), target); rec.setPostProcessedFile(target); rec.getAssociatedFiles().add(target.getAbsolutePath()); }