From f9b09775e31ad1e8f27261c9b545dd0977cd4b7e Mon Sep 17 00:00:00 2001 From: 0xb00bface <0xboobface@gmail.com> Date: Mon, 21 Dec 2020 23:10:56 +0100 Subject: [PATCH] Improved robustness of live previews --- .../ctbrec/ui/controls/StreamPreview.java | 39 +++++++++++-------- .../main/java/ctbrec/ui/tabs/ThumbCell.java | 39 +++++++++++++++++-- 2 files changed, 58 insertions(+), 20 deletions(-) diff --git a/client/src/main/java/ctbrec/ui/controls/StreamPreview.java b/client/src/main/java/ctbrec/ui/controls/StreamPreview.java index 74cbe074..9b1eb20e 100644 --- a/client/src/main/java/ctbrec/ui/controls/StreamPreview.java +++ b/client/src/main/java/ctbrec/ui/controls/StreamPreview.java @@ -27,7 +27,7 @@ import javafx.scene.media.MediaPlayer; import javafx.scene.media.MediaView; public class StreamPreview extends StackPane { - private static final transient Logger LOG = LoggerFactory.getLogger(StreamPreview.class); + private static final Logger LOG = LoggerFactory.getLogger(StreamPreview.class); private ImageView preview = new ImageView(); private MediaView videoPreview; @@ -35,7 +35,8 @@ public class StreamPreview extends StackPane { private Media video; private ProgressIndicator progressIndicator; private static ExecutorService executor = Executors.newSingleThreadExecutor(); - private static Future future; + private Future future; + private volatile boolean running = false; public StreamPreview() { videoPreview = new MediaView(); @@ -63,20 +64,24 @@ public class StreamPreview extends StackPane { } public void startStream(Model model) { - Platform.runLater(() -> { - progressIndicator.setVisible(true); - if(model.getPreview() != null) { - try { - videoPreview.setVisible(false); - Image img = new Image(model.getPreview(), true); - preview.setImage(img); - double aspect = img.getWidth() / img.getHeight(); - double w = Config.getInstance().getSettings().thumbWidth; - double h = w / aspect; - resizeTo(w, h); - } catch (Exception e) {} - } - }); + if (running) { + return; + } + running = true; + LOG.debug("Starting preview stream for model {}", model); + progressIndicator.setVisible(true); + if(model.getPreview() != null) { + try { + videoPreview.setVisible(false); + Image img = new Image(model.getPreview(), true); + preview.setImage(img); + double aspect = img.getWidth() / img.getHeight(); + double w = Config.getInstance().getSettings().thumbWidth; + double h = w / aspect; + resizeTo(w, h); + } catch (Exception e) {} + } + if(future != null && !future.isDone()) { future.cancel(true); } @@ -85,6 +90,7 @@ public class StreamPreview extends StackPane { List sources = model.getStreamSources(); Collections.sort(sources); StreamSource best = sources.get(0); + LOG.debug("StreamSource {}", best); checkInterrupt(); LOG.debug("Preview url for {} is {}", model.getName(), best.getMediaPlaylistUrl()); video = new Media(best.getMediaPlaylistUrl()); @@ -148,6 +154,7 @@ public class StreamPreview extends StackPane { } public void stop() { + running = false; MediaPlayer old = videoPlayer; Future oldFuture = future; new Thread(() -> { diff --git a/client/src/main/java/ctbrec/ui/tabs/ThumbCell.java b/client/src/main/java/ctbrec/ui/tabs/ThumbCell.java index 1026b708..aa2df6ee 100644 --- a/client/src/main/java/ctbrec/ui/tabs/ThumbCell.java +++ b/client/src/main/java/ctbrec/ui/tabs/ThumbCell.java @@ -87,6 +87,7 @@ public class ThumbCell extends StackPane { private Recorder recorder; private Circle recordingIndicator; private PausedIndicator pausedIndicator; + private StackPane previewTrigger; private int index = 0; ContextMenu popup; private static final Color colorNormal = Color.BLACK; @@ -105,6 +106,7 @@ public class ThumbCell extends StackPane { .maximumSize(10000) .build(CacheLoader.from(ThumbCell::getStreamResolution)); private ThumbOverviewTab parent; + private CompletableFuture startPreview; public ThumbCell(ThumbOverviewTab parent, Model model, Recorder recorder, double aspectRatio) { this.parent = parent; @@ -231,7 +233,7 @@ public class ThumbCell extends StackPane { private Node createPreviewTrigger() { int s = 32; - StackPane previewTrigger = new StackPane(); + previewTrigger = new StackPane(); previewTrigger.setStyle("-fx-background-color: white;"); previewTrigger.setOpacity(.8); previewTrigger.setMaxSize(s, s); @@ -247,11 +249,36 @@ public class ThumbCell extends StackPane { previewTrigger.setClip(clip); StackPane.setAlignment(previewTrigger, Pos.BOTTOM_LEFT); StackPane.setMargin(previewTrigger, new Insets(0, 0, 24, 4)); - previewTrigger.setOnMouseEntered(evt -> setPreviewVisible(previewTrigger, true)); - previewTrigger.setOnMouseExited(evt -> setPreviewVisible(previewTrigger, false)); + previewTrigger.setOnMouseEntered(evt -> startPreview()); + previewTrigger.setOnMouseExited(evt -> stopPreview()); return previewTrigger; } + private void stopPreview() { + if (startPreview != null) { + startPreview.cancel(true); + } + setPreviewVisible(previewTrigger, false); + } + + private void startPreview() { + previewTrigger.setCursor(Cursor.HAND); + startPreview = CompletableFuture.supplyAsync(() -> { + try { + Thread.sleep(500); + return true; + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return false; + } + }).whenComplete((result, exception) -> { + startPreview = null; + if (result.booleanValue()) { + setPreviewVisible(previewTrigger, true); + } + }); + } + private void setPreviewVisible(Node previewTrigger, boolean visible) { parent.suspendUpdates(visible); iv.setVisible(!visible); @@ -260,7 +287,11 @@ public class ThumbCell extends StackPane { name.setVisible(!visible); nameBackground.setVisible(!visible); streamPreview.setVisible(visible); - streamPreview.startStream(model); + if (visible) { + streamPreview.startStream(model); + } else { + streamPreview.stop(); + } recordingIndicator.setVisible(!visible); pausedIndicator.setVisible(!visible); if (!visible) {