forked from j62/ctbrec
1
0
Fork 0

Add script post-processor

This commit is contained in:
0xb00bface 2020-09-23 18:52:30 +02:00
parent 67ff48e2dc
commit f6afed3717
5 changed files with 91 additions and 5 deletions

View File

@ -11,6 +11,7 @@ import ctbrec.recorder.postprocessing.Move;
import ctbrec.recorder.postprocessing.PostProcessor; import ctbrec.recorder.postprocessing.PostProcessor;
import ctbrec.recorder.postprocessing.Remux; import ctbrec.recorder.postprocessing.Remux;
import ctbrec.recorder.postprocessing.Rename; import ctbrec.recorder.postprocessing.Rename;
import ctbrec.recorder.postprocessing.Script;
import ctbrec.ui.controls.Dialogs; import ctbrec.ui.controls.Dialogs;
import ctbrec.ui.settings.api.Preferences; import ctbrec.ui.settings.api.Preferences;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
@ -22,6 +23,7 @@ public class PostProcessingDialogFactory {
static Map<Class<?>, Class<?>> ppToDialogMap = new HashMap<>(); static Map<Class<?>, Class<?>> ppToDialogMap = new HashMap<>();
static { static {
ppToDialogMap.put(Remux.class, RemuxerPaneFactory.class); ppToDialogMap.put(Remux.class, RemuxerPaneFactory.class);
ppToDialogMap.put(Script.class, ScriptPaneFactory.class);
ppToDialogMap.put(Rename.class, RenamerPaneFactory.class); ppToDialogMap.put(Rename.class, RenamerPaneFactory.class);
ppToDialogMap.put(Move.class, MoverPaneFactory.class); ppToDialogMap.put(Move.class, MoverPaneFactory.class);
} }

View File

@ -13,6 +13,7 @@ import ctbrec.recorder.postprocessing.PostProcessor;
import ctbrec.recorder.postprocessing.RemoveKeepFile; import ctbrec.recorder.postprocessing.RemoveKeepFile;
import ctbrec.recorder.postprocessing.Remux; import ctbrec.recorder.postprocessing.Remux;
import ctbrec.recorder.postprocessing.Rename; import ctbrec.recorder.postprocessing.Rename;
import ctbrec.recorder.postprocessing.Script;
import ctbrec.ui.controls.Dialogs; import ctbrec.ui.controls.Dialogs;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener;
@ -34,9 +35,10 @@ public class PostProcessingStepPanel extends GridPane {
private static final Class<?>[] POST_PROCESSOR_CLASSES = new Class<?>[] { // @formatter: off private static final Class<?>[] POST_PROCESSOR_CLASSES = new Class<?>[] { // @formatter: off
Copy.class, Copy.class,
Remux.class,
Rename.class, Rename.class,
Move.class, Move.class,
Remux.class,
Script.class,
DeleteOriginal.class, DeleteOriginal.class,
RemoveKeepFile.class RemoveKeepFile.class
}; // @formatter: on }; // @formatter: on

View File

@ -0,0 +1,27 @@
package ctbrec.ui.settings;
import ctbrec.recorder.postprocessing.PostProcessor;
import ctbrec.recorder.postprocessing.Script;
import ctbrec.ui.settings.api.Category;
import ctbrec.ui.settings.api.Preferences;
import ctbrec.ui.settings.api.Setting;
import javafx.beans.property.SimpleStringProperty;
public class ScriptPaneFactory extends AbstractPostProcessingPaneFactory {
@Override
public Preferences doCreatePostProcessorPane(PostProcessor pp) {
SimpleStringProperty script = new SimpleStringProperty(null, Script.SCRIPT_EXECUTABLE, pp.getConfig().getOrDefault(Script.SCRIPT_EXECUTABLE, "c:\\users\\johndoe\\somescript"));
SimpleStringProperty params = new SimpleStringProperty(null, Script.SCRIPT_PARAMS, pp.getConfig().getOrDefault(Script.SCRIPT_PARAMS, "${absolutePath}"));
properties.add(script);
properties.add(params);
return Preferences.of(new MapPreferencesStorage(),
Category.of(pp.getName(),
Setting.of("Script", script),
Setting.of("Parameters", params)
)
);
}
}

View File

@ -25,7 +25,9 @@ public abstract class AbstractPlaceholderAwarePostProcessor extends AbstractPost
"${epochSecond}", "${epochSecond}",
"${fileSuffix}", "${fileSuffix}",
"${modelNotes}", "${modelNotes}",
"${recordingsDir}" "${recordingsDir}",
"${absolutePath}",
"${absoluteParentPath}"
}; };
public String fillInPlaceHolders(String input, Recording rec, Config config) { public String fillInPlaceHolders(String input, Recording rec, Config config) {
@ -40,6 +42,8 @@ public abstract class AbstractPlaceholderAwarePostProcessor extends AbstractPost
.replace("${epochSecond}", Long.toString(rec.getStartDate().getEpochSecond())) .replace("${epochSecond}", Long.toString(rec.getStartDate().getEpochSecond()))
.replace("${modelNotes}", config.getModelNotes(rec.getModel())) .replace("${modelNotes}", config.getModelNotes(rec.getModel()))
.replace("${recordingsDir}", config.getSettings().recordingsDir) .replace("${recordingsDir}", config.getSettings().recordingsDir)
.replace("${absolutePath}", rec.getPostProcessedFile().getAbsolutePath())
.replace("${absoluteParentPath}", rec.getPostProcessedFile().getParentFile().getAbsolutePath())
; ;
output = replaceUtcDateTime(rec, output); output = replaceUtcDateTime(rec, output);

View File

@ -1,14 +1,26 @@
package ctbrec.recorder.postprocessing; package ctbrec.recorder.postprocessing;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.NotImplementedExcetion; import ctbrec.OS;
import ctbrec.Recording; import ctbrec.Recording;
import ctbrec.io.StreamRedirectThread;
import ctbrec.recorder.RecordingManager; import ctbrec.recorder.RecordingManager;
import ctbrec.recorder.download.ProcessExitedUncleanException;
public class Script extends AbstractPlaceholderAwarePostProcessor { public class Script extends AbstractPlaceholderAwarePostProcessor {
private static final Logger LOG = LoggerFactory.getLogger(Script.class);
public static final String SCRIPT_EXECUTABLE = "script.executable";
public static final String SCRIPT_PARAMS = "script.params";
@Override @Override
public String getName() { public String getName() {
return "execute script"; return "execute script";
@ -16,7 +28,46 @@ public class Script extends AbstractPlaceholderAwarePostProcessor {
@Override @Override
public void postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException { public void postprocess(Recording rec, RecordingManager recordingManager, Config config) throws IOException, InterruptedException {
// TODO make it possible to choose, which placeholders to pass to the script List<String> cmdline = buildCommandLine(rec, config);
throw new NotImplementedExcetion(); Runtime rt = Runtime.getRuntime();
String[] args = cmdline.toArray(new String[0]);
if (LOG.isDebugEnabled()) {
LOG.debug("Running {}", Arrays.toString(args));
}
Process process = rt.exec(args, OS.getEnvironment());
startLogging(process);
int exitCode = process.waitFor();
LOG.debug("Process finished with exit code {}", exitCode);
if (exitCode != 0) {
throw new ProcessExitedUncleanException("Script finished with exit code " + exitCode);
} }
} }
private List<String> buildCommandLine(Recording rec, Config config) throws IOException {
String script = getConfig().getOrDefault(SCRIPT_EXECUTABLE, "somescript");
String params = getConfig().getOrDefault(SCRIPT_PARAMS, "${absolutePath}");
List<String> cmdline = new ArrayList<>();
cmdline.add(script);
String replacedParams = fillInPlaceHolders(params, rec, config);
Arrays.stream(replacedParams.split(" ")).forEach(cmdline::add);
return cmdline;
}
private void startLogging(Process process) {
// TODO maybe write these to a separate log file, e.g. recname.ts.script.log
Thread std = new Thread(new StreamRedirectThread(process.getInputStream(), System.out));
std.setName("Process stdout pipe");
std.setDaemon(true);
std.start();
Thread err = new Thread(new StreamRedirectThread(process.getErrorStream(), System.err));
err.setName("Process stderr pipe");
err.setDaemon(true);
err.start();
}
@Override
public String toString() {
return (getName() + " " + getConfig().getOrDefault(Script.SCRIPT_EXECUTABLE, "")).trim();
}
}