From 5a5d75264c6aa003dd8a4a3a72f79f528da50273 Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sat, 28 Mar 2020 16:17:20 -0400 Subject: [PATCH 01/29] Beginnings of video player Progress on gurkenlabs#291 --- .../litiengine/video/VideoManager.java | 231 +++++++++++++ .../litiengine/video/VideoManagerImpl.java | 303 ++++++++++++++++++ .../litiengine/video/VideoPlayer.java | 51 +++ 3 files changed, 585 insertions(+) create mode 100644 src/de/gurkenlabs/litiengine/video/VideoManager.java create mode 100644 src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java create mode 100644 src/de/gurkenlabs/litiengine/video/VideoPlayer.java diff --git a/src/de/gurkenlabs/litiengine/video/VideoManager.java b/src/de/gurkenlabs/litiengine/video/VideoManager.java new file mode 100644 index 000000000..36cd37cb3 --- /dev/null +++ b/src/de/gurkenlabs/litiengine/video/VideoManager.java @@ -0,0 +1,231 @@ +package de.gurkenlabs.litiengine.video; + +import java.time.Duration; +import java.util.logging.Level; +import java.util.logging.Logger; + +/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * + * Do not import anything from javafx into this class! + * + * Not all JREs contain javafx. Some JREs may throw + * java.lang.Error upon loading of this class if + * a javafx import exists but the library is missing! + * + *!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ + +public final class VideoManager implements VideoPlayer { + + private static final Logger log = Logger.getLogger(VideoManager.class.getName()); + private static VideoPlayer impl; + + private VideoManager() { + throw new UnsupportedOperationException(); + }; + + /** + * Initializes the media player + * + * @throws IllegalStateException if the media player has already been initialized + * + * @throws NoClassDefFoundError if JavaFX is not installed (you can catch this + * if you want to handle JavaFX not being installed) + * + * @throws SecurityException if a security manager exists and it denies access to + * the classloader which loaded this class + * + * @throws LinkageError if the linkage otherwise fails (It is highly discouraged to + * catch this) + */ + public void initialize(String[] args) throws NoClassDefFoundError { + + if(impl != null) { + throw new IllegalStateException("Video player already initialized!"); + } + + try { + ClassLoader classLoader = this.getClass().getClassLoader(); + Class.forName("javafx.scene.media.MediaPlayer", false, classLoader); + classLoader.setPackageAssertionStatus("de.gurkenlabs.litiengine.video", true); + } catch (ClassNotFoundException e) { + NoClassDefFoundError err = new NoClassDefFoundError("JavaFX is not installed!"); + err.initCause(e); + log.log(Level.SEVERE, err, () -> err.getMessage()); + throw err; + } catch (LinkageError e) { + log.log(Level.SEVERE, e, () -> e.getMessage()); + throw e; + } catch (SecurityException e) { + log.log(Level.SEVERE, e, () -> e.getMessage()); + throw e; + } + + impl = new VideoManagerImpl(); + + } + + @Override + public boolean isStatusUnknown() { + return impl.isStatusUnknown(); + } + + @Override + public boolean isReady() { + return impl.isReady(); + } + + + @Override + public boolean isErrored() { + return impl.isErrored(); + } + + @Override + public boolean isPlaying() { + return impl.isPlaying(); + } + + @Override + public boolean isPaused() { + return impl.isPaused(); + } + + @Override + public boolean isBuffering() { + return impl.isBuffering(); + } + + @Override + public boolean isStopped() { + return impl.isStopped(); + } + + @Override + public Status getStatus() { + return impl.getStatus(); + } + + @Override + public void dispose() { + impl.dispose(); + } + + @Override + public Throwable getError() { + return impl.getError(); + } + + @Override + public double getBalance() { + return impl.getBalance(); + } + + @Override + public Duration getBufferProgressTime() { + return impl.getBufferProgressTime(); + } + + @Override + public int getCurrentCount() { + return impl.getCurrentCount(); + } + + @Override + public double getCurrentRate() { + return impl.getCurrentRate(); + } + + @Override + public Duration getCurrentTime() { + return impl.getCurrentTime(); + } + + @Override + public Object getMedia() { + //TODO return Video resource + } + + @Override + public double getRate() { + return impl.getRate(); + } + + @Override + public Duration getStartTime() { + return impl.getStartTime(); + } + + @Override + public Duration getStopTime() { + return impl.getStopTime(); + } + + @Override + public Duration getTotalDuration() { + return impl.getTotalDuration(); + } + + @Override + public double getVolume() { + return impl.getVolume(); + } + + @Override + public void pause() { + impl.pause(); + } + + public void setVideo(VideoResource video) { + //TODO + } + + public void play(VideoResource video) { + //TODO + } + + @Override + public void play() { + impl.play(); + } + + @Override + public void seek(Duration seekTime) { + impl.seek(seekTime); + } + + @Override + public void setBalance(double value) { + impl.setBalance(value); + } + + @Override + public void setCycleCount(int value) { + impl.setCycleCount(value); + } + + @Override + public void setRate(double value) { + impl.setRate(value); + } + + @Override + public void setStartTime(Duration value) { + impl.setStartTime(value); + } + + @Override + public void setStopTime(Duration value) { + impl.setStopTime(value); + } + + @Override + public void setVolume(double value) { + impl.setVolume(value); + } + + @Override + public void stop() { + impl.stop(); + } + +} diff --git a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java new file mode 100644 index 000000000..8837a6b27 --- /dev/null +++ b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java @@ -0,0 +1,303 @@ +package de.gurkenlabs.litiengine.video; + +import static java.time.Duration.ZERO; +import static javafx.scene.media.MediaPlayer.Status.*; + +import javafx.embed.swing.JFXPanel; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.media.Media; +import javafx.scene.media.MediaException; +import javafx.scene.media.MediaPlayer; +import javafx.scene.media.MediaView; + +final class VideoManagerImpl implements VideoPlayer{ + + private static VideoManagerImpl INSTANCE; + + private JFXPanel panel = new JFXPanel(); + private Media media; + private MediaPlayer mediaPlayer; + private MediaView mediaView; + + { + assert INSTANCE == null; + INSTANCE = this; + } + + void setMedia(Media media) { + if(mediaPlayer != null) { + mediaPlayer.dispose(); + } + + this.mediaPlayer = new MediaPlayer(media); + this.media = media; + this.mediaView = new MediaView(mediaPlayer); + Group root = new Group(mediaView); + Scene scene = new Scene(root, media.getWidth(), media.getHeight()); + panel.setScene(scene); + } + + @Override + public boolean isStatusUnknown() { + if(playerValid()) { + return mediaPlayer.getStatus() == UNKNOWN; + } + return true; + } + + @Override + public boolean isReady() { + if(playerValid()) { + return mediaPlayer.getStatus() == READY; + } + return false; + } + + @Override + public boolean isPlaying() { + if(playerValid()) { + return mediaPlayer.getStatus() == PLAYING; + } + return false; + } + + @Override + public boolean isErrored() { + if(playerValid()) { + return mediaPlayer.getStatus() == HALTED; + } + return false; + } + + @Override + public boolean isPaused() { + if(playerValid()) { + return mediaPlayer.getStatus() == PAUSED; + } + return false; + } + + @Override + public boolean isBuffering() { + if(playerValid()) { + return mediaPlayer.getStatus() == STALLED; + } + return false; + } + + @Override + public boolean isStopped() { + if(playerValid()) { + return mediaPlayer.getStatus() == STOPPED; + } + return false; + } + + public VideoPlayer.Status getStatus() { + switch (mediaPlayer.getStatus()) { + case DISPOSED: + return Status.DISPOSED; + case HALTED: + return Status.ERRORED; + case PAUSED: + return Status.PAUSED; + case PLAYING: + return Status.PLAYING; + case READY: + return Status.READY; + case STALLED: + return Status.STALLED; + case STOPPED: + return Status.STOPPED; + default: + return Status.UNKNOWN; + } + } + + void play(Media media) { + setMedia(media); + play(); + } + + public void play() { + if(panel != null && playerValid() && media != null && mediaView != null) { + panel.setVisible(true); + mediaPlayer.play(); + } + } + + @Override + public void dispose() { + mediaPlayer.dispose(); + } + + @Override + public MediaException getError() { + if(playerValid()) { + return mediaPlayer.getError(); + } + return null; + } + + @Override + public double getBalance() { + if(playerValid()) { + return mediaPlayer.getBalance(); + } + return 0; + } + + @Override + public java.time.Duration getBufferProgressTime() { + if(playerValid()) { + return convertDuration(mediaPlayer.getBufferProgressTime()); + } + return ZERO; + } + + @Override + public int getCurrentCount() { + if(playerValid()) { + return mediaPlayer.getCurrentCount(); + } + return 0; + } + + @Override + public double getCurrentRate() { + if(playerValid()) { + return mediaPlayer.getCurrentRate(); + } + return 0; + } + + @Override + public java.time.Duration getCurrentTime() { + if(playerValid()) { + return convertDuration(mediaPlayer.getCurrentTime()); + } + return ZERO; + } + + @Override + public Media getMedia() { + return media; + } + + @Override + public double getRate() { + if(playerValid()) { + return mediaPlayer.getRate(); + } + return 0; + } + + @Override + public java.time.Duration getStartTime() { + if(playerValid()) { + return convertDuration(mediaPlayer.getStartTime()); + } + return ZERO; + } + + @Override + public java.time.Duration getStopTime() { + if(playerValid()) { + return convertDuration(mediaPlayer.getStopTime()); + } + return ZERO; + } + + @Override + public java.time.Duration getTotalDuration() { + if(playerValid()) { + return convertDuration(mediaPlayer.getTotalDuration()); + } + return ZERO; + } + + @Override + public double getVolume() { + if(playerValid()) { + return mediaPlayer.getVolume(); + } + return 0; + } + + @Override + public void pause() { + if(playerValid()) { + mediaPlayer.pause(); + } + } + + @Override + public void seek(java.time.Duration seekTime) { + if(playerValid()) { + mediaPlayer.seek(convertDuration(seekTime)); + } + } + + @Override + public void setBalance(double value) { + if(playerValid()) { + mediaPlayer.setBalance(value); + } + } + + @Override + public void setCycleCount(int value) { + if(playerValid()) { + mediaPlayer.setCycleCount(value); + } + } + + @Override + public void setRate(double value) { + if(playerValid()) { + mediaPlayer.setRate(value); + } + } + + @Override + public void setStartTime(java.time.Duration value) { + if(playerValid()) { + mediaPlayer.setStartTime(convertDuration(value)); + } + } + + @Override + public void setStopTime(java.time.Duration value) { + if(playerValid()) { + mediaPlayer.setStopTime(convertDuration(value)); + } + } + + @Override + public void setVolume(double value) { + if(playerValid()) { + mediaPlayer.setVolume(value); + } + } + + @Override + public void stop() { + if(playerValid()) { + mediaPlayer.stop(); + } + } + + private java.time.Duration convertDuration(javafx.util.Duration duration) { + return java.time.Duration.ofSeconds((long) duration.toSeconds()); + } + + private javafx.util.Duration convertDuration(java.time.Duration duration) { + return javafx.util.Duration.seconds((double)duration.getSeconds()); + } + + private boolean playerValid() { + return mediaPlayer != null; + } + +} diff --git a/src/de/gurkenlabs/litiengine/video/VideoPlayer.java b/src/de/gurkenlabs/litiengine/video/VideoPlayer.java new file mode 100644 index 000000000..0d6aca04d --- /dev/null +++ b/src/de/gurkenlabs/litiengine/video/VideoPlayer.java @@ -0,0 +1,51 @@ +package de.gurkenlabs.litiengine.video; + +import java.time.Duration; + +interface VideoPlayer { + void dispose(); + + boolean isStatusUnknown(); + boolean isReady(); + boolean isErrored(); + boolean isPlaying(); + boolean isPaused(); + boolean isBuffering(); + boolean isStopped(); + Status getStatus(); + + Throwable getError(); + double getBalance(); + Duration getBufferProgressTime(); + int getCurrentCount(); + double getCurrentRate(); + Duration getCurrentTime(); + Object getMedia(); + double getRate(); + Duration getStartTime(); + Duration getStopTime(); + Duration getTotalDuration(); + double getVolume(); + void pause(); + void play(); + void seek(Duration seekTime); + void setBalance(double value); + void setCycleCount(int value); + void setRate(double value); + void setStartTime(Duration value); + void setStopTime(Duration value); + void setVolume(double value); + void stop(); + + public static enum Status { + DISPOSED, + ERRORED, + PAUSED, + PLAYING, + READY, + STALLED, + STOPPED, + UNKNOWN + } + +} From 040423daf95fac83cb1308d2e91cd2aa56fb2adc Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sat, 28 Mar 2020 16:30:01 -0400 Subject: [PATCH 02/29] Video manager is no longer a singleton. Multiple videos should be able to play at the same time. --- .../litiengine/video/VideoManager.java | 47 +++++++++++++++---- .../litiengine/video/VideoManagerImpl.java | 7 --- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManager.java b/src/de/gurkenlabs/litiengine/video/VideoManager.java index 36cd37cb3..8a6898d63 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManager.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManager.java @@ -17,11 +17,43 @@ public final class VideoManager implements VideoPlayer { private static final Logger log = Logger.getLogger(VideoManager.class.getName()); - private static VideoPlayer impl; - private VideoManager() { - throw new UnsupportedOperationException(); - }; + private VideoPlayer impl; + + { + initialize(); + } + + /** + * Creates a new VideoManager + */ + VideoManager() {}; + + /** + * Creates a new VideoManager which load the + * specified video without playing it. + * + * @param video the video to load + */ + VideoManager(VideoResource video) { + setVideo(video); + } + + /** + * Creates a new VideoManager which will load the + * specified video. + * + * @param video the video to load + * @param play whether to immediately begin playing the video + */ + VideoManager(VideoResource video, boolean play) { + if(play) { + playVideo(video); + } + else { + setVideo(video); + } + } /** * Initializes the media player @@ -37,16 +69,15 @@ private VideoManager() { * @throws LinkageError if the linkage otherwise fails (It is highly discouraged to * catch this) */ - public void initialize(String[] args) throws NoClassDefFoundError { + public void initialize() throws NoClassDefFoundError { if(impl != null) { throw new IllegalStateException("Video player already initialized!"); } try { - ClassLoader classLoader = this.getClass().getClassLoader(); + ClassLoader classLoader = VideoManager.class.getClassLoader(); Class.forName("javafx.scene.media.MediaPlayer", false, classLoader); - classLoader.setPackageAssertionStatus("de.gurkenlabs.litiengine.video", true); } catch (ClassNotFoundException e) { NoClassDefFoundError err = new NoClassDefFoundError("JavaFX is not installed!"); err.initCause(e); @@ -142,7 +173,7 @@ public Duration getCurrentTime() { @Override public Object getMedia() { - //TODO return Video resource + //TODO return VideoResource } @Override diff --git a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java index 8837a6b27..6e18e3fc5 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java @@ -12,19 +12,12 @@ import javafx.scene.media.MediaView; final class VideoManagerImpl implements VideoPlayer{ - - private static VideoManagerImpl INSTANCE; private JFXPanel panel = new JFXPanel(); private Media media; private MediaPlayer mediaPlayer; private MediaView mediaView; - { - assert INSTANCE == null; - INSTANCE = this; - } - void setMedia(Media media) { if(mediaPlayer != null) { mediaPlayer.dispose(); From fb5db723b5557e0b01801a8342a08def5403aca8 Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sat, 28 Mar 2020 16:55:52 -0400 Subject: [PATCH 03/29] Make VideoManager a GuiComponent --- .../litiengine/video/VideoManager.java | 16 ++++++++++++++-- .../litiengine/video/VideoManagerImpl.java | 6 ++++++ .../gurkenlabs/litiengine/video/VideoPlayer.java | 3 +++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManager.java b/src/de/gurkenlabs/litiengine/video/VideoManager.java index 8a6898d63..2873625b8 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManager.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManager.java @@ -1,9 +1,12 @@ package de.gurkenlabs.litiengine.video; +import java.awt.Graphics2D; import java.time.Duration; import java.util.logging.Level; import java.util.logging.Logger; +import de.gurkenlabs.litiengine.gui.GuiComponent; + /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * * Do not import anything from javafx into this class! @@ -14,7 +17,7 @@ * *!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ -public final class VideoManager implements VideoPlayer { +public final class VideoManager extends GuiComponent implements VideoPlayer { private static final Logger log = Logger.getLogger(VideoManager.class.getName()); @@ -27,7 +30,9 @@ public final class VideoManager implements VideoPlayer { /** * Creates a new VideoManager */ - VideoManager() {}; + VideoManager() { + super(0,0); + }; /** * Creates a new VideoManager which load the @@ -36,6 +41,7 @@ public final class VideoManager implements VideoPlayer { * @param video the video to load */ VideoManager(VideoResource video) { + super(0,0); setVideo(video); } @@ -47,6 +53,7 @@ public final class VideoManager implements VideoPlayer { * @param play whether to immediately begin playing the video */ VideoManager(VideoResource video, boolean play) { + super(0,0); if(play) { playVideo(video); } @@ -259,4 +266,9 @@ public void stop() { impl.stop(); } + @Override + public void render(Graphics2D g) { + impl.getPanel().update(g); + } + } diff --git a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java index 6e18e3fc5..26506d8a4 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java @@ -3,6 +3,8 @@ import static java.time.Duration.ZERO; import static javafx.scene.media.MediaPlayer.Status.*; +import javax.swing.JComponent; + import javafx.embed.swing.JFXPanel; import javafx.scene.Group; import javafx.scene.Scene; @@ -281,6 +283,10 @@ public void stop() { } } + JComponent getPanel() { + return panel; + } + private java.time.Duration convertDuration(javafx.util.Duration duration) { return java.time.Duration.ofSeconds((long) duration.toSeconds()); } diff --git a/src/de/gurkenlabs/litiengine/video/VideoPlayer.java b/src/de/gurkenlabs/litiengine/video/VideoPlayer.java index 0d6aca04d..0844125bb 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoPlayer.java +++ b/src/de/gurkenlabs/litiengine/video/VideoPlayer.java @@ -2,6 +2,8 @@ import java.time.Duration; +import javax.swing.JComponent; + interface VideoPlayer { void dispose(); @@ -36,6 +38,7 @@ interface VideoPlayer { void setStopTime(Duration value); void setVolume(double value); void stop(); + JComponent getPanel(); public static enum Status { DISPOSED, From f625f86714386993b6a2987f3dafd2b85afc4901 Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sat, 28 Mar 2020 16:59:33 -0400 Subject: [PATCH 04/29] Make javafx verify code stop running when the library has loaded --- .../litiengine/video/VideoManager.java | 86 ++++++++++++------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManager.java b/src/de/gurkenlabs/litiengine/video/VideoManager.java index 2873625b8..874858d76 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManager.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManager.java @@ -11,26 +11,54 @@ * * Do not import anything from javafx into this class! * - * Not all JREs contain javafx. Some JREs may throw - * java.lang.Error upon loading of this class if - * a javafx import exists but the library is missing! + * Not all JREs contain javafx. Java will throw a + * java.lang.Error if we accidentally try to load a + * javafx class if the library doesn't exist! * *!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ public final class VideoManager extends GuiComponent implements VideoPlayer { private static final Logger log = Logger.getLogger(VideoManager.class.getName()); + private static boolean checked = false; private VideoPlayer impl; { + if(!checked) { + try { + ClassLoader classLoader = VideoManager.class.getClassLoader(); + Class.forName("javafx.scene.media.MediaPlayer", false, classLoader); + } catch (ClassNotFoundException e) { + NoClassDefFoundError err = new NoClassDefFoundError("JavaFX is not installed!"); + err.initCause(e); + log.log(Level.SEVERE, err, () -> err.getMessage()); + throw err; + } catch (LinkageError e) { + log.log(Level.SEVERE, e, () -> e.getMessage()); + throw e; + } catch (SecurityException e) { + log.log(Level.SEVERE, e, () -> e.getMessage()); + throw e; + } + } + checked = true; initialize(); } /** * Creates a new VideoManager + * + * @throws NoClassDefFoundError if JavaFX is not installed (you can catch this + * if you want to handle JavaFX not being installed) + * + * @throws SecurityException if a security manager exists and it denies access to + * the classloader which loaded this class + * + * @throws LinkageError if the linkage otherwise fails (It is highly discouraged to + * catch this) */ - VideoManager() { + VideoManager() throws NoClassDefFoundError { super(0,0); }; @@ -39,8 +67,17 @@ public final class VideoManager extends GuiComponent implements VideoPlayer { * specified video without playing it. * * @param video the video to load + * + * @throws NoClassDefFoundError if JavaFX is not installed (you can catch this + * if you want to handle JavaFX not being installed) + * + * @throws SecurityException if a security manager exists and it denies access to + * the classloader which loaded this class + * + * @throws LinkageError if the linkage otherwise fails (It is highly discouraged to + * catch this) */ - VideoManager(VideoResource video) { + VideoManager(VideoResource video) throws NoClassDefFoundError { super(0,0); setVideo(video); } @@ -51,8 +88,17 @@ public final class VideoManager extends GuiComponent implements VideoPlayer { * * @param video the video to load * @param play whether to immediately begin playing the video + * + * @throws NoClassDefFoundError if JavaFX is not installed (you can catch this + * if you want to handle JavaFX not being installed) + * + * @throws SecurityException if a security manager exists and it denies access to + * the classloader which loaded this class + * + * @throws LinkageError if the linkage otherwise fails (It is highly discouraged to + * catch this) */ - VideoManager(VideoResource video, boolean play) { + VideoManager(VideoResource video, boolean play) throws NoClassDefFoundError { super(0,0); if(play) { playVideo(video); @@ -66,38 +112,13 @@ public final class VideoManager extends GuiComponent implements VideoPlayer { * Initializes the media player * * @throws IllegalStateException if the media player has already been initialized - * - * @throws NoClassDefFoundError if JavaFX is not installed (you can catch this - * if you want to handle JavaFX not being installed) - * - * @throws SecurityException if a security manager exists and it denies access to - * the classloader which loaded this class - * - * @throws LinkageError if the linkage otherwise fails (It is highly discouraged to - * catch this) */ - public void initialize() throws NoClassDefFoundError { + private void initialize() { if(impl != null) { throw new IllegalStateException("Video player already initialized!"); } - try { - ClassLoader classLoader = VideoManager.class.getClassLoader(); - Class.forName("javafx.scene.media.MediaPlayer", false, classLoader); - } catch (ClassNotFoundException e) { - NoClassDefFoundError err = new NoClassDefFoundError("JavaFX is not installed!"); - err.initCause(e); - log.log(Level.SEVERE, err, () -> err.getMessage()); - throw err; - } catch (LinkageError e) { - log.log(Level.SEVERE, e, () -> e.getMessage()); - throw e; - } catch (SecurityException e) { - log.log(Level.SEVERE, e, () -> e.getMessage()); - throw e; - } - impl = new VideoManagerImpl(); } @@ -111,7 +132,6 @@ public boolean isStatusUnknown() { public boolean isReady() { return impl.isReady(); } - @Override public boolean isErrored() { From e31e8404b72c712ab3cbc4fcde2702a6a56ae08e Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sat, 28 Mar 2020 17:26:00 -0400 Subject: [PATCH 05/29] Don't reduce visibility of getPanel() --- src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java index 26506d8a4..361c15f74 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java @@ -283,7 +283,7 @@ public void stop() { } } - JComponent getPanel() { + public JComponent getPanel() { return panel; } From 7ea07dd1f171f9c3bf312a44ad600914c79431b4 Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sat, 28 Mar 2020 19:08:35 -0400 Subject: [PATCH 06/29] Don't import from javafx --- .../gurkenlabs/litiengine/video/VideoManager.java | 6 ++++++ .../gurkenlabs/litiengine/video/VideoPlayer.java | 15 +++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManager.java b/src/de/gurkenlabs/litiengine/video/VideoManager.java index 874858d76..7e3309ae7 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManager.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManager.java @@ -289,6 +289,12 @@ public void stop() { @Override public void render(Graphics2D g) { impl.getPanel().update(g); + + @Override + public Container getPanel() { + return impl.getPanel(); + } + } } diff --git a/src/de/gurkenlabs/litiengine/video/VideoPlayer.java b/src/de/gurkenlabs/litiengine/video/VideoPlayer.java index 0844125bb..8f8f23eff 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoPlayer.java +++ b/src/de/gurkenlabs/litiengine/video/VideoPlayer.java @@ -1,8 +1,19 @@ package de.gurkenlabs.litiengine.video; +import java.awt.Container; import java.time.Duration; -import javax.swing.JComponent; +import de.gurkenlabs.litiengine.resources.VideoResource; + +/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * + * Do not import anything from javafx into this interface! + * + * Not all JREs contain javafx. Java will throw a + * java.lang.Error if we accidentally try to load a + * javafx class if the library doesn't exist! + * + *!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ interface VideoPlayer { void dispose(); @@ -38,7 +49,7 @@ interface VideoPlayer { void setStopTime(Duration value); void setVolume(double value); void stop(); - JComponent getPanel(); + Container getPanel(); public static enum Status { DISPOSED, From be6cebd3186b794a3e4e8d0dee4849d5a399d132 Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sat, 28 Mar 2020 19:10:39 -0400 Subject: [PATCH 07/29] Make VideoManagers a resource --- .../litiengine/resources/Resources.java | 14 +++++ .../litiengine/resources/VideoResource.java | 22 +++++++ .../litiengine/resources/Videos.java | 26 +++++++++ .../litiengine/video/VideoManager.java | 58 +++++++++++++++---- .../litiengine/video/VideoManagerImpl.java | 54 +++++++++++------ .../litiengine/video/VideoPlayer.java | 6 +- 6 files changed, 149 insertions(+), 31 deletions(-) create mode 100644 src/de/gurkenlabs/litiengine/resources/VideoResource.java create mode 100644 src/de/gurkenlabs/litiengine/resources/Videos.java diff --git a/src/de/gurkenlabs/litiengine/resources/Resources.java b/src/de/gurkenlabs/litiengine/resources/Resources.java index c3188b4ad..bb4bae00b 100644 --- a/src/de/gurkenlabs/litiengine/resources/Resources.java +++ b/src/de/gurkenlabs/litiengine/resources/Resources.java @@ -41,6 +41,7 @@ *
  • (localizable) strings
  • *
  • spritesheets
  • *
  • sounds
  • + *
  • videos
  • * * * @see ResourcesContainer @@ -55,6 +56,7 @@ public final class Resources { private static Images images = new Images(); private static Spritesheets spritesheets = new Spritesheets(); private static Blueprints blueprints = new Blueprints(); + private static Videos videos = new Videos(); private Resources() { throw new UnsupportedOperationException(); @@ -148,6 +150,17 @@ public static Spritesheets spritesheets() { public static Blueprints blueprints() { return blueprints; } + + /** + * Gets the container that manages VideoManager resources. + * + * @return The VideoManager resource container. + * + * @see VideoManager + */ + public static Videos videos() { + return videos; + } /** * Load Spritesheets, Tilesets and Maps from a game resource file created with the utiLITI editor. @@ -332,6 +345,7 @@ public static void clearAll() { tilesets().clear(); images().clear(); spritesheets().clear(); + videos().clear(); } public static URL getLocation(String name) { diff --git a/src/de/gurkenlabs/litiengine/resources/VideoResource.java b/src/de/gurkenlabs/litiengine/resources/VideoResource.java new file mode 100644 index 000000000..1effb3165 --- /dev/null +++ b/src/de/gurkenlabs/litiengine/resources/VideoResource.java @@ -0,0 +1,22 @@ +package de.gurkenlabs.litiengine.resources; + +import java.net.URI; + +public class VideoResource extends NamedResource { + + private final String uri; + + public VideoResource(String uri, String name) { + this.uri = uri; + setName(name); + } + + public VideoResource(URI uri, String name) { + this(uri.toString(), name); + } + + public String getURI() { + return uri; + } + +} diff --git a/src/de/gurkenlabs/litiengine/resources/Videos.java b/src/de/gurkenlabs/litiengine/resources/Videos.java new file mode 100644 index 000000000..5e6c21640 --- /dev/null +++ b/src/de/gurkenlabs/litiengine/resources/Videos.java @@ -0,0 +1,26 @@ +package de.gurkenlabs.litiengine.resources; + +import java.net.URL; + +import de.gurkenlabs.litiengine.video.VideoManager; + +public class Videos extends ResourcesContainer{ + + Videos(){} + + public VideoManager load(VideoResource video) throws NoClassDefFoundError { + return load(video, false); + } + + public VideoManager load(VideoResource video, boolean play) throws NoClassDefFoundError { + VideoManager videoManager = new VideoManager(video, play); + this.add(video.getName(), videoManager); + return videoManager; + } + + @Override + protected VideoManager load(URL resourceName) throws Exception, NoClassDefFoundError { + return new VideoManager(resourceName); + } + +} diff --git a/src/de/gurkenlabs/litiengine/video/VideoManager.java b/src/de/gurkenlabs/litiengine/video/VideoManager.java index 7e3309ae7..e884a336d 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManager.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManager.java @@ -1,11 +1,17 @@ package de.gurkenlabs.litiengine.video; +import java.awt.Container; import java.awt.Graphics2D; +import java.io.IOException; +import java.net.URL; import java.time.Duration; import java.util.logging.Level; import java.util.logging.Logger; +import javax.net.ssl.SSLHandshakeException; + import de.gurkenlabs.litiengine.gui.GuiComponent; +import de.gurkenlabs.litiengine.resources.VideoResource; /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * @@ -22,6 +28,8 @@ public final class VideoManager extends GuiComponent implements VideoPlayer { private static final Logger log = Logger.getLogger(VideoManager.class.getName()); private static boolean checked = false; + public static boolean allowNetworkConnections = false; + private VideoPlayer impl; { @@ -58,7 +66,7 @@ public final class VideoManager extends GuiComponent implements VideoPlayer { * @throws LinkageError if the linkage otherwise fails (It is highly discouraged to * catch this) */ - VideoManager() throws NoClassDefFoundError { + public VideoManager() throws NoClassDefFoundError { super(0,0); }; @@ -77,7 +85,7 @@ public final class VideoManager extends GuiComponent implements VideoPlayer { * @throws LinkageError if the linkage otherwise fails (It is highly discouraged to * catch this) */ - VideoManager(VideoResource video) throws NoClassDefFoundError { + public VideoManager(VideoResource video) throws NoClassDefFoundError { super(0,0); setVideo(video); } @@ -98,16 +106,38 @@ public final class VideoManager extends GuiComponent implements VideoPlayer { * @throws LinkageError if the linkage otherwise fails (It is highly discouraged to * catch this) */ - VideoManager(VideoResource video, boolean play) throws NoClassDefFoundError { + public VideoManager(VideoResource video, boolean play) throws NoClassDefFoundError { super(0,0); if(play) { - playVideo(video); + play(video); } else { setVideo(video); } } + public VideoManager(URL url) throws NoClassDefFoundError, IOException { + this(url, false); + } + + public VideoManager(URL url, boolean play) throws NoClassDefFoundError, IOException { + super(0,0); + if(url.getProtocol().startsWith("http")) { + if(!allowNetworkConnections) { + throw new IOException("Network access disallowed"); + } + if(url.getProtocol().equals("http")) { + throw new SSLHandshakeException("Insecure protocol: http. Use https"); + } + } + if(play) { + play(url); + } + else { + setVideo(url); + } + } + /** * Initializes the media player * @@ -198,11 +228,6 @@ public Duration getCurrentTime() { return impl.getCurrentTime(); } - @Override - public Object getMedia() { - //TODO return VideoResource - } - @Override public double getRate() { return impl.getRate(); @@ -234,11 +259,11 @@ public void pause() { } public void setVideo(VideoResource video) { - //TODO + impl.setVideo(video); } public void play(VideoResource video) { - //TODO + impl.play(video); } @Override @@ -288,13 +313,22 @@ public void stop() { @Override public void render(Graphics2D g) { - impl.getPanel().update(g); + getPanel().update(g); + } @Override public Container getPanel() { return impl.getPanel(); } + @Override + public void setVideo(URL url) { + impl.setVideo(url); + } + + @Override + public void play(URL url) { + impl.play(url); } } diff --git a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java index 361c15f74..4bbb9175f 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java @@ -3,8 +3,11 @@ import static java.time.Duration.ZERO; import static javafx.scene.media.MediaPlayer.Status.*; +import java.net.URL; + import javax.swing.JComponent; +import de.gurkenlabs.litiengine.resources.VideoResource; import javafx.embed.swing.JFXPanel; import javafx.scene.Group; import javafx.scene.Scene; @@ -19,8 +22,35 @@ final class VideoManagerImpl implements VideoPlayer{ private Media media; private MediaPlayer mediaPlayer; private MediaView mediaView; + + @Override + public void setVideo(VideoResource video) { + setMedia(new Media(video.getURI())); + } + + @Override + public void play(VideoResource video) { + play(new Media(video.getURI())); + } + + @Override + public void setVideo(URL url) { + setMedia(new Media(url.toString())); + } + + @Override + public void play(URL url) { + play(new Media(url.toString())); + } + + public void play() { + if(panel != null && playerValid() && media != null && mediaView != null) { + panel.setVisible(true); + mediaPlayer.play(); + } + } - void setMedia(Media media) { + private void setMedia(Media media) { if(mediaPlayer != null) { mediaPlayer.dispose(); } @@ -33,6 +63,11 @@ void setMedia(Media media) { panel.setScene(scene); } + private void play(Media media) { + setMedia(media); + play(); + } + @Override public boolean isStatusUnknown() { if(playerValid()) { @@ -109,18 +144,6 @@ public VideoPlayer.Status getStatus() { return Status.UNKNOWN; } } - - void play(Media media) { - setMedia(media); - play(); - } - - public void play() { - if(panel != null && playerValid() && media != null && mediaView != null) { - panel.setVisible(true); - mediaPlayer.play(); - } - } @Override public void dispose() { @@ -175,11 +198,6 @@ public java.time.Duration getCurrentTime() { return ZERO; } - @Override - public Media getMedia() { - return media; - } - @Override public double getRate() { if(playerValid()) { diff --git a/src/de/gurkenlabs/litiengine/video/VideoPlayer.java b/src/de/gurkenlabs/litiengine/video/VideoPlayer.java index 8f8f23eff..91083fd4c 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoPlayer.java +++ b/src/de/gurkenlabs/litiengine/video/VideoPlayer.java @@ -1,6 +1,7 @@ package de.gurkenlabs.litiengine.video; import java.awt.Container; +import java.net.URL; import java.time.Duration; import de.gurkenlabs.litiengine.resources.VideoResource; @@ -33,13 +34,16 @@ interface VideoPlayer { int getCurrentCount(); double getCurrentRate(); Duration getCurrentTime(); - Object getMedia(); double getRate(); Duration getStartTime(); Duration getStopTime(); Duration getTotalDuration(); double getVolume(); void pause(); + void setVideo(VideoResource video); + void setVideo(URL url); + void play(VideoResource video); + void play(URL url); void play(); void seek(Duration seekTime); void setBalance(double value); From 915ae4f1baa6ad6dc281c62fa023030d62399bfb Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sun, 29 Mar 2020 10:52:36 -0400 Subject: [PATCH 08/29] Fix deadlock --- .../litiengine/video/VideoManagerImpl.java | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java index 4bbb9175f..7243323e6 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java @@ -8,6 +8,7 @@ import javax.swing.JComponent; import de.gurkenlabs.litiengine.resources.VideoResource; +import javafx.application.Platform; import javafx.embed.swing.JFXPanel; import javafx.scene.Group; import javafx.scene.Scene; @@ -51,16 +52,18 @@ public void play() { } private void setMedia(Media media) { - if(mediaPlayer != null) { - mediaPlayer.dispose(); - } - - this.mediaPlayer = new MediaPlayer(media); - this.media = media; - this.mediaView = new MediaView(mediaPlayer); - Group root = new Group(mediaView); - Scene scene = new Scene(root, media.getWidth(), media.getHeight()); - panel.setScene(scene); + Platform.runLater(() -> { + if(mediaPlayer != null) { + mediaPlayer.dispose(); + } + + this.mediaPlayer = new MediaPlayer(media); + this.media = media; + this.mediaView = new MediaView(mediaPlayer); + Group root = new Group(mediaView); + Scene scene = new Scene(root, media.getWidth(), media.getHeight()); + panel.setScene(scene); + }); } private void play(Media media) { From afbd82b92d5e8175a3ca68309e2227dc79146fcf Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sun, 29 Mar 2020 11:08:29 -0400 Subject: [PATCH 09/29] Fix more threading issues --- .../litiengine/video/VideoManagerImpl.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java index 7243323e6..5f3c18691 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java @@ -19,10 +19,9 @@ final class VideoManagerImpl implements VideoPlayer{ - private JFXPanel panel = new JFXPanel(); - private Media media; - private MediaPlayer mediaPlayer; - private MediaView mediaView; + private volatile JFXPanel panel = new JFXPanel(); + private volatile MediaPlayer mediaPlayer; + private volatile MediaView mediaView; @Override public void setVideo(VideoResource video) { @@ -45,20 +44,19 @@ public void play(URL url) { } public void play() { - if(panel != null && playerValid() && media != null && mediaView != null) { + if(playerValid()) { panel.setVisible(true); mediaPlayer.play(); } } - private void setMedia(Media media) { + private synchronized void setMedia(Media media) { Platform.runLater(() -> { if(mediaPlayer != null) { mediaPlayer.dispose(); } this.mediaPlayer = new MediaPlayer(media); - this.media = media; this.mediaView = new MediaView(mediaPlayer); Group root = new Group(mediaView); Scene scene = new Scene(root, media.getWidth(), media.getHeight()); @@ -66,9 +64,11 @@ private void setMedia(Media media) { }); } - private void play(Media media) { + private synchronized void play(Media media) { setMedia(media); - play(); + Platform.runLater(() -> { + play(); + }); } @Override From b81b2efc2b6b88befbbfb4acef0818a871365086 Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sun, 29 Mar 2020 11:24:35 -0400 Subject: [PATCH 10/29] Don't need to store mediaPlayer --- .../litiengine/video/VideoManagerImpl.java | 79 ++++++++++--------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java index 5f3c18691..5947019de 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java @@ -20,7 +20,6 @@ final class VideoManagerImpl implements VideoPlayer{ private volatile JFXPanel panel = new JFXPanel(); - private volatile MediaPlayer mediaPlayer; private volatile MediaView mediaView; @Override @@ -46,20 +45,21 @@ public void play(URL url) { public void play() { if(playerValid()) { panel.setVisible(true); - mediaPlayer.play(); + getPlayer().play(); } } private synchronized void setMedia(Media media) { Platform.runLater(() -> { - if(mediaPlayer != null) { - mediaPlayer.dispose(); + final MediaPlayer player = getPlayer(); + if(player != null) { + player.dispose(); } - this.mediaPlayer = new MediaPlayer(media); - this.mediaView = new MediaView(mediaPlayer); + this.mediaView = new MediaView(new MediaPlayer(media)); Group root = new Group(mediaView); Scene scene = new Scene(root, media.getWidth(), media.getHeight()); + mediaView.autosize(); panel.setScene(scene); }); } @@ -74,7 +74,7 @@ private synchronized void play(Media media) { @Override public boolean isStatusUnknown() { if(playerValid()) { - return mediaPlayer.getStatus() == UNKNOWN; + return getPlayer().getStatus() == UNKNOWN; } return true; } @@ -82,7 +82,7 @@ public boolean isStatusUnknown() { @Override public boolean isReady() { if(playerValid()) { - return mediaPlayer.getStatus() == READY; + return getPlayer().getStatus() == READY; } return false; } @@ -90,7 +90,7 @@ public boolean isReady() { @Override public boolean isPlaying() { if(playerValid()) { - return mediaPlayer.getStatus() == PLAYING; + return getPlayer().getStatus() == PLAYING; } return false; } @@ -98,7 +98,7 @@ public boolean isPlaying() { @Override public boolean isErrored() { if(playerValid()) { - return mediaPlayer.getStatus() == HALTED; + return getPlayer().getStatus() == HALTED; } return false; } @@ -106,7 +106,7 @@ public boolean isErrored() { @Override public boolean isPaused() { if(playerValid()) { - return mediaPlayer.getStatus() == PAUSED; + return getPlayer().getStatus() == PAUSED; } return false; } @@ -114,7 +114,7 @@ public boolean isPaused() { @Override public boolean isBuffering() { if(playerValid()) { - return mediaPlayer.getStatus() == STALLED; + return getPlayer().getStatus() == STALLED; } return false; } @@ -122,13 +122,13 @@ public boolean isBuffering() { @Override public boolean isStopped() { if(playerValid()) { - return mediaPlayer.getStatus() == STOPPED; + return getPlayer().getStatus() == STOPPED; } return false; } public VideoPlayer.Status getStatus() { - switch (mediaPlayer.getStatus()) { + switch (getPlayer().getStatus()) { case DISPOSED: return Status.DISPOSED; case HALTED: @@ -150,13 +150,13 @@ public VideoPlayer.Status getStatus() { @Override public void dispose() { - mediaPlayer.dispose(); + getPlayer().dispose(); } @Override public MediaException getError() { if(playerValid()) { - return mediaPlayer.getError(); + return getPlayer().getError(); } return null; } @@ -164,7 +164,7 @@ public MediaException getError() { @Override public double getBalance() { if(playerValid()) { - return mediaPlayer.getBalance(); + return getPlayer().getBalance(); } return 0; } @@ -172,7 +172,7 @@ public double getBalance() { @Override public java.time.Duration getBufferProgressTime() { if(playerValid()) { - return convertDuration(mediaPlayer.getBufferProgressTime()); + return convertDuration(getPlayer().getBufferProgressTime()); } return ZERO; } @@ -180,7 +180,7 @@ public java.time.Duration getBufferProgressTime() { @Override public int getCurrentCount() { if(playerValid()) { - return mediaPlayer.getCurrentCount(); + return getPlayer().getCurrentCount(); } return 0; } @@ -188,7 +188,7 @@ public int getCurrentCount() { @Override public double getCurrentRate() { if(playerValid()) { - return mediaPlayer.getCurrentRate(); + return getPlayer().getCurrentRate(); } return 0; } @@ -196,7 +196,7 @@ public double getCurrentRate() { @Override public java.time.Duration getCurrentTime() { if(playerValid()) { - return convertDuration(mediaPlayer.getCurrentTime()); + return convertDuration(getPlayer().getCurrentTime()); } return ZERO; } @@ -204,7 +204,7 @@ public java.time.Duration getCurrentTime() { @Override public double getRate() { if(playerValid()) { - return mediaPlayer.getRate(); + return getPlayer().getRate(); } return 0; } @@ -212,7 +212,7 @@ public double getRate() { @Override public java.time.Duration getStartTime() { if(playerValid()) { - return convertDuration(mediaPlayer.getStartTime()); + return convertDuration(getPlayer().getStartTime()); } return ZERO; } @@ -220,7 +220,7 @@ public java.time.Duration getStartTime() { @Override public java.time.Duration getStopTime() { if(playerValid()) { - return convertDuration(mediaPlayer.getStopTime()); + return convertDuration(getPlayer().getStopTime()); } return ZERO; } @@ -228,7 +228,7 @@ public java.time.Duration getStopTime() { @Override public java.time.Duration getTotalDuration() { if(playerValid()) { - return convertDuration(mediaPlayer.getTotalDuration()); + return convertDuration(getPlayer().getTotalDuration()); } return ZERO; } @@ -236,7 +236,7 @@ public java.time.Duration getTotalDuration() { @Override public double getVolume() { if(playerValid()) { - return mediaPlayer.getVolume(); + return getPlayer().getVolume(); } return 0; } @@ -244,63 +244,63 @@ public double getVolume() { @Override public void pause() { if(playerValid()) { - mediaPlayer.pause(); + getPlayer().pause(); } } @Override public void seek(java.time.Duration seekTime) { if(playerValid()) { - mediaPlayer.seek(convertDuration(seekTime)); + getPlayer().seek(convertDuration(seekTime)); } } @Override public void setBalance(double value) { if(playerValid()) { - mediaPlayer.setBalance(value); + getPlayer().setBalance(value); } } @Override public void setCycleCount(int value) { if(playerValid()) { - mediaPlayer.setCycleCount(value); + getPlayer().setCycleCount(value); } } @Override public void setRate(double value) { if(playerValid()) { - mediaPlayer.setRate(value); + getPlayer().setRate(value); } } @Override public void setStartTime(java.time.Duration value) { if(playerValid()) { - mediaPlayer.setStartTime(convertDuration(value)); + getPlayer().setStartTime(convertDuration(value)); } } @Override public void setStopTime(java.time.Duration value) { if(playerValid()) { - mediaPlayer.setStopTime(convertDuration(value)); + getPlayer().setStopTime(convertDuration(value)); } } @Override public void setVolume(double value) { if(playerValid()) { - mediaPlayer.setVolume(value); + getPlayer().setVolume(value); } } @Override public void stop() { if(playerValid()) { - mediaPlayer.stop(); + getPlayer().stop(); } } @@ -316,8 +316,15 @@ private javafx.util.Duration convertDuration(java.time.Duration duration) { return javafx.util.Duration.seconds((double)duration.getSeconds()); } + private MediaPlayer getPlayer() { + if(mediaView != null) { + return mediaView.getMediaPlayer(); + } + return null; + } + private boolean playerValid() { - return mediaPlayer != null; + return getPlayer() != null; } } From fb48a254dd38202db4271aaecdb59c26a4cb676f Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sun, 29 Mar 2020 17:54:46 -0400 Subject: [PATCH 11/29] Fix black screen --- src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java index 5947019de..e864dd7ed 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java @@ -61,6 +61,7 @@ private synchronized void setMedia(Media media) { Scene scene = new Scene(root, media.getWidth(), media.getHeight()); mediaView.autosize(); panel.setScene(scene); + mediaView.getMediaPlayer().setOnReady(() -> panel.setSize(media.getWidth(), media.getHeight())); }); } From ec99a8ae69ea10c4dc078704a70d1c48e50756ee Mon Sep 17 00:00:00 2001 From: Gamebuster Date: Sun, 29 Mar 2020 19:12:19 -0400 Subject: [PATCH 12/29] Add JavaFX to classpath (#3) * Add JavaFX to classpath * Figured out how to make JavaFX compile with jdk8 and jdk11 * Travis needs OpenJFX 8 to compile for Java 8 --- .classpath | 50 +++++++++---------- .settings/org.eclipse.jdt.core.prefs | 4 +- .travis.yml | 6 ++- build-maven.gradle | 19 +++++++ build.gradle | 17 ++++++- .../litiengine/resources/Resources.java | 2 +- 6 files changed, 67 insertions(+), 31 deletions(-) diff --git a/.classpath b/.classpath index 78b60bd14..2bf1919a4 100644 --- a/.classpath +++ b/.classpath @@ -1,25 +1,25 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 80a5df502..daecd4083 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -2,13 +2,13 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.compliance=11 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.compiler.source=11 org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 diff --git a/.travis.yml b/.travis.yml index 77e3b34e9..45b2b5661 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,10 @@ install: true before_install: - chmod +x gradlew - sudo apt-get -y install at-spi2-core - -jdk: openjdk11 + - sudo apt-get -y install openjfx +jdk: + - openjdk11 + - openjdk8 git: depth: false diff --git a/build-maven.gradle b/build-maven.gradle index 4c10a9e2e..4c0d2ae35 100644 --- a/build-maven.gradle +++ b/build-maven.gradle @@ -1,7 +1,23 @@ +buildscript { + dependencies { + if(JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_11)) { + classpath "org.openjfx:javafx-plugin:0.0.8" + } + } +} + apply plugin: 'java-library' apply plugin: 'maven-publish' apply plugin: 'signing' +if(JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_11)) { + apply plugin: 'org.openjfx.javafxplugin' + javafx { + version = "11.0.2" + modules = ['javafx.media', 'javafx.swing'] + } +} + sourceSets { main.java.srcDir "src" main.resources.srcDir "resources" @@ -36,6 +52,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter-params:5.4.1' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.1' testImplementation 'org.mockito:mockito-core:2.25.1' + } test { @@ -93,6 +110,8 @@ tasks.withType(JavaCompile) { group = "de.gurkenlabs" archivesBaseName = "litiengine" version = "0.4.19" +sourceCompatibility = "8" +targetCompatibility = "8" publishing { publications { diff --git a/build.gradle b/build.gradle index a75704f7f..497557768 100644 --- a/build.gradle +++ b/build.gradle @@ -2,13 +2,26 @@ buildscript { repositories { mavenCentral() } + dependencies { + if(JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_11)) { + classpath "org.openjfx:javafx-plugin:0.0.8" + } + } } - plugins { +plugins { id 'com.stehno.natives' version '0.3.1' id 'org.sonarqube' version '2.8' } +if(JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_11)) { + apply plugin: 'org.openjfx.javafxplugin' + javafx { + version = "11.0.2" + modules = ['javafx.media', 'javafx.swing'] + } +} + natives { configurations = ['runtimeClasspath'] outputDir = 'libs' @@ -19,6 +32,8 @@ apply plugin: 'jacoco' archivesBaseName = "litiengine" version = "v0.4.19-alpha" +sourceCompatibility = "8" +targetCompatibility = "8" sourceSets { main.java.srcDir "src" diff --git a/src/de/gurkenlabs/litiengine/resources/Resources.java b/src/de/gurkenlabs/litiengine/resources/Resources.java index bb4bae00b..ee3324297 100644 --- a/src/de/gurkenlabs/litiengine/resources/Resources.java +++ b/src/de/gurkenlabs/litiengine/resources/Resources.java @@ -156,7 +156,7 @@ public static Blueprints blueprints() { * * @return The VideoManager resource container. * - * @see VideoManager + * @see de.gurkenlabs.litiengine.video.VideoManager */ public static Videos videos() { return videos; From 2ea279338c3b7fcf2f828c8b99478d3d79fdddf3 Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Mon, 30 Mar 2020 23:23:22 -0400 Subject: [PATCH 13/29] This property should never be set. --- src/de/gurkenlabs/litiengine/video/VideoManager.java | 5 ----- src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java | 7 ------- src/de/gurkenlabs/litiengine/video/VideoPlayer.java | 1 - 3 files changed, 13 deletions(-) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManager.java b/src/de/gurkenlabs/litiengine/video/VideoManager.java index e884a336d..07dfdc82d 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManager.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManager.java @@ -281,11 +281,6 @@ public void setBalance(double value) { impl.setBalance(value); } - @Override - public void setCycleCount(int value) { - impl.setCycleCount(value); - } - @Override public void setRate(double value) { impl.setRate(value); diff --git a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java index e864dd7ed..3013aa6fd 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java @@ -263,13 +263,6 @@ public void setBalance(double value) { } } - @Override - public void setCycleCount(int value) { - if(playerValid()) { - getPlayer().setCycleCount(value); - } - } - @Override public void setRate(double value) { if(playerValid()) { diff --git a/src/de/gurkenlabs/litiengine/video/VideoPlayer.java b/src/de/gurkenlabs/litiengine/video/VideoPlayer.java index 91083fd4c..ab115d119 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoPlayer.java +++ b/src/de/gurkenlabs/litiengine/video/VideoPlayer.java @@ -47,7 +47,6 @@ interface VideoPlayer { void play(); void seek(Duration seekTime); void setBalance(double value); - void setCycleCount(int value); void setRate(double value); void setStartTime(Duration value); void setStopTime(Duration value); From 3f643605805ac5a7c6e82fa060c42b900d4dc327 Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Mon, 30 Mar 2020 23:25:25 -0400 Subject: [PATCH 14/29] Add javadocs --- .../litiengine/video/VideoManager.java | 146 ++++++++++++++++-- .../litiengine/video/VideoManagerImpl.java | 1 + .../litiengine/video/VideoPlayer.java | 5 +- 3 files changed, 142 insertions(+), 10 deletions(-) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManager.java b/src/de/gurkenlabs/litiengine/video/VideoManager.java index 07dfdc82d..ede15321f 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManager.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManager.java @@ -76,14 +76,21 @@ public VideoManager() throws NoClassDefFoundError { * * @param video the video to load * - * @throws NoClassDefFoundError if JavaFX is not installed (you can catch this - * if you want to handle JavaFX not being installed) + * @throws NoClassDefFoundError if JavaFX is not installed (you can catch this if you + * want to handle JavaFX not being installed) + * + * @throws IOException if the VideoResource's URL protocol is web based and the + * connection is refused + * + * @throws javafx.scene.media.MediaException see {@link javafx.scene.media.Media#Media(String)} * * @throws SecurityException if a security manager exists and it denies access to * the classloader which loaded this class * - * @throws LinkageError if the linkage otherwise fails (It is highly discouraged to - * catch this) + * @throws LinkageError if JavaFX exists but otherwise fails to load (It is highly + * discouraged to catch this) + * + * @see {@link javafx.scene.media.Media#Media(String)} for more details and thrown exceptions */ public VideoManager(VideoResource video) throws NoClassDefFoundError { super(0,0); @@ -92,19 +99,26 @@ public VideoManager(VideoResource video) throws NoClassDefFoundError { /** * Creates a new VideoManager which will load the - * specified video. + * specified video, and play it if specified. * * @param video the video to load * @param play whether to immediately begin playing the video * - * @throws NoClassDefFoundError if JavaFX is not installed (you can catch this - * if you want to handle JavaFX not being installed) + * @throws NoClassDefFoundError if JavaFX is not installed (you can catch this if you + * want to handle JavaFX not being installed) + * + * @throws IOException if the VideoResource's URL protocol is web based and the + * connection is refused + * + * @throws javafx.scene.media.MediaException see {@link javafx.scene.media.Media#Media(String)} * * @throws SecurityException if a security manager exists and it denies access to * the classloader which loaded this class * - * @throws LinkageError if the linkage otherwise fails (It is highly discouraged to - * catch this) + * @throws LinkageError if JavaFX exists but otherwise fails to load (It is highly + * discouraged to catch this) + * + * @see {@link javafx.scene.media.Media#Media(String)} for more details and thrown exceptions */ public VideoManager(VideoResource video, boolean play) throws NoClassDefFoundError { super(0,0); @@ -116,10 +130,52 @@ public VideoManager(VideoResource video, boolean play) throws NoClassDefFoundErr } } + /** + * Creates a new VideoManager which will load the + * specified video, and play it if specified. + * + * @param url the URL of the video + * + * @throws NoClassDefFoundError if JavaFX is not installed (you can catch this if you + * want to handle JavaFX not being installed) + * + * @throws IOException if the URL protocol is web based and the connection is refused + * + * @throws javafx.scene.media.MediaException see {@link javafx.scene.media.Media#Media(String)} + * + * @throws SecurityException if a security manager exists and it denies access to + * the classloader which loaded this class + * + * @throws LinkageError if JavaFX exists but otherwise fails to load (It is highly + * discouraged to catch this) + * + * @see {@link javafx.scene.media.Media#Media(String)} for more details and thrown exceptions + */ public VideoManager(URL url) throws NoClassDefFoundError, IOException { this(url, false); } + /** + * Creates a new video manager which will load the specified video, and play it if + * desired + * + * @param url the URL of the video + * + * @throws NoClassDefFoundError if JavaFX is not installed (you can catch this if you + * want to handle JavaFX not being installed) + * + * @throws IOException if the URL protocol is web based and the connection is refused + * + * @throws javafx.scene.media.MediaException see {@link javafx.scene.media.Media#Media(String)} + * + * @throws SecurityException if a security manager exists and it denies access to + * the classloader which loaded this class + * + * @throws LinkageError if JavaFX exists but otherwise fails to load (It is highly + * discouraged to catch this) + * + * @see {@link javafx.scene.media.Media#Media(String)} for more details and thrown exceptions + */ public VideoManager(URL url, boolean play) throws NoClassDefFoundError, IOException { super(0,0); if(url.getProtocol().startsWith("http")) { @@ -153,16 +209,37 @@ private void initialize() { } + /** + * @return true if the status of the video player is unknown. + * + * This is generally the State of the player immediately after + * creation. + * + * @see javafx.scene.media.MediaPlayer.Status.UNKNOWN + */ @Override public boolean isStatusUnknown() { return impl.isStatusUnknown(); } + /** + * @return true if the video is ready to play. + * + * @see javafx.scene.media.MediaPlayer.Status.READY + */ @Override public boolean isReady() { return impl.isReady(); } + /** + * @return true if a critical error has occured during video playback. + * + * This means that playback can never continue again with this VideoManager + * and a new VideoManager should be created. + * + * @see javafx.scene.media.MediaPlayer.Status.HALTED + */ @Override public boolean isErrored() { return impl.isErrored(); @@ -178,21 +255,40 @@ public boolean isPaused() { return impl.isPaused(); } + /** + * @return true if the video has stopped playing because the + * buffer has slowed or stopped. + * + * @see javafx.scene.media.MediaPlayer.Status.STALLED + */ @Override public boolean isBuffering() { return impl.isBuffering(); } + /** + * @return true if playback has been stopped under normal conditions + * + * @see javafx.scene.media.MediaPlayer.Status.STOPPED + */ @Override public boolean isStopped() { return impl.isStopped(); } + /** + * @return the status of the video player + * + * @see javafx.scene.media.MediaPlayer.Status + */ @Override public Status getStatus() { return impl.getStatus(); } + /** + * Free all resources associated with this player. + */ @Override public void dispose() { impl.dispose(); @@ -203,31 +299,58 @@ public Throwable getError() { return impl.getError(); } + /** + * @return the audio balance (the leftness or rightness of the audio). + */ @Override public double getBalance() { return impl.getBalance(); } + /** + * @see javafx.scene.media.MediaPlayer#bufferProgressTimeProperty() + */ @Override public Duration getBufferProgressTime() { return impl.getBufferProgressTime(); } + /** + * @return the number of completed playback cycles. Begins at 0. + * + * @see {@link javafx.scene.media.MediaPlayer#currentCountProperty()} + */ @Override public int getCurrentCount() { return impl.getCurrentCount(); } + /** + * @return the speed the video is set to play at + * + * Not to be confused with {@link #getRate()} + */ @Override public double getCurrentRate() { return impl.getCurrentRate(); } + /** + * @return the current time elapsed in the video + */ @Override public Duration getCurrentTime() { return impl.getCurrentTime(); } + /** + * @return the current playback speed of the video, + * regardless of settings. + * + * For example if {@link #setRate(double)} is called + * with a value of 1.0, and then the player is paused, + * this will return 0.0. + */ @Override public double getRate() { return impl.getRate(); @@ -243,6 +366,11 @@ public Duration getStopTime() { return impl.getStopTime(); } + /** + * @return the total amount of time the player is allowed to play until finished. + * + * @see javafx.scene.media.MediaPlayer#totalDuration + */ @Override public Duration getTotalDuration() { return impl.getTotalDuration(); diff --git a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java index 3013aa6fd..3c4bfc48b 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java @@ -298,6 +298,7 @@ public void stop() { } } + @Override public JComponent getPanel() { return panel; } diff --git a/src/de/gurkenlabs/litiengine/video/VideoPlayer.java b/src/de/gurkenlabs/litiengine/video/VideoPlayer.java index ab115d119..187c41a22 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoPlayer.java +++ b/src/de/gurkenlabs/litiengine/video/VideoPlayer.java @@ -54,9 +54,12 @@ interface VideoPlayer { void stop(); Container getPanel(); + /** + * @see javafx.scene.media.MediaPlayer.Status + */ public static enum Status { DISPOSED, - ERRORED, + ERRORED, //HALTED PAUSED, PLAYING, READY, From cad48aba3fbc01d7d389f0cefc757952e0f3e402 Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Mon, 30 Mar 2020 23:26:47 -0400 Subject: [PATCH 15/29] I Forgot to push VideoRenderer previously --- .../litiengine/graphics/VideoRenderer.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/de/gurkenlabs/litiengine/graphics/VideoRenderer.java diff --git a/src/de/gurkenlabs/litiengine/graphics/VideoRenderer.java b/src/de/gurkenlabs/litiengine/graphics/VideoRenderer.java new file mode 100644 index 000000000..ee5bd347b --- /dev/null +++ b/src/de/gurkenlabs/litiengine/graphics/VideoRenderer.java @@ -0,0 +1,20 @@ +package de.gurkenlabs.litiengine.graphics; + +import java.awt.Graphics2D; + +import de.gurkenlabs.litiengine.video.VideoManager; + +public final class VideoRenderer { + + private VideoRenderer() { + throw new UnsupportedOperationException(); + } + + public static void render(final Graphics2D g, final VideoManager video, final double x, final double y) { + if(video == null) { + return; + } + //TODO implement me! + } + +} From 22d0b0e710d4d3cec71ad81cb89192dcd00511a0 Mon Sep 17 00:00:00 2001 From: Gamebuster Date: Tue, 31 Mar 2020 00:55:11 -0400 Subject: [PATCH 16/29] Fix javadoc and improve security of url (#4) * Fix javadoc and improve security of url handling --- .../litiengine/video/VideoManager.java | 47 ++++++++----------- .../litiengine/video/VideoManagerImpl.java | 38 ++++++++++----- .../litiengine/video/VideoPlayer.java | 5 +- 3 files changed, 50 insertions(+), 40 deletions(-) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManager.java b/src/de/gurkenlabs/litiengine/video/VideoManager.java index ede15321f..69429efdd 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManager.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManager.java @@ -3,16 +3,16 @@ import java.awt.Container; import java.awt.Graphics2D; import java.io.IOException; +import java.io.UncheckedIOException; import java.net.URL; import java.time.Duration; import java.util.logging.Level; import java.util.logging.Logger; -import javax.net.ssl.SSLHandshakeException; - import de.gurkenlabs.litiengine.gui.GuiComponent; import de.gurkenlabs.litiengine.resources.VideoResource; + /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * * Do not import anything from javafx into this class! @@ -66,7 +66,7 @@ public final class VideoManager extends GuiComponent implements VideoPlayer { * @throws LinkageError if the linkage otherwise fails (It is highly discouraged to * catch this) */ - public VideoManager() throws NoClassDefFoundError { + public VideoManager() { super(0,0); }; @@ -79,7 +79,7 @@ public VideoManager() throws NoClassDefFoundError { * @throws NoClassDefFoundError if JavaFX is not installed (you can catch this if you * want to handle JavaFX not being installed) * - * @throws IOException if the VideoResource's URL protocol is web based and the + * @throws UncheckedIOException if the VideoResource's URI protocol is web based and the * connection is refused * * @throws javafx.scene.media.MediaException see {@link javafx.scene.media.Media#Media(String)} @@ -90,9 +90,9 @@ public VideoManager() throws NoClassDefFoundError { * @throws LinkageError if JavaFX exists but otherwise fails to load (It is highly * discouraged to catch this) * - * @see {@link javafx.scene.media.Media#Media(String)} for more details and thrown exceptions + * @see javafx.scene.media.Media#Media(String) */ - public VideoManager(VideoResource video) throws NoClassDefFoundError { + public VideoManager(VideoResource video) { super(0,0); setVideo(video); } @@ -107,7 +107,7 @@ public VideoManager(VideoResource video) throws NoClassDefFoundError { * @throws NoClassDefFoundError if JavaFX is not installed (you can catch this if you * want to handle JavaFX not being installed) * - * @throws IOException if the VideoResource's URL protocol is web based and the + * @throws UncheckedIOException if the VideoResource's URL protocol is web based and the * connection is refused * * @throws javafx.scene.media.MediaException see {@link javafx.scene.media.Media#Media(String)} @@ -118,9 +118,9 @@ public VideoManager(VideoResource video) throws NoClassDefFoundError { * @throws LinkageError if JavaFX exists but otherwise fails to load (It is highly * discouraged to catch this) * - * @see {@link javafx.scene.media.Media#Media(String)} for more details and thrown exceptions + * @see javafx.scene.media.Media#Media(String) */ - public VideoManager(VideoResource video, boolean play) throws NoClassDefFoundError { + public VideoManager(VideoResource video, boolean play) { super(0,0); if(play) { play(video); @@ -149,7 +149,7 @@ public VideoManager(VideoResource video, boolean play) throws NoClassDefFoundErr * @throws LinkageError if JavaFX exists but otherwise fails to load (It is highly * discouraged to catch this) * - * @see {@link javafx.scene.media.Media#Media(String)} for more details and thrown exceptions + * @see javafx.scene.media.Media#Media(String) */ public VideoManager(URL url) throws NoClassDefFoundError, IOException { this(url, false); @@ -160,6 +160,7 @@ public VideoManager(URL url) throws NoClassDefFoundError, IOException { * desired * * @param url the URL of the video + * @param play whether to immediately begin playing the video * * @throws NoClassDefFoundError if JavaFX is not installed (you can catch this if you * want to handle JavaFX not being installed) @@ -174,18 +175,10 @@ public VideoManager(URL url) throws NoClassDefFoundError, IOException { * @throws LinkageError if JavaFX exists but otherwise fails to load (It is highly * discouraged to catch this) * - * @see {@link javafx.scene.media.Media#Media(String)} for more details and thrown exceptions + * @see javafx.scene.media.Media#Media(String) */ public VideoManager(URL url, boolean play) throws NoClassDefFoundError, IOException { super(0,0); - if(url.getProtocol().startsWith("http")) { - if(!allowNetworkConnections) { - throw new IOException("Network access disallowed"); - } - if(url.getProtocol().equals("http")) { - throw new SSLHandshakeException("Insecure protocol: http. Use https"); - } - } if(play) { play(url); } @@ -215,7 +208,7 @@ private void initialize() { * This is generally the State of the player immediately after * creation. * - * @see javafx.scene.media.MediaPlayer.Status.UNKNOWN + * @see javafx.scene.media.MediaPlayer.Status#UNKNOWN */ @Override public boolean isStatusUnknown() { @@ -225,7 +218,7 @@ public boolean isStatusUnknown() { /** * @return true if the video is ready to play. * - * @see javafx.scene.media.MediaPlayer.Status.READY + * @see javafx.scene.media.MediaPlayer.Status#READY */ @Override public boolean isReady() { @@ -238,7 +231,7 @@ public boolean isReady() { * This means that playback can never continue again with this VideoManager * and a new VideoManager should be created. * - * @see javafx.scene.media.MediaPlayer.Status.HALTED + * @see javafx.scene.media.MediaPlayer.Status#HALTED */ @Override public boolean isErrored() { @@ -259,7 +252,7 @@ public boolean isPaused() { * @return true if the video has stopped playing because the * buffer has slowed or stopped. * - * @see javafx.scene.media.MediaPlayer.Status.STALLED + * @see javafx.scene.media.MediaPlayer.Status#STALLED */ @Override public boolean isBuffering() { @@ -269,7 +262,7 @@ public boolean isBuffering() { /** * @return true if playback has been stopped under normal conditions * - * @see javafx.scene.media.MediaPlayer.Status.STOPPED + * @see javafx.scene.media.MediaPlayer.Status#STOPPED */ @Override public boolean isStopped() { @@ -318,7 +311,7 @@ public Duration getBufferProgressTime() { /** * @return the number of completed playback cycles. Begins at 0. * - * @see {@link javafx.scene.media.MediaPlayer#currentCountProperty()} + * @see javafx.scene.media.MediaPlayer#currentCountProperty() */ @Override public int getCurrentCount() { @@ -445,12 +438,12 @@ public Container getPanel() { } @Override - public void setVideo(URL url) { + public void setVideo(URL url) throws IOException{ impl.setVideo(url); } @Override - public void play(URL url) { + public void play(URL url) throws IOException { impl.play(url); } diff --git a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java index 3c4bfc48b..42bc46118 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java @@ -3,11 +3,15 @@ import static java.time.Duration.ZERO; import static javafx.scene.media.MediaPlayer.Status.*; +import java.io.IOException; +import java.io.UncheckedIOException; import java.net.URL; +import javax.net.ssl.SSLHandshakeException; import javax.swing.JComponent; import de.gurkenlabs.litiengine.resources.VideoResource; + import javafx.application.Platform; import javafx.embed.swing.JFXPanel; import javafx.scene.Group; @@ -24,22 +28,41 @@ final class VideoManagerImpl implements VideoPlayer{ @Override public void setVideo(VideoResource video) { + if(video.getURI().startsWith("http")) { + try { + setVideo(new URL(video.getURI())); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } setMedia(new Media(video.getURI())); } @Override public void play(VideoResource video) { - play(new Media(video.getURI())); + setVideo(video); + play(); } @Override - public void setVideo(URL url) { + public void setVideo(URL url) throws IOException { + if(url.getProtocol().startsWith("http")) { + if(!VideoManager.allowNetworkConnections) { + throw new IOException("Network access disallowed"); + } + if(url.getProtocol().equals("http")) { + throw new SSLHandshakeException("Insecure protocol: http. Use https"); + } + } setMedia(new Media(url.toString())); } @Override - public void play(URL url) { - play(new Media(url.toString())); + public void play(URL url) throws IOException { + setVideo(url); + Platform.runLater(() -> { + play(); + }); } public void play() { @@ -65,13 +88,6 @@ private synchronized void setMedia(Media media) { }); } - private synchronized void play(Media media) { - setMedia(media); - Platform.runLater(() -> { - play(); - }); - } - @Override public boolean isStatusUnknown() { if(playerValid()) { diff --git a/src/de/gurkenlabs/litiengine/video/VideoPlayer.java b/src/de/gurkenlabs/litiengine/video/VideoPlayer.java index 187c41a22..411875ad8 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoPlayer.java +++ b/src/de/gurkenlabs/litiengine/video/VideoPlayer.java @@ -1,6 +1,7 @@ package de.gurkenlabs.litiengine.video; import java.awt.Container; +import java.io.IOException; import java.net.URL; import java.time.Duration; @@ -41,9 +42,9 @@ interface VideoPlayer { double getVolume(); void pause(); void setVideo(VideoResource video); - void setVideo(URL url); + void setVideo(URL url) throws IOException; void play(VideoResource video); - void play(URL url); + void play(URL url) throws IOException; void play(); void seek(Duration seekTime); void setBalance(double value); From 02ed3ca15f2f69096366fc63827840ed6efb6d9e Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Tue, 31 Mar 2020 02:17:51 -0400 Subject: [PATCH 17/29] Fixed threading issues that occured as a result of the previous changes --- .../litiengine/video/VideoManagerImpl.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java index 42bc46118..96907fe50 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java @@ -27,7 +27,7 @@ final class VideoManagerImpl implements VideoPlayer{ private volatile MediaView mediaView; @Override - public void setVideo(VideoResource video) { + public synchronized void setVideo(VideoResource video) { if(video.getURI().startsWith("http")) { try { setVideo(new URL(video.getURI())); @@ -39,13 +39,14 @@ public void setVideo(VideoResource video) { } @Override - public void play(VideoResource video) { + public synchronized void play(VideoResource video) { setVideo(video); + while(isStatusUnknown()); play(); } @Override - public void setVideo(URL url) throws IOException { + public synchronized void setVideo(URL url) throws IOException { if(url.getProtocol().startsWith("http")) { if(!VideoManager.allowNetworkConnections) { throw new IOException("Network access disallowed"); @@ -58,17 +59,18 @@ public void setVideo(URL url) throws IOException { } @Override - public void play(URL url) throws IOException { + public synchronized void play(URL url) throws IOException { setVideo(url); - Platform.runLater(() -> { - play(); - }); + while(isStatusUnknown()); + play(); } - public void play() { + public synchronized void play() { if(playerValid()) { panel.setVisible(true); - getPlayer().play(); + Platform.runLater(() -> { + getPlayer().play(); + }); } } From 4ba1d37b220208e596c836da3d3ebe8a9d2d089d Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Tue, 31 Mar 2020 16:02:17 -0400 Subject: [PATCH 18/29] Implement VideoRenderer, Closes gurkenlabs#291 --- src/de/gurkenlabs/litiengine/graphics/VideoRenderer.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/de/gurkenlabs/litiengine/graphics/VideoRenderer.java b/src/de/gurkenlabs/litiengine/graphics/VideoRenderer.java index ee5bd347b..7fb8914bf 100644 --- a/src/de/gurkenlabs/litiengine/graphics/VideoRenderer.java +++ b/src/de/gurkenlabs/litiengine/graphics/VideoRenderer.java @@ -10,11 +10,13 @@ private VideoRenderer() { throw new UnsupportedOperationException(); } - public static void render(final Graphics2D g, final VideoManager video, final double x, final double y) { - if(video == null) { + public static void render(final Graphics2D g, final VideoManager video) { + if(video == null || video.isStatusUnknown()) { return; } - //TODO implement me! + g.translate(video.getX(), video.getY()); + video.getPanel().paint(g); + g.translate(-video.getX(), -video.getY()); } } From 02ed1668cb49b41d7c97f1b094ec483a85043256 Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sat, 25 Apr 2020 01:47:54 -0400 Subject: [PATCH 19/29] Video resource manager (no implementation provided) see https://github.com/gurkenlabs/litiengine/pull/326#issuecomment-618953971 --- .../litiengine/graphics/VideoRenderer.java | 22 ++ .../litiengine/resources/Resources.java | 14 + .../litiengine/resources/VideoResource.java | 22 ++ .../litiengine/resources/Videos.java | 26 ++ .../litiengine/video/VideoManager.java | 372 ++++++++++++++++++ .../litiengine/video/VideoPlayer.java | 67 ++++ 6 files changed, 523 insertions(+) create mode 100644 src/de/gurkenlabs/litiengine/graphics/VideoRenderer.java create mode 100644 src/de/gurkenlabs/litiengine/resources/VideoResource.java create mode 100644 src/de/gurkenlabs/litiengine/resources/Videos.java create mode 100644 src/de/gurkenlabs/litiengine/video/VideoManager.java create mode 100644 src/de/gurkenlabs/litiengine/video/VideoPlayer.java diff --git a/src/de/gurkenlabs/litiengine/graphics/VideoRenderer.java b/src/de/gurkenlabs/litiengine/graphics/VideoRenderer.java new file mode 100644 index 000000000..4e36c6ce1 --- /dev/null +++ b/src/de/gurkenlabs/litiengine/graphics/VideoRenderer.java @@ -0,0 +1,22 @@ +package de.gurkenlabs.litiengine.graphics; + +import java.awt.Graphics2D; + +import de.gurkenlabs.litiengine.video.VideoManager; + +public final class VideoRenderer { + + private VideoRenderer() { + throw new UnsupportedOperationException(); + } + + public static void render(final Graphics2D g, final VideoManager video) { + if(video == null || video.isStatusUnknown()) { + return; + } + g.translate(video.getX(), video.getY()); + video.getPanel().paint(g); + g.translate(-video.getX(), -video.getY()); + } + +} \ No newline at end of file diff --git a/src/de/gurkenlabs/litiengine/resources/Resources.java b/src/de/gurkenlabs/litiengine/resources/Resources.java index c3188b4ad..ee3324297 100644 --- a/src/de/gurkenlabs/litiengine/resources/Resources.java +++ b/src/de/gurkenlabs/litiengine/resources/Resources.java @@ -41,6 +41,7 @@ *
  • (localizable) strings
  • *
  • spritesheets
  • *
  • sounds
  • + *
  • videos
  • * * * @see ResourcesContainer @@ -55,6 +56,7 @@ public final class Resources { private static Images images = new Images(); private static Spritesheets spritesheets = new Spritesheets(); private static Blueprints blueprints = new Blueprints(); + private static Videos videos = new Videos(); private Resources() { throw new UnsupportedOperationException(); @@ -148,6 +150,17 @@ public static Spritesheets spritesheets() { public static Blueprints blueprints() { return blueprints; } + + /** + * Gets the container that manages VideoManager resources. + * + * @return The VideoManager resource container. + * + * @see de.gurkenlabs.litiengine.video.VideoManager + */ + public static Videos videos() { + return videos; + } /** * Load Spritesheets, Tilesets and Maps from a game resource file created with the utiLITI editor. @@ -332,6 +345,7 @@ public static void clearAll() { tilesets().clear(); images().clear(); spritesheets().clear(); + videos().clear(); } public static URL getLocation(String name) { diff --git a/src/de/gurkenlabs/litiengine/resources/VideoResource.java b/src/de/gurkenlabs/litiengine/resources/VideoResource.java new file mode 100644 index 000000000..1effb3165 --- /dev/null +++ b/src/de/gurkenlabs/litiengine/resources/VideoResource.java @@ -0,0 +1,22 @@ +package de.gurkenlabs.litiengine.resources; + +import java.net.URI; + +public class VideoResource extends NamedResource { + + private final String uri; + + public VideoResource(String uri, String name) { + this.uri = uri; + setName(name); + } + + public VideoResource(URI uri, String name) { + this(uri.toString(), name); + } + + public String getURI() { + return uri; + } + +} diff --git a/src/de/gurkenlabs/litiengine/resources/Videos.java b/src/de/gurkenlabs/litiengine/resources/Videos.java new file mode 100644 index 000000000..5e6c21640 --- /dev/null +++ b/src/de/gurkenlabs/litiengine/resources/Videos.java @@ -0,0 +1,26 @@ +package de.gurkenlabs.litiengine.resources; + +import java.net.URL; + +import de.gurkenlabs.litiengine.video.VideoManager; + +public class Videos extends ResourcesContainer{ + + Videos(){} + + public VideoManager load(VideoResource video) throws NoClassDefFoundError { + return load(video, false); + } + + public VideoManager load(VideoResource video, boolean play) throws NoClassDefFoundError { + VideoManager videoManager = new VideoManager(video, play); + this.add(video.getName(), videoManager); + return videoManager; + } + + @Override + protected VideoManager load(URL resourceName) throws Exception, NoClassDefFoundError { + return new VideoManager(resourceName); + } + +} diff --git a/src/de/gurkenlabs/litiengine/video/VideoManager.java b/src/de/gurkenlabs/litiengine/video/VideoManager.java new file mode 100644 index 000000000..27fc877a3 --- /dev/null +++ b/src/de/gurkenlabs/litiengine/video/VideoManager.java @@ -0,0 +1,372 @@ +package de.gurkenlabs.litiengine.video; + +import java.awt.Container; +import java.awt.Graphics2D; +import java.io.IOException; +import java.net.URL; +import java.time.Duration; +import java.util.logging.Level; +import java.util.logging.Logger; + +import de.gurkenlabs.litiengine.gui.GuiComponent; +import de.gurkenlabs.litiengine.resources.VideoResource; + +/** + * + * UNIMPLEMENTED + * + * THIS CLASS IS SUBJECT TO CHANGE DRAMATICALLY + * + */ + +public final class VideoManager extends GuiComponent implements VideoPlayer { + + private static final Logger log = Logger.getLogger(VideoManager.class.getName()); + private static boolean checked = false; + + public static boolean allowNetworkConnections = false; + + protected VideoPlayer impl; + + { + if(!checked) { + try { + + //TODO Load natives + + } catch (LinkageError e) { + log.log(Level.SEVERE, e, () -> e.getMessage()); + throw e; + } catch (SecurityException e) { + log.log(Level.SEVERE, e, () -> e.getMessage()); + throw e; + } + } + checked = true; + initialize(); + } + + /** + * Creates a new VideoManager + * + * @throws SecurityException if a security manager exists and it denies access to + * the classloader which loaded this class + * + * @throws LinkageError if the native binaries were unable to load + */ + public VideoManager() { + super(0,0); + }; + + /** + * Creates a new VideoManager which load the + * specified video without playing it. + * + * @param video the video to load + * + * @throws SecurityException if a security manager exists and it denies access to + * the classloader which loaded this class + * + * @throws LinkageError if the native binaries were unable to load + */ + public VideoManager(VideoResource video) { + super(0,0); + setVideo(video); + } + + /** + * Creates a new VideoManager which will load the + * specified video, and play it if specified. + * + * @param video the video to load + * @param play whether to immediately begin playing the video + * + * @throws SecurityException if a security manager exists and it denies access to + * the classloader which loaded this class + * + * @throws LinkageError if the native binaries were unable to load + */ + public VideoManager(VideoResource video, boolean play) { + super(0,0); + if(play) { + play(video); + } + else { + setVideo(video); + } + } + + /** + * Creates a new VideoManager which will load the + * specified video, and play it if specified. + * + * @param url the URL of the video + * + * @throws SecurityException if a security manager exists and it denies access to + * the classloader which loaded this class + * + * @throws LinkageError if the native binaries were unable to load + * + */ + public VideoManager(URL url) throws NoClassDefFoundError, IOException { + this(url, false); + } + + /** + * Creates a new video manager which will load the specified video, and play it if + * desired + * + * @param url the URL of the video + * @param play whether to immediately begin playing the video + * + * @throws SecurityException if a security manager exists and it denies access to + * the classloader which loaded this class + * + * @throws LinkageError if the native binaries were unable to load + */ + public VideoManager(URL url, boolean play) throws NoClassDefFoundError, IOException { + super(0,0); + if(play) { + play(url); + } + else { + setVideo(url); + } + } + + /** + * Initializes the media player + * + * @throws IllegalStateException if the media player has already been initialized + */ + protected void initialize() { + + if(impl != null) { + throw new IllegalStateException("Video player already initialized!"); + } + + //impl = new VideoManagerImpl(); + + } + + /** + * @return true if the status of the video player is unknown. + * + * This is generally the State of the player immediately after + * creation. + */ + @Override + public boolean isStatusUnknown() { + return impl.isStatusUnknown(); + } + + /** + * @return true if the video is ready to play. + */ + @Override + public boolean isReady() { + return impl.isReady(); + } + + /** + * @return true if a critical error has occured during video playback. + * + * This means that playback can never continue again with this VideoManager + * and a new VideoManager should be created. + */ + @Override + public boolean isErrored() { + return impl.isErrored(); + } + + @Override + public boolean isPlaying() { + return impl.isPlaying(); + } + + @Override + public boolean isPaused() { + return impl.isPaused(); + } + + /** + * @return true if the video has stopped playing because the + * buffer has slowed or stopped. + */ + @Override + public boolean isBuffering() { + return impl.isBuffering(); + } + + /** + * @return true if playback has been stopped under normal conditions + */ + @Override + public boolean isStopped() { + return impl.isStopped(); + } + + /** + * @return the status of the video player + */ + @Override + public Status getStatus() { + return impl.getStatus(); + } + + /** + * Free all resources associated with this player. + */ + @Override + public void dispose() { + impl.dispose(); + } + + @Override + public Throwable getError() { + return impl.getError(); + } + + /** + * @return the audio balance (the leftness or rightness of the audio). + */ + @Override + public double getBalance() { + return impl.getBalance(); + } + + @Override + public Duration getBufferProgressTime() { + return impl.getBufferProgressTime(); + } + + @Override + public int getCurrentCount() { + return impl.getCurrentCount(); + } + + /** + * @return the speed the video is set to play at + * + * Not to be confused with {@link #getRate()} + */ + @Override + public double getCurrentRate() { + return impl.getCurrentRate(); + } + + /** + * @return the current time elapsed in the video + */ + @Override + public Duration getCurrentTime() { + return impl.getCurrentTime(); + } + + /** + * @return the current playback speed of the video, + * regardless of settings. + * + * For example if {@link #setRate(double)} is called + * with a value of 1.0, and then the player is paused, + * this will return 0.0. + */ + @Override + public double getRate() { + return impl.getRate(); + } + + @Override + public Duration getStartTime() { + return impl.getStartTime(); + } + + @Override + public Duration getStopTime() { + return impl.getStopTime(); + } + + @Override + public Duration getTotalDuration() { + return impl.getTotalDuration(); + } + + @Override + public double getVolume() { + return impl.getVolume(); + } + + @Override + public void pause() { + impl.pause(); + } + + public void setVideo(VideoResource video) { + impl.setVideo(video); + } + + public void play(VideoResource video) { + impl.play(video); + } + + @Override + public void play() { + impl.play(); + } + + @Override + public void seek(Duration seekTime) { + impl.seek(seekTime); + } + + @Override + public void setBalance(double value) { + impl.setBalance(value); + } + + @Override + public void setRate(double value) { + impl.setRate(value); + } + + @Override + public void setStartTime(Duration value) { + impl.setStartTime(value); + } + + @Override + public void setStopTime(Duration value) { + impl.setStopTime(value); + } + + @Override + public void setVolume(double value) { + impl.setVolume(value); + } + + @Override + public void stop() { + impl.stop(); + } + + @Override + public void render(Graphics2D g) { + getPanel().update(g); + } + + @Override + public Container getPanel() { + return impl.getPanel(); + } + + @Override + public void setVideo(URL url) throws IOException{ + impl.setVideo(url); + } + + @Override + public void play(URL url) throws IOException { + impl.play(url); + } + +} diff --git a/src/de/gurkenlabs/litiengine/video/VideoPlayer.java b/src/de/gurkenlabs/litiengine/video/VideoPlayer.java new file mode 100644 index 000000000..e48c7aca9 --- /dev/null +++ b/src/de/gurkenlabs/litiengine/video/VideoPlayer.java @@ -0,0 +1,67 @@ +package de.gurkenlabs.litiengine.video; + +import java.awt.Container; +import java.io.IOException; +import java.net.URL; +import java.time.Duration; + +import de.gurkenlabs.litiengine.resources.VideoResource; + +/** + * + * UNIMPLEMENTED + * + * THIS INTERFACE IS SUBJECT TO CHANGE DRAMATICALLY + * + */ + +interface VideoPlayer { + void dispose(); + + boolean isStatusUnknown(); + boolean isReady(); + boolean isErrored(); + boolean isPlaying(); + boolean isPaused(); + boolean isBuffering(); + boolean isStopped(); + Status getStatus(); + + Throwable getError(); + double getBalance(); + Duration getBufferProgressTime(); + int getCurrentCount(); + double getCurrentRate(); + Duration getCurrentTime(); + double getRate(); + Duration getStartTime(); + Duration getStopTime(); + Duration getTotalDuration(); + double getVolume(); + void pause(); + void setVideo(VideoResource video); + void setVideo(URL url) throws IOException; + void play(VideoResource video); + void play(URL url) throws IOException; + void play(); + void seek(Duration seekTime); + void setBalance(double value); + void setRate(double value); + void setStartTime(Duration value); + void setStopTime(Duration value); + void setVolume(double value); + void stop(); + Container getPanel(); + + public static enum Status { + DISPOSED, + ERRORED, //HALTED + PAUSED, + PLAYING, + READY, + STALLED, + STOPPED, + UNKNOWN + } + +} From a2c09cd3ab488e9313482e7ca2f8a2650e6e81ba Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sat, 25 Apr 2020 02:11:08 -0400 Subject: [PATCH 20/29] Make VideoManager abstract --- .../litiengine/video/VideoManager.java | 60 +++++++++---------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManager.java b/src/de/gurkenlabs/litiengine/video/VideoManager.java index 27fc877a3..1ce0e54f2 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManager.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManager.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.net.URL; import java.time.Duration; +import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; @@ -19,21 +20,17 @@ * */ -public final class VideoManager extends GuiComponent implements VideoPlayer { +public abstract class VideoManager extends GuiComponent implements VideoPlayer { private static final Logger log = Logger.getLogger(VideoManager.class.getName()); - private static boolean checked = false; - - public static boolean allowNetworkConnections = false; + protected static ArrayList loadedNatives = new ArrayList(); protected VideoPlayer impl; { - if(!checked) { + if(!nativesLoaded()) { try { - - //TODO Load natives - + loadNatives(); } catch (LinkageError e) { log.log(Level.SEVERE, e, () -> e.getMessage()); throw e; @@ -42,16 +39,13 @@ public final class VideoManager extends GuiComponent implements VideoPlayer { throw e; } } - checked = true; + initialize(); } /** * Creates a new VideoManager * - * @throws SecurityException if a security manager exists and it denies access to - * the classloader which loaded this class - * * @throws LinkageError if the native binaries were unable to load */ public VideoManager() { @@ -64,9 +58,6 @@ public VideoManager() { * * @param video the video to load * - * @throws SecurityException if a security manager exists and it denies access to - * the classloader which loaded this class - * * @throws LinkageError if the native binaries were unable to load */ public VideoManager(VideoResource video) { @@ -81,9 +72,6 @@ public VideoManager(VideoResource video) { * @param video the video to load * @param play whether to immediately begin playing the video * - * @throws SecurityException if a security manager exists and it denies access to - * the classloader which loaded this class - * * @throws LinkageError if the native binaries were unable to load */ public VideoManager(VideoResource video, boolean play) { @@ -102,9 +90,6 @@ public VideoManager(VideoResource video, boolean play) { * * @param url the URL of the video * - * @throws SecurityException if a security manager exists and it denies access to - * the classloader which loaded this class - * * @throws LinkageError if the native binaries were unable to load * */ @@ -119,9 +104,6 @@ public VideoManager(URL url) throws NoClassDefFoundError, IOException { * @param url the URL of the video * @param play whether to immediately begin playing the video * - * @throws SecurityException if a security manager exists and it denies access to - * the classloader which loaded this class - * * @throws LinkageError if the native binaries were unable to load */ public VideoManager(URL url, boolean play) throws NoClassDefFoundError, IOException { @@ -137,16 +119,30 @@ public VideoManager(URL url, boolean play) throws NoClassDefFoundError, IOExcept /** * Initializes the media player * + * should set {@link #impl} to an instance of VideoPlayer + * * @throws IllegalStateException if the media player has already been initialized */ - protected void initialize() { - - if(impl != null) { - throw new IllegalStateException("Video player already initialized!"); - } - - //impl = new VideoManagerImpl(); - + protected abstract void initialize(); + + /** + * Load the native library required to play videos with this video manager + * + * Should add a string representation of the library to {@link #loadedNatives} + * if it successfully loads + * + * @throws LinkageError if the library is unable to load + * @throws IllegalStateException if the library is already loaded + */ + protected abstract void loadNatives(); + + /** + * @return true if the native library required to play the video has been loaded + */ + protected abstract boolean nativesLoaded(); + + public static boolean nativeLoaded(String libName) { + return loadedNatives.contains(libName); } /** From fa110a04effaeb5b8e15da689a327aac18be0ce4 Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sat, 25 Apr 2020 03:03:54 -0400 Subject: [PATCH 21/29] Added video manager factory --- .../litiengine/resources/VideoResource.java | 20 +++++- .../litiengine/resources/Videos.java | 8 ++- .../litiengine/video/VideoManager.java | 66 ++----------------- .../litiengine/video/VideoManagerFactory.java | 51 ++++++++++++++ 4 files changed, 79 insertions(+), 66 deletions(-) create mode 100644 src/de/gurkenlabs/litiengine/video/VideoManagerFactory.java diff --git a/src/de/gurkenlabs/litiengine/resources/VideoResource.java b/src/de/gurkenlabs/litiengine/resources/VideoResource.java index 1effb3165..b4cc94f30 100644 --- a/src/de/gurkenlabs/litiengine/resources/VideoResource.java +++ b/src/de/gurkenlabs/litiengine/resources/VideoResource.java @@ -2,21 +2,37 @@ import java.net.URI; +import de.gurkenlabs.litiengine.video.VideoManagerFactory; + public class VideoResource extends NamedResource { + private final String player; private final String uri; public VideoResource(String uri, String name) { + this(VideoManagerFactory.getDefaultPlayer(), uri, name); + } + + public VideoResource(URI uri, String name) { + this(VideoManagerFactory.getDefaultPlayer(), uri, name); + } + + public VideoResource(String player, String uri, String name) { + this.player = player; this.uri = uri; setName(name); } - public VideoResource(URI uri, String name) { - this(uri.toString(), name); + public VideoResource(String player, URI uri, String name) { + this(player, uri.toString(), name); } public String getURI() { return uri; } + public String getPlayerType() { + return player; + } + } diff --git a/src/de/gurkenlabs/litiengine/resources/Videos.java b/src/de/gurkenlabs/litiengine/resources/Videos.java index 5e6c21640..910a22e72 100644 --- a/src/de/gurkenlabs/litiengine/resources/Videos.java +++ b/src/de/gurkenlabs/litiengine/resources/Videos.java @@ -3,6 +3,7 @@ import java.net.URL; import de.gurkenlabs.litiengine.video.VideoManager; +import de.gurkenlabs.litiengine.video.VideoManagerFactory; public class Videos extends ResourcesContainer{ @@ -13,14 +14,17 @@ public VideoManager load(VideoResource video) throws NoClassDefFoundError { } public VideoManager load(VideoResource video, boolean play) throws NoClassDefFoundError { - VideoManager videoManager = new VideoManager(video, play); + VideoManager videoManager = VideoManagerFactory.create(video); + if(play) { + videoManager.play(); + } this.add(video.getName(), videoManager); return videoManager; } @Override protected VideoManager load(URL resourceName) throws Exception, NoClassDefFoundError { - return new VideoManager(resourceName); + return VideoManagerFactory.create(new VideoResource(resourceName.toURI(), resourceName.toString())); } } diff --git a/src/de/gurkenlabs/litiengine/video/VideoManager.java b/src/de/gurkenlabs/litiengine/video/VideoManager.java index 1ce0e54f2..3b9104eab 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManager.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManager.java @@ -44,78 +44,20 @@ public abstract class VideoManager extends GuiComponent implements VideoPlayer { } /** - * Creates a new VideoManager + * Creates a new VideoManager which can play the + * specified video. * - * @throws LinkageError if the native binaries were unable to load - */ - public VideoManager() { - super(0,0); - }; - - /** - * Creates a new VideoManager which load the - * specified video without playing it. + * Subclasses MUST overwrite this constructor * * @param video the video to load * * @throws LinkageError if the native binaries were unable to load */ - public VideoManager(VideoResource video) { + protected VideoManager(VideoResource video) { super(0,0); setVideo(video); } - /** - * Creates a new VideoManager which will load the - * specified video, and play it if specified. - * - * @param video the video to load - * @param play whether to immediately begin playing the video - * - * @throws LinkageError if the native binaries were unable to load - */ - public VideoManager(VideoResource video, boolean play) { - super(0,0); - if(play) { - play(video); - } - else { - setVideo(video); - } - } - - /** - * Creates a new VideoManager which will load the - * specified video, and play it if specified. - * - * @param url the URL of the video - * - * @throws LinkageError if the native binaries were unable to load - * - */ - public VideoManager(URL url) throws NoClassDefFoundError, IOException { - this(url, false); - } - - /** - * Creates a new video manager which will load the specified video, and play it if - * desired - * - * @param url the URL of the video - * @param play whether to immediately begin playing the video - * - * @throws LinkageError if the native binaries were unable to load - */ - public VideoManager(URL url, boolean play) throws NoClassDefFoundError, IOException { - super(0,0); - if(play) { - play(url); - } - else { - setVideo(url); - } - } - /** * Initializes the media player * diff --git a/src/de/gurkenlabs/litiengine/video/VideoManagerFactory.java b/src/de/gurkenlabs/litiengine/video/VideoManagerFactory.java new file mode 100644 index 000000000..873ddd43b --- /dev/null +++ b/src/de/gurkenlabs/litiengine/video/VideoManagerFactory.java @@ -0,0 +1,51 @@ +package de.gurkenlabs.litiengine.video; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; + +import de.gurkenlabs.litiengine.resources.VideoResource; + +public final class VideoManagerFactory { + + private VideoManagerFactory() { + throw new UnsupportedOperationException(); + } + + private static final HashMap> PLAYERS = new HashMap>(); + private static String DEFAULT_VIDEO_PLAYER; + + public static void registerPlayerType(String name, Class clazz) { + if(PLAYERS.containsKey(name)) { + throw new IllegalStateException("Video player with name " + name + " already registered!"); + } + PLAYERS.put(name, clazz); + if(DEFAULT_VIDEO_PLAYER == null) { + setDefaultPlayer(name); + } + } + + public static void setDefaultPlayer(String name) { + if(PLAYERS.containsKey(name)) { + DEFAULT_VIDEO_PLAYER = name; + } + else { + throw new IllegalArgumentException("Player " + name + " is not registered"); + } + } + + public static String getDefaultPlayer() { + return DEFAULT_VIDEO_PLAYER; + } + + public static VideoManager create(VideoResource videoResource) { + try { + Constructor c = PLAYERS.get(videoResource.getPlayerType()).getConstructor(VideoResource.class); + c.setAccessible(true); + return c.newInstance(videoResource); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { + throw new Error(e); + } + } + +} From 0343693ee16529c0dbe89d779bee38c5a6c54ac2 Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sat, 25 Apr 2020 03:53:01 -0400 Subject: [PATCH 22/29] VideoManagerImpl -> JavaFXVideoManager --- ...nagerImpl.java => JavaFXVideoManager.java} | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) rename src/de/gurkenlabs/litiengine/video/{VideoManagerImpl.java => JavaFXVideoManager.java} (84%) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java b/src/de/gurkenlabs/litiengine/video/JavaFXVideoManager.java similarity index 84% rename from src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java rename to src/de/gurkenlabs/litiengine/video/JavaFXVideoManager.java index 96907fe50..fe32d6ecb 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManagerImpl.java +++ b/src/de/gurkenlabs/litiengine/video/JavaFXVideoManager.java @@ -6,6 +6,7 @@ import java.io.IOException; import java.io.UncheckedIOException; import java.net.URL; +import java.util.logging.Level; import javax.net.ssl.SSLHandshakeException; import javax.swing.JComponent; @@ -21,11 +22,22 @@ import javafx.scene.media.MediaPlayer; import javafx.scene.media.MediaView; -final class VideoManagerImpl implements VideoPlayer{ - +public final class JavaFXVideoManager extends VideoManager{ + private volatile JFXPanel panel = new JFXPanel(); private volatile MediaView mediaView; + public static boolean allowNetworkConnections = false; + public static final String NAME = "javaFX"; + + public static void register() { + VideoManagerFactory.registerPlayerType(NAME, JavaFXVideoManager.class); + } + + protected JavaFXVideoManager(VideoResource video) { + super(video); + } + @Override public synchronized void setVideo(VideoResource video) { if(video.getURI().startsWith("http")) { @@ -48,7 +60,7 @@ public synchronized void play(VideoResource video) { @Override public synchronized void setVideo(URL url) throws IOException { if(url.getProtocol().startsWith("http")) { - if(!VideoManager.allowNetworkConnections) { + if(!allowNetworkConnections) { throw new IOException("Network access disallowed"); } if(url.getProtocol().equals("http")) { @@ -339,5 +351,35 @@ private MediaPlayer getPlayer() { private boolean playerValid() { return getPlayer() != null; } + + @Override + protected void initialize() { + //no special initialization code needed for javafx + } + + @Override + protected void loadNatives() { + try { + ClassLoader classLoader = VideoManager.class.getClassLoader(); + Class.forName("javafx.scene.media.MediaPlayer", false, classLoader); + } catch (ClassNotFoundException e) { + NoClassDefFoundError err = new NoClassDefFoundError("JavaFX is not installed!"); + err.initCause(e); + log.log(Level.SEVERE, err, () -> err.getMessage()); + throw err; + } catch (LinkageError e) { + log.log(Level.SEVERE, e, () -> e.getMessage()); + throw e; + } catch (SecurityException e) { + log.log(Level.SEVERE, e, () -> e.getMessage()); + throw e; + } + loadedNatives.add(NAME); + } + + @Override + protected boolean nativesLoaded() { + return loadedNatives.contains(NAME); + } } From dbbf2e4aa8ed7833649836759f579c243dccec70 Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sat, 25 Apr 2020 03:55:45 -0400 Subject: [PATCH 23/29] change visibility --- src/de/gurkenlabs/litiengine/video/VideoManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManager.java b/src/de/gurkenlabs/litiengine/video/VideoManager.java index 3b9104eab..66380de90 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManager.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManager.java @@ -22,10 +22,10 @@ public abstract class VideoManager extends GuiComponent implements VideoPlayer { - private static final Logger log = Logger.getLogger(VideoManager.class.getName()); + protected static final Logger log = Logger.getLogger(VideoManager.class.getName()); protected static ArrayList loadedNatives = new ArrayList(); - protected VideoPlayer impl; + private VideoPlayer impl; { if(!nativesLoaded()) { From 355e78ef0b28c14854ed71dde0904feff2df3d1f Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sat, 25 Apr 2020 04:00:27 -0400 Subject: [PATCH 24/29] Remove unecessary method overrides --- .../litiengine/video/VideoManager.java | 230 ------------------ 1 file changed, 230 deletions(-) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManager.java b/src/de/gurkenlabs/litiengine/video/VideoManager.java index 66380de90..c8a7675dd 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManager.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManager.java @@ -1,10 +1,6 @@ package de.gurkenlabs.litiengine.video; -import java.awt.Container; import java.awt.Graphics2D; -import java.io.IOException; -import java.net.URL; -import java.time.Duration; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; @@ -12,21 +8,11 @@ import de.gurkenlabs.litiengine.gui.GuiComponent; import de.gurkenlabs.litiengine.resources.VideoResource; -/** - * - * UNIMPLEMENTED - * - * THIS CLASS IS SUBJECT TO CHANGE DRAMATICALLY - * - */ - public abstract class VideoManager extends GuiComponent implements VideoPlayer { protected static final Logger log = Logger.getLogger(VideoManager.class.getName()); protected static ArrayList loadedNatives = new ArrayList(); - private VideoPlayer impl; - { if(!nativesLoaded()) { try { @@ -86,225 +72,9 @@ protected VideoManager(VideoResource video) { public static boolean nativeLoaded(String libName) { return loadedNatives.contains(libName); } - - /** - * @return true if the status of the video player is unknown. - * - * This is generally the State of the player immediately after - * creation. - */ - @Override - public boolean isStatusUnknown() { - return impl.isStatusUnknown(); - } - /** - * @return true if the video is ready to play. - */ - @Override - public boolean isReady() { - return impl.isReady(); - } - - /** - * @return true if a critical error has occured during video playback. - * - * This means that playback can never continue again with this VideoManager - * and a new VideoManager should be created. - */ - @Override - public boolean isErrored() { - return impl.isErrored(); - } - - @Override - public boolean isPlaying() { - return impl.isPlaying(); - } - - @Override - public boolean isPaused() { - return impl.isPaused(); - } - - /** - * @return true if the video has stopped playing because the - * buffer has slowed or stopped. - */ - @Override - public boolean isBuffering() { - return impl.isBuffering(); - } - - /** - * @return true if playback has been stopped under normal conditions - */ - @Override - public boolean isStopped() { - return impl.isStopped(); - } - - /** - * @return the status of the video player - */ - @Override - public Status getStatus() { - return impl.getStatus(); - } - - /** - * Free all resources associated with this player. - */ - @Override - public void dispose() { - impl.dispose(); - } - - @Override - public Throwable getError() { - return impl.getError(); - } - - /** - * @return the audio balance (the leftness or rightness of the audio). - */ - @Override - public double getBalance() { - return impl.getBalance(); - } - - @Override - public Duration getBufferProgressTime() { - return impl.getBufferProgressTime(); - } - - @Override - public int getCurrentCount() { - return impl.getCurrentCount(); - } - - /** - * @return the speed the video is set to play at - * - * Not to be confused with {@link #getRate()} - */ - @Override - public double getCurrentRate() { - return impl.getCurrentRate(); - } - - /** - * @return the current time elapsed in the video - */ - @Override - public Duration getCurrentTime() { - return impl.getCurrentTime(); - } - - /** - * @return the current playback speed of the video, - * regardless of settings. - * - * For example if {@link #setRate(double)} is called - * with a value of 1.0, and then the player is paused, - * this will return 0.0. - */ - @Override - public double getRate() { - return impl.getRate(); - } - - @Override - public Duration getStartTime() { - return impl.getStartTime(); - } - - @Override - public Duration getStopTime() { - return impl.getStopTime(); - } - - @Override - public Duration getTotalDuration() { - return impl.getTotalDuration(); - } - - @Override - public double getVolume() { - return impl.getVolume(); - } - - @Override - public void pause() { - impl.pause(); - } - - public void setVideo(VideoResource video) { - impl.setVideo(video); - } - - public void play(VideoResource video) { - impl.play(video); - } - - @Override - public void play() { - impl.play(); - } - - @Override - public void seek(Duration seekTime) { - impl.seek(seekTime); - } - - @Override - public void setBalance(double value) { - impl.setBalance(value); - } - - @Override - public void setRate(double value) { - impl.setRate(value); - } - - @Override - public void setStartTime(Duration value) { - impl.setStartTime(value); - } - - @Override - public void setStopTime(Duration value) { - impl.setStopTime(value); - } - - @Override - public void setVolume(double value) { - impl.setVolume(value); - } - - @Override - public void stop() { - impl.stop(); - } - @Override public void render(Graphics2D g) { getPanel().update(g); } - - @Override - public Container getPanel() { - return impl.getPanel(); - } - - @Override - public void setVideo(URL url) throws IOException{ - impl.setVideo(url); - } - - @Override - public void play(URL url) throws IOException { - impl.play(url); - } - } From 7138a8f3f60208c14f51387d10fe2b84f063e7f5 Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sat, 25 Apr 2020 05:06:56 -0400 Subject: [PATCH 25/29] Fix NoSuchMethodException --- src/de/gurkenlabs/litiengine/video/VideoManagerFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManagerFactory.java b/src/de/gurkenlabs/litiengine/video/VideoManagerFactory.java index 873ddd43b..ac2ed6efb 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManagerFactory.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManagerFactory.java @@ -40,7 +40,7 @@ public static String getDefaultPlayer() { public static VideoManager create(VideoResource videoResource) { try { - Constructor c = PLAYERS.get(videoResource.getPlayerType()).getConstructor(VideoResource.class); + Constructor c = PLAYERS.get(videoResource.getPlayerType()).getDeclaredConstructor(VideoResource.class); c.setAccessible(true); return c.newInstance(videoResource); } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { From d1dac5a647421d47044cc3c234332dc504b2d06b Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sat, 25 Apr 2020 05:07:25 -0400 Subject: [PATCH 26/29] Fix NullPointerException --- src/de/gurkenlabs/litiengine/video/JavaFXVideoManager.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/de/gurkenlabs/litiengine/video/JavaFXVideoManager.java b/src/de/gurkenlabs/litiengine/video/JavaFXVideoManager.java index fe32d6ecb..49cdf81c5 100644 --- a/src/de/gurkenlabs/litiengine/video/JavaFXVideoManager.java +++ b/src/de/gurkenlabs/litiengine/video/JavaFXVideoManager.java @@ -159,6 +159,9 @@ public boolean isStopped() { } public VideoPlayer.Status getStatus() { + if(getPlayer() == null) { + return Status.UNKNOWN; + } switch (getPlayer().getStatus()) { case DISPOSED: return Status.DISPOSED; From 0d23c0def736c9b02ba2f9e7f6dd232bf61737a5 Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sat, 25 Apr 2020 05:08:17 -0400 Subject: [PATCH 27/29] Fix missing toolkit caused by the new changes --- src/de/gurkenlabs/litiengine/video/JavaFXVideoManager.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/de/gurkenlabs/litiengine/video/JavaFXVideoManager.java b/src/de/gurkenlabs/litiengine/video/JavaFXVideoManager.java index 49cdf81c5..8993b92ad 100644 --- a/src/de/gurkenlabs/litiengine/video/JavaFXVideoManager.java +++ b/src/de/gurkenlabs/litiengine/video/JavaFXVideoManager.java @@ -24,7 +24,7 @@ public final class JavaFXVideoManager extends VideoManager{ - private volatile JFXPanel panel = new JFXPanel(); + private volatile JFXPanel panel; private volatile MediaView mediaView; public static boolean allowNetworkConnections = false; @@ -40,6 +40,7 @@ protected JavaFXVideoManager(VideoResource video) { @Override public synchronized void setVideo(VideoResource video) { + this.panel = new JFXPanel(); if(video.getURI().startsWith("http")) { try { setVideo(new URL(video.getURI())); @@ -52,8 +53,8 @@ public synchronized void setVideo(VideoResource video) { @Override public synchronized void play(VideoResource video) { - setVideo(video); while(isStatusUnknown()); + setVideo(video); play(); } @@ -72,8 +73,8 @@ public synchronized void setVideo(URL url) throws IOException { @Override public synchronized void play(URL url) throws IOException { - setVideo(url); while(isStatusUnknown()); + setVideo(url); play(); } From 9a371b1c7810cded8aaf3d5337060252fc9b0c09 Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sat, 25 Apr 2020 05:24:42 -0400 Subject: [PATCH 28/29] Fix javadoc --- src/de/gurkenlabs/litiengine/video/VideoManager.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/de/gurkenlabs/litiengine/video/VideoManager.java b/src/de/gurkenlabs/litiengine/video/VideoManager.java index c8a7675dd..4cc64cf3e 100644 --- a/src/de/gurkenlabs/litiengine/video/VideoManager.java +++ b/src/de/gurkenlabs/litiengine/video/VideoManager.java @@ -47,8 +47,6 @@ protected VideoManager(VideoResource video) { /** * Initializes the media player * - * should set {@link #impl} to an instance of VideoPlayer - * * @throws IllegalStateException if the media player has already been initialized */ protected abstract void initialize(); From 2716c97def20534d346894c116ba38b71bb1259f Mon Sep 17 00:00:00 2001 From: Gamebuster19901 Date: Sat, 25 Apr 2020 05:28:28 -0400 Subject: [PATCH 29/29] Fix missing toolkit for url videos --- src/de/gurkenlabs/litiengine/video/JavaFXVideoManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/de/gurkenlabs/litiengine/video/JavaFXVideoManager.java b/src/de/gurkenlabs/litiengine/video/JavaFXVideoManager.java index 8993b92ad..6e34f9147 100644 --- a/src/de/gurkenlabs/litiengine/video/JavaFXVideoManager.java +++ b/src/de/gurkenlabs/litiengine/video/JavaFXVideoManager.java @@ -60,6 +60,7 @@ public synchronized void play(VideoResource video) { @Override public synchronized void setVideo(URL url) throws IOException { + this.panel = new JFXPanel(); if(url.getProtocol().startsWith("http")) { if(!allowNetworkConnections) { throw new IOException("Network access disallowed");