From e31f7d05fb602b330e52de69e9da3d5b739d760f Mon Sep 17 00:00:00 2001 From: Werner Randelshofer Date: Sun, 18 Aug 2024 15:33:46 +0200 Subject: [PATCH] Make player controller even smaller. --- .../movieplayer/MainWindowController.java | 16 ++++++ .../movieplayer/PlayerControlsController.java | 7 --- .../movieplayer/fxplayer/FXAudioTrack.java | 40 +++++++++++++++ .../javafx/movieplayer/fxplayer/FXMedia.java | 43 ++++++++++++++-- .../movieplayer/fxplayer/FXSubtitleTrack.java | 42 ++++++++++++++++ .../movieplayer/fxplayer/FXVideoTrack.java | 50 +++++++++++++++++++ .../movieplayer/monteplayer/PlayerEngine.java | 10 ++-- .../demo/javafx/movieplayer/Labels.properties | 5 +- .../demo/javafx/movieplayer/MainWindow.fxml | 10 +++- .../javafx/movieplayer/PlayerControls.fxml | 15 +++--- 10 files changed, 212 insertions(+), 26 deletions(-) create mode 100644 org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/fxplayer/FXAudioTrack.java create mode 100644 org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/fxplayer/FXSubtitleTrack.java create mode 100644 org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/fxplayer/FXVideoTrack.java diff --git a/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/MainWindowController.java b/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/MainWindowController.java index 5e85539..8c99f76 100644 --- a/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/MainWindowController.java +++ b/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/MainWindowController.java @@ -87,6 +87,22 @@ void open(ActionEvent event) { } } + @FXML + void play(ActionEvent event) { + MediaPlayerInterface player = getPlayer(); + if (player != null) { + player.play(); + } + } + + @FXML + void pause(ActionEvent event) { + MediaPlayerInterface player = getPlayer(); + if (player != null) { + player.pause(); + } + } + private Stage getStage() { Scene scene = rootPane.getScene(); return scene == null ? null : (Stage) scene.getWindow(); diff --git a/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/PlayerControlsController.java b/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/PlayerControlsController.java index 69af529..a4d96cd 100644 --- a/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/PlayerControlsController.java +++ b/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/PlayerControlsController.java @@ -69,8 +69,6 @@ public class PlayerControlsController extends AnchorPane { @FXML // fx:id="timeSlider" private Slider timeSlider; // Value injected by FXMLLoader - @FXML // fx:id="volumeSlider" - private Slider volumeSlider; // Value injected by FXMLLoader private final ObjectProperty player = new SimpleObjectProperty<>(); @@ -143,16 +141,13 @@ void initialize() { assert rootPane != null : "fx:id=\"rootPane\" was not injected: check your FXML file 'PlayerControls.fxml'."; assert timeLabel != null : "fx:id=\"timeLabel\" was not injected: check your FXML file 'PlayerControls.fxml'."; assert timeSlider != null : "fx:id=\"timeSlider\" was not injected: check your FXML file 'PlayerControls.fxml'."; - assert volumeSlider != null : "fx:id=\"volumeSlider\" was not injected: check your FXML file 'PlayerControls.fxml'."; ControllerPaneMouseDraggedHandler dh = new ControllerPaneMouseDraggedHandler(this); ControllerPaneVisibleHandler vh = new ControllerPaneVisibleHandler(this); player.addListener(this::playerChanged); - volumeSlider.disableProperty().bind(muteButton.selectedProperty()); muteButton.visibleProperty().bind(hasAudio); - volumeSlider.visibleProperty().bind(hasAudio); timeSlider.valueProperty().addListener(this::timeSliderChanged); } @@ -195,7 +190,6 @@ private void playerChanged(Observable observable, MediaPlayerInterface oldValue, oldValue.currentTimeProperty().removeListener(currentTimeHandler); timeLabel.textProperty().unbind(); newValue.statusProperty().removeListener(statusChangeListener); - volumeSlider.valueProperty().unbindBidirectional(oldValue.volumeProperty()); muteButton.selectedProperty().unbindBidirectional(oldValue.muteProperty()); oldValue.getMedia().getTracks().removeListener(trackHandler); } @@ -208,7 +202,6 @@ private void playerChanged(Observable observable, MediaPlayerInterface oldValue, )); newValue.currentTimeProperty().addListener(currentTimeHandler); newValue.statusProperty().addListener(statusChangeListener); - volumeSlider.valueProperty().bindBidirectional(newValue.volumeProperty()); muteButton.selectedProperty().bindBidirectional(newValue.muteProperty()); newValue.getMedia().getTracks().addListener(trackHandler); } diff --git a/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/fxplayer/FXAudioTrack.java b/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/fxplayer/FXAudioTrack.java new file mode 100644 index 0000000..66453a7 --- /dev/null +++ b/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/fxplayer/FXAudioTrack.java @@ -0,0 +1,40 @@ +/* + * @(#)FXTrack.java + * Copyright © 2024 Werner Randelshofer, Switzerland. MIT License. + */ + +package org.monte.demo.javafx.movieplayer.fxplayer; + +import javafx.scene.media.AudioTrack; +import org.monte.demo.javafx.movieplayer.model.AudioTrackInterface; + +import java.util.Locale; +import java.util.Map; + +public class FXAudioTrack implements AudioTrackInterface { + private final AudioTrack track; + + public FXAudioTrack(AudioTrack track) { + this.track = track; + } + + @Override + public Locale getLocale() { + return track.getLocale(); + } + + @Override + public Map getMetadata() { + return track.getMetadata(); + } + + @Override + public String getName() { + return track.getName(); + } + + @Override + public long getTrackID() { + return track.getTrackID(); + } +} diff --git a/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/fxplayer/FXMedia.java b/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/fxplayer/FXMedia.java index 37c4f85..ee2c641 100644 --- a/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/fxplayer/FXMedia.java +++ b/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/fxplayer/FXMedia.java @@ -9,9 +9,14 @@ import javafx.beans.property.ReadOnlyIntegerProperty; import javafx.beans.property.ReadOnlyObjectProperty; import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import javafx.collections.ObservableMap; +import javafx.scene.media.AudioTrack; import javafx.scene.media.Media; +import javafx.scene.media.SubtitleTrack; +import javafx.scene.media.Track; +import javafx.scene.media.VideoTrack; import javafx.util.Duration; import org.monte.demo.javafx.movieplayer.model.MediaInterface; import org.monte.demo.javafx.movieplayer.model.TrackInterface; @@ -20,10 +25,44 @@ * Adapter for JavaFX {@link Media}. */ public class FXMedia implements MediaInterface { + private final ObservableList tracks = FXCollections.observableArrayList(); + private final Media media; public FXMedia(Media media) { this.media = media; + for (Track track : media.getTracks()) { + switch (track) { + case VideoTrack t -> tracks.add(new FXVideoTrack(t)); + case AudioTrack t -> tracks.add(new FXAudioTrack(t)); + case SubtitleTrack t -> tracks.add(new FXSubtitleTrack(t)); + default -> tracks.add(new FXTrack(track)); + } + } + + media.getTracks().addListener(new ListChangeListener() { + @Override + public void onChanged(Change c) { + while (c.next()) { + if (c.wasRemoved()) { + tracks.subList(c.getFrom(), c.getTo()).clear(); + ; + } + if (c.wasAdded()) { + int i = c.getFrom(); + for (Track track : c.getAddedSubList()) { + switch (track) { + case VideoTrack t -> tracks.add(i, new FXVideoTrack(t)); + case AudioTrack t -> tracks.add(i, new FXAudioTrack(t)); + case SubtitleTrack t -> tracks.add(i, new FXSubtitleTrack(t)); + default -> tracks.add(i, new FXTrack(track)); + } + i++; + } + } + } + } + }); } @Override @@ -69,9 +108,7 @@ public String getSource() { @Override public ObservableList getTracks() { - ObservableList result = FXCollections.observableArrayList(); - media.getTracks().forEach(t -> result.add(new FXTrack(t))); - return result; + return tracks; } diff --git a/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/fxplayer/FXSubtitleTrack.java b/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/fxplayer/FXSubtitleTrack.java new file mode 100644 index 0000000..4ccb60e --- /dev/null +++ b/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/fxplayer/FXSubtitleTrack.java @@ -0,0 +1,42 @@ + +/* + * @(#)FXTrack.java + * Copyright © 2024 Werner Randelshofer, Switzerland. MIT License. + */ + +package org.monte.demo.javafx.movieplayer.fxplayer; + +import javafx.scene.media.SubtitleTrack; +import org.monte.demo.javafx.movieplayer.model.SubtitleTrackInterface; + +import java.util.Locale; +import java.util.Map; + +public class FXSubtitleTrack implements SubtitleTrackInterface { + private final SubtitleTrack track; + + public FXSubtitleTrack(SubtitleTrack track) { + this.track = track; + } + + + @Override + public Locale getLocale() { + return track.getLocale(); + } + + @Override + public Map getMetadata() { + return track.getMetadata(); + } + + @Override + public String getName() { + return track.getName(); + } + + @Override + public long getTrackID() { + return track.getTrackID(); + } +} diff --git a/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/fxplayer/FXVideoTrack.java b/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/fxplayer/FXVideoTrack.java new file mode 100644 index 0000000..5fc30e2 --- /dev/null +++ b/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/fxplayer/FXVideoTrack.java @@ -0,0 +1,50 @@ +/* + * @(#)FXTrack.java + * Copyright © 2024 Werner Randelshofer, Switzerland. MIT License. + */ + +package org.monte.demo.javafx.movieplayer.fxplayer; + +import javafx.scene.media.VideoTrack; +import org.monte.demo.javafx.movieplayer.model.VideoTrackInterface; + +import java.util.Locale; +import java.util.Map; + +public class FXVideoTrack implements VideoTrackInterface { + private final VideoTrack track; + + public FXVideoTrack(VideoTrack track) { + this.track = track; + } + + @Override + public int getHeight() { + return track.getHeight(); + } + + @Override + public int getWidth() { + return track.getWidth(); + } + + @Override + public Locale getLocale() { + return track.getLocale(); + } + + @Override + public Map getMetadata() { + return track.getMetadata(); + } + + @Override + public String getName() { + return track.getName(); + } + + @Override + public long getTrackID() { + return track.getTrackID(); + } +} diff --git a/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/monteplayer/PlayerEngine.java b/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/monteplayer/PlayerEngine.java index c266f0b..f83a695 100644 --- a/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/monteplayer/PlayerEngine.java +++ b/org.monte.demo.javafx.movieplayer/src/main/java/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/monteplayer/PlayerEngine.java @@ -332,10 +332,12 @@ protected void doStarted() throws Exception { private void stopAudio() { for (var t : media.getTracks()) { if (t instanceof MonteAudioTrack mat) { - SourceDataLine sourceDataLine = mat.getSourceDataLine(); - if (sourceDataLine != null) { - sourceDataLine.flush(); - } + mat.dispatcher.execute(() -> { + SourceDataLine sourceDataLine = mat.getSourceDataLine(); + if (sourceDataLine != null) { + sourceDataLine.flush(); + } + }); } } } diff --git a/org.monte.demo.javafx.movieplayer/src/main/resources/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/Labels.properties b/org.monte.demo.javafx.movieplayer/src/main/resources/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/Labels.properties index 8169330..249cd22 100644 --- a/org.monte.demo.javafx.movieplayer/src/main/resources/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/Labels.properties +++ b/org.monte.demo.javafx.movieplayer/src/main/resources/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/Labels.properties @@ -19,4 +19,7 @@ error.creatingPlayer=Can not play this file view.zoomToActualSize=Zoom to Actual Size view.zoomToFit=Zoom to Fit view.zoomIn=Zoom in -view.zoomOut=Zoom out \ No newline at end of file +view.zoomOut=Zoom out +play.menu=Play +play.menuItem=Play +pause.menuItem=Pause \ No newline at end of file diff --git a/org.monte.demo.javafx.movieplayer/src/main/resources/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/MainWindow.fxml b/org.monte.demo.javafx.movieplayer/src/main/resources/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/MainWindow.fxml index 6437606..1cc82e1 100644 --- a/org.monte.demo.javafx.movieplayer/src/main/resources/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/MainWindow.fxml +++ b/org.monte.demo.javafx.movieplayer/src/main/resources/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/MainWindow.fxml @@ -7,8 +7,8 @@ - @@ -27,6 +27,12 @@ + + + + + + diff --git a/org.monte.demo.javafx.movieplayer/src/main/resources/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/PlayerControls.fxml b/org.monte.demo.javafx.movieplayer/src/main/resources/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/PlayerControls.fxml index 8fa3ab8..7e98362 100644 --- a/org.monte.demo.javafx.movieplayer/src/main/resources/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/PlayerControls.fxml +++ b/org.monte.demo.javafx.movieplayer/src/main/resources/org.monte.demo.javafx.movieplayer/org/monte/demo/javafx/movieplayer/PlayerControls.fxml @@ -15,13 +15,11 @@ + AnchorPane.bottomAnchor="4.0"> - - @@ -31,17 +29,16 @@ -