From b268549ef6cb073dc717ecdcc54cd1be37e05652 Mon Sep 17 00:00:00 2001 From: 0xb00bface <0xboobface@gmail.com> Date: Wed, 1 Nov 2023 18:02:11 +0100 Subject: [PATCH] Fix loading of EventHandlerConfiguration --- .../ui/settings/ActionSettingsPanel.java | 5 +- .../event/EventHandlerConfiguration.java | 120 +----------- .../java/ctbrec/event/ModelPredicate.java | 18 +- .../recorder/download/hls/FFmpegDownload.java | 174 ------------------ 4 files changed, 22 insertions(+), 295 deletions(-) delete mode 100644 common/src/main/java/ctbrec/recorder/download/hls/FFmpegDownload.java diff --git a/client/src/main/java/ctbrec/ui/settings/ActionSettingsPanel.java b/client/src/main/java/ctbrec/ui/settings/ActionSettingsPanel.java index 1089e0e1..d751e6cf 100644 --- a/client/src/main/java/ctbrec/ui/settings/ActionSettingsPanel.java +++ b/client/src/main/java/ctbrec/ui/settings/ActionSettingsPanel.java @@ -7,6 +7,7 @@ import ctbrec.StringUtil; import ctbrec.event.*; import ctbrec.event.EventHandlerConfiguration.ActionConfiguration; import ctbrec.event.EventHandlerConfiguration.PredicateConfiguration; +import ctbrec.io.json.mapper.ModelMapper; import ctbrec.recorder.Recorder; import ctbrec.ui.CamrecApplication; import ctbrec.ui.DesktopIntegration; @@ -33,6 +34,7 @@ import javafx.scene.layout.Priority; import javafx.stage.Modality; import javafx.stage.Stage; import javafx.stage.Window; +import org.mapstruct.factory.Mappers; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,6 +50,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; public class ActionSettingsPanel extends GridPane { private static final Logger LOG = LoggerFactory.getLogger(ActionSettingsPanel.class); @@ -168,7 +171,7 @@ public class ActionSettingsPanel extends GridPane { if (!modelSelectionPane.isAllSelected()) { var pc = new PredicateConfiguration(); pc.setType(ModelPredicate.class.getName()); - pc.setModels(modelSelectionPane.getSelectedItems()); + pc.setModels(modelSelectionPane.getSelectedItems().stream().map(Mappers.getMapper(ModelMapper.class)::toDto).collect(Collectors.toList())); // NOSONAR pc.setName("model is one of:" + modelSelectionPane.getSelectedItems()); config.getPredicates().add(pc); } diff --git a/common/src/main/java/ctbrec/event/EventHandlerConfiguration.java b/common/src/main/java/ctbrec/event/EventHandlerConfiguration.java index 2cbb45aa..efa0fe83 100644 --- a/common/src/main/java/ctbrec/event/EventHandlerConfiguration.java +++ b/common/src/main/java/ctbrec/event/EventHandlerConfiguration.java @@ -1,9 +1,13 @@ package ctbrec.event; -import ctbrec.Model; +import ctbrec.io.json.dto.ModelDto; +import lombok.Data; +import lombok.EqualsAndHashCode; import java.util.*; +@Data +@EqualsAndHashCode(of = "id") public class EventHandlerConfiguration { private String id; @@ -16,111 +20,25 @@ public class EventHandlerConfiguration { id = UUID.randomUUID().toString(); } - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public Event.Type getEvent() { - return event; - } - - public void setEvent(Event.Type event) { - this.event = event; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public List getPredicates() { - return predicates; - } - - public void setPredicates(List predicates) { - this.predicates = predicates; - } - - public List getActions() { - return actions; - } - - public void setActions(List actions) { - this.actions = actions; - } - + @Data public static class PredicateConfiguration { private String name; private String type; - private List models; + private List models; private Map configuration = new HashMap<>(); - public void setName(String name) { - this.name = name; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public Map getConfiguration() { - return configuration; - } - - public void setConfiguration(Map configuration) { - this.configuration = configuration; - } - - public List getModels() { - return models; - } - - public void setModels(List models) { - this.models = models; - } - @Override public String toString() { return name; } } + @Data public static class ActionConfiguration { private String name; private String type; private Map configuration = new HashMap<>(); - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public Map getConfiguration() { - return configuration; - } - - public void setConfiguration(Map configuration) { - this.configuration = configuration; - } - - public void setName(String name) { - this.name = name; - } - @Override public String toString() { return name; @@ -131,26 +49,4 @@ public class EventHandlerConfiguration { public String toString() { return name + ", when:" + predicates + " do:" + actions + "]"; } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - EventHandlerConfiguration other = (EventHandlerConfiguration) obj; - if (id == null) { - return other.id == null; - } else return id.equals(other.id); - } } diff --git a/common/src/main/java/ctbrec/event/ModelPredicate.java b/common/src/main/java/ctbrec/event/ModelPredicate.java index d573ab6f..587872cd 100644 --- a/common/src/main/java/ctbrec/event/ModelPredicate.java +++ b/common/src/main/java/ctbrec/event/ModelPredicate.java @@ -1,17 +1,20 @@ package ctbrec.event; +import ctbrec.Model; +import ctbrec.event.EventHandlerConfiguration.PredicateConfiguration; +import ctbrec.io.json.mapper.ModelMapper; +import org.mapstruct.factory.Mappers; + import java.util.List; import java.util.Objects; import java.util.function.Predicate; -import ctbrec.Model; -import ctbrec.event.EventHandlerConfiguration.PredicateConfiguration; - public class ModelPredicate extends EventPredicate { private Predicate internal; - public ModelPredicate() {} + public ModelPredicate() { + } public ModelPredicate(Model model) { internal = createFor(model); @@ -22,7 +25,7 @@ public class ModelPredicate extends EventPredicate { } private void configure(List models) { - if(models.isEmpty()) { + if (models.isEmpty()) { throw new IllegalArgumentException("List has to contain at least one model"); } @@ -40,8 +43,7 @@ public class ModelPredicate extends EventPredicate { private Predicate createFor(Model model) { return evt -> { - if(evt instanceof AbstractModelEvent) { - AbstractModelEvent modelEvent = (AbstractModelEvent) evt; + if (evt instanceof AbstractModelEvent modelEvent) { Model other = modelEvent.getModel(); return Objects.equals(model, other); } else { @@ -52,6 +54,6 @@ public class ModelPredicate extends EventPredicate { @Override public void configure(PredicateConfiguration pc) { - configure(pc.getModels()); + configure(pc.getModels().stream().map(Mappers.getMapper(ModelMapper.class)::toModel).toList()); } } diff --git a/common/src/main/java/ctbrec/recorder/download/hls/FFmpegDownload.java b/common/src/main/java/ctbrec/recorder/download/hls/FFmpegDownload.java deleted file mode 100644 index 0d603601..00000000 --- a/common/src/main/java/ctbrec/recorder/download/hls/FFmpegDownload.java +++ /dev/null @@ -1,174 +0,0 @@ -package ctbrec.recorder.download.hls; - -import com.iheartradio.m3u8.ParseException; -import com.iheartradio.m3u8.PlaylistException; -import ctbrec.Config; -import ctbrec.Model; -import ctbrec.OS; -import ctbrec.Recording; -import ctbrec.io.HttpClient; -import ctbrec.io.StreamRedirector; -import ctbrec.recorder.download.ProcessExitedUncleanException; -import ctbrec.recorder.download.hls.SegmentPlaylist.Segment; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.xml.bind.JAXBException; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.time.Instant; -import java.util.Arrays; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.regex.Pattern; - -/** - * Does the whole HLS download with FFmpeg. Not used at the moment, because FFMpeg can't - * handle the HLS encryption of Flirt4Free correctly - */ -public class FFmpegDownload extends AbstractHlsDownload { - private static final transient Logger LOG = LoggerFactory.getLogger(FFmpegDownload.class); - - private transient Process ffmpeg; - private File targetFile; - - public FFmpegDownload(HttpClient client) { - super(client); - } - - @Override - public void init(Config config, Model model, Instant startTime, ExecutorService executorService) throws IOException { - super.init(config, model, startTime, executorService); - String suffix = config.getSettings().ffmpegFileSuffix; - targetFile = config.getFileForRecording(model, suffix, startTime); - } - - @Override - public FFmpegDownload call() throws IOException { - try { - Files.createDirectories(targetFile.getParentFile().toPath()); - String chunkPlaylist = getSegmentPlaylistUrl(model); - - String[] args = config.getSettings().ffmpegMergedDownloadArgs.split(" "); - String[] argsPlusFile = new String[args.length + 5]; - int i = 0; - argsPlusFile[i++] = "-headers"; - argsPlusFile[i++] = "User-Agent: " + config.getSettings().httpUserAgent; - argsPlusFile[i++] = "-i"; - argsPlusFile[i++] = chunkPlaylist; - System.arraycopy(args, 0, argsPlusFile, i, args.length); - argsPlusFile[argsPlusFile.length - 1] = targetFile.getAbsolutePath(); - String[] cmdline = OS.getFFmpegCommand(argsPlusFile); - LOG.debug("Command line: {}", Arrays.toString(cmdline)); - ffmpeg = Runtime.getRuntime().exec(cmdline, new String[0], targetFile.getParentFile()); - int exitCode = 1; - File ffmpegLog = File.createTempFile(targetFile.getName(), ".log"); - ffmpegLog.deleteOnExit(); - try (FileOutputStream mergeLogStream = new FileOutputStream(ffmpegLog)) { - Thread stdout = new Thread(new StreamRedirector(ffmpeg.getInputStream(), mergeLogStream)); - Thread stderr = new Thread(new StreamRedirector(ffmpeg.getErrorStream(), mergeLogStream)); - stdout.start(); - stderr.start(); - exitCode = ffmpeg.waitFor(); - stdout.join(); - stderr.join(); - mergeLogStream.flush(); - } - if (exitCode == 0) { - if (ffmpegLog.exists()) { - Files.delete(ffmpegLog.toPath()); - } - } else { - LOG.info("FFmpeg exit code was {}. Logfile: {}", exitCode, ffmpegLog.getAbsolutePath()); - throw new ProcessExitedUncleanException("FFmpeg exit code was " + exitCode); - } - } catch (InterruptedException e) { - LOG.error("Thread interrupted while waiting for FFmpeg to terminate"); - Thread.currentThread().interrupt(); - } catch (ExecutionException | ParseException | PlaylistException | JAXBException e) { - LOG.error("Couldn't start FFmpeg process for stream download", e); - } - return this; - } - - @Override - public void stop() { - if (ffmpeg != null && ffmpeg.isAlive()) { - OutputStream ffmpegStdIn = ffmpeg.getOutputStream(); - try { - ffmpegStdIn.write("q".getBytes(StandardCharsets.UTF_8)); - ffmpegStdIn.flush(); - ffmpegStdIn.close(); - } catch (IOException e) { - LOG.error("Couldn't terminate FFmpeg by sending 'q'", e); - ffmpeg.destroy(); - } - } - } - - @Override - public Model getModel() { - return model; - } - - @Override - public void postProcess(Recording recording) { - // nothing to here for now - } - - @Override - public File getTarget() { - return targetFile; - } - - @Override - public String getPath(Model model) { - String absolutePath = getTarget().getAbsolutePath(); - String recordingsDir = Config.getInstance().getSettings().recordingsDir; - String relativePath = absolutePath.replaceFirst(Pattern.quote(recordingsDir), ""); - return relativePath; - } - - @Override - protected void internalStop() { - stop(); - } - - @Override - public boolean isSingleFile() { - return true; - } - - @Override - public long getSizeInByte() { - return getTarget().length(); - } - - protected void createTargetDirectory() throws IOException { - // TODO Auto-generated method stub - - } - - @Override - protected void execute(SegmentDownload segmentDownload) { - // TODO Auto-generated method stub - - } - - @Override - protected OutputStream getSegmentOutputStream(Segment segment) throws IOException { - // TODO Auto-generated method stub - return null; - } - - @Override - public void finalizeDownload() { - // TODO Auto-generated method stub - - } - -}