add audio track selection popup, slider displays time as h:mm:ss now
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Jannik 2020-07-09 19:42:26 +02:00
parent 834bffda93
commit d210655dcf
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
6 changed files with 123 additions and 26 deletions

View File

@ -51,13 +51,13 @@
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
<version>2.6</version> <version>2.7</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.jfoenix</groupId> <groupId>com.jfoenix</groupId>
<artifactId>jfoenix</artifactId> <artifactId>jfoenix</artifactId>
<version>9.0.9</version> <version>9.0.10</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -77,6 +77,7 @@ public class Player {
pane = (AnchorPane) fxmlLoader.load(); pane = (AnchorPane) fxmlLoader.load();
stage = new Stage(); stage = new Stage();
scene = new Scene(pane); scene = new Scene(pane);
scene.getStylesheets().add(getClass().getResource("/css/Player.css").toExternalForm());
stage.setScene(scene); stage.setScene(scene);
stage.setTitle("HomeFlix"); stage.setTitle("HomeFlix");
stage.getIcons().add(new Image(Main.class.getResourceAsStream("/icons/Homeflix_Icon_64x64.png"))); stage.getIcons().add(new Image(Main.class.getResourceAsStream("/icons/Homeflix_Icon_64x64.png")));

View File

@ -23,6 +23,8 @@
package org.mosad.homeflix.player; package org.mosad.homeflix.player;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -33,6 +35,7 @@ import org.mosad.homeflix.datatypes.FilmTabelDataType;
import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialogLayout; import com.jfoenix.controls.JFXDialogLayout;
import com.jfoenix.controls.JFXListView;
import com.jfoenix.controls.JFXPopup; import com.jfoenix.controls.JFXPopup;
import com.jfoenix.controls.JFXPopup.PopupHPosition; import com.jfoenix.controls.JFXPopup.PopupHPosition;
import com.jfoenix.controls.JFXPopup.PopupVPosition; import com.jfoenix.controls.JFXPopup.PopupVPosition;
@ -44,6 +47,7 @@ import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.scene.Cursor; import javafx.scene.Cursor;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.image.Image; import javafx.scene.image.Image;
@ -54,11 +58,14 @@ import javafx.scene.image.WritableImage;
import javafx.scene.input.MouseEvent; import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import javafx.scene.media.MediaView; import javafx.scene.media.MediaView;
import javafx.scene.text.Text; import javafx.scene.text.Text;
import javafx.util.StringConverter;
import uk.co.caprica.vlcj.factory.MediaPlayerFactory; import uk.co.caprica.vlcj.factory.MediaPlayerFactory;
import uk.co.caprica.vlcj.player.base.MediaPlayer; import uk.co.caprica.vlcj.player.base.MediaPlayer;
import uk.co.caprica.vlcj.player.base.TrackDescription;
import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer; import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer;
import uk.co.caprica.vlcj.player.embedded.videosurface.CallbackVideoSurface; import uk.co.caprica.vlcj.player.embedded.videosurface.CallbackVideoSurface;
import uk.co.caprica.vlcj.player.embedded.videosurface.VideoSurfaceAdapters; import uk.co.caprica.vlcj.player.embedded.videosurface.VideoSurfaceAdapters;
@ -107,6 +114,8 @@ public class PlayerController {
private long endTime = 0; private long endTime = 0;
private long skipTime = 0; private long skipTime = 0;
private long duration = 0; private long duration = 0;
private List<TrackDescription> tracks = new ArrayList<>();
private int currentTrack = 0;
private int season = 0; private int season = 0;
private int episode = 0; private int episode = 0;
@ -119,6 +128,8 @@ public class PlayerController {
private Image fullscreen = new Image("icons/baseline_fullscreen_white_48dp.png"); private Image fullscreen = new Image("icons/baseline_fullscreen_white_48dp.png");
private Image fullscreenExit = new Image("icons/baseline_fullscreen_exit_white_48dp.png"); private Image fullscreenExit = new Image("icons/baseline_fullscreen_exit_white_48dp.png");
private JFXPopup audioPopup;
/** /**
* create a new PlayerWindow object * create a new PlayerWindow object
* @param player the player object (needed for closing action) * @param player the player object (needed for closing action)
@ -150,6 +161,11 @@ public class PlayerController {
initPlayerWindow(); initPlayerWindow();
initMediaPlayer(); initMediaPlayer();
initTimeSlider(); initTimeSlider();
Pane thumb = (Pane) timeSlider.lookup(".thumb");
System.out.println(thumb.getChildren());
} }
/** /**
@ -162,7 +178,7 @@ public class PlayerController {
// hide controls timer initialization // hide controls timer initialization
final Timer timer = new Timer(); final Timer timer = new Timer();
TimerTask controlAnimationTask = null; // task to execute save operation TimerTask controlAnimationTask = null; // task to execute save operation
final long delayTime = 3000; // hide the controls after 2 seconds final long delayTime = 4000; // hide the controls after 2 seconds
@Override @Override
public void handle(MouseEvent mouseEvent) { public void handle(MouseEvent mouseEvent) {
@ -181,6 +197,7 @@ public class PlayerController {
controlAnimationTask = new TimerTask() { controlAnimationTask = new TimerTask() {
@Override @Override
public void run() { public void run() {
// TODO a animation would be nice
hBoxTop.setVisible(false); hBoxTop.setVisible(false);
bottomVBox.setVisible(false); bottomVBox.setVisible(false);
player.getScene().setCursor(Cursor.NONE); player.getScene().setCursor(Cursor.NONE);
@ -200,12 +217,8 @@ public class PlayerController {
@Override @Override
public void mediaPlayerReady(MediaPlayer mediaPlayer) { public void mediaPlayerReady(MediaPlayer mediaPlayer) {
System.out.println(mediaPlayer.audio().trackCount()); tracks = mediaPlayer.audio().trackDescriptions();
currentTrack = mediaPlayer.audio().track();
mediaPlayer.audio().trackDescriptions().forEach(trackDesc -> {
System.out.println(trackDesc.description());
});
} }
@Override @Override
@ -226,7 +239,7 @@ public class PlayerController {
@Override @Override
public void lengthChanged(MediaPlayer mediaPlayer, long newLength) { public void lengthChanged(MediaPlayer mediaPlayer, long newLength) {
duration = newLength; duration = newLength;
timeSlider.setMax((duration / 1000) / 60); // TODO move timeslider to seconds timeSlider.setMax(duration / 1000);
} }
}); });
@ -256,9 +269,38 @@ public class PlayerController {
timeSlider.valueProperty().addListener(new ChangeListener<Number>() { timeSlider.valueProperty().addListener(new ChangeListener<Number>() {
@Override @Override
public void changed(ObservableValue<? extends Number> ov, Number old_val, Number new_val) { public void changed(ObservableValue<? extends Number> ov, Number old_val, Number new_val) {
skipTime = ((new_val.longValue() * 1000 * 60) - currentTime); skipTime = ((new_val.longValue() * 1000) - currentTime);
//System.out.println(timeSlider.getChildrenUnmodifiable());
} }
}); });
timeSlider.setOnMouseMoved(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
//System.out.println("TEST");
}
});
// show h:mm:ss in the animated thumb
StringConverter<Double> convert = new StringConverter<Double>() {
@Override
public String toString(Double object) {
long time = object.longValue();
return String.format("%d:%02d:%02d", TimeUnit.SECONDS.toHours(time) % 24,
TimeUnit.SECONDS.toMinutes(time) % 60, TimeUnit.SECONDS.toSeconds(time) % 60);
}
@Override
public Double fromString(String string) {
return null;
}
};
timeSlider.setLabelFormatter(convert);
// TODO add a preview to the animated thumb, if that's possible
} }
public void start() { public void start() {
@ -283,7 +325,7 @@ public class PlayerController {
private void updateControls() { private void updateControls() {
// update slider position, if the mouse does not press on the time // update slider position, if the mouse does not press on the time
if (!mousePressed) { if (!mousePressed) {
timeSlider.setValue((currentTime / 1000) / 60); timeSlider.setValue(currentTime / 1000);
} }
// update endTime label // update endTime label
@ -341,17 +383,38 @@ public class PlayerController {
@FXML @FXML
void btnAudioAction(ActionEvent event) { void btnAudioAction(ActionEvent event) {
// TODO move to separate class "AudioPopup" if (audioPopup == null) {
audioPopup = new JFXPopup();
JFXDialogLayout content = new JFXDialogLayout(); JFXListView<String> list = new JFXListView<String>();
content.setHeading(new Text("Test")); tracks.forEach(track -> {
content.setBody(new Text("Hallo 123")); list.getItems().add(track.description());
content.setPrefSize(150, 200); });
JFXPopup popup = new JFXPopup(); list.getSelectionModel().select(currentTrack);
popup.setPopupContent(content); list.setOnMouseClicked(ev -> {
popup.show(btnAudio, PopupVPosition.BOTTOM, PopupHPosition.RIGHT, setAudioTrack(list.getSelectionModel().getSelectedIndex());
0, -1 * bottomVBox.getHeight()); audioPopup.hide();
});
// TODO style the JFXListView
JFXDialogLayout content = new JFXDialogLayout();
content.setPrefSize(150, 200);
content.setHeading(new Text("Audio"));
content.setBody(list);
content.setPadding(new Insets(-20, -20, -20, -20)); // fix JFXDialogLayout padding
content.setSpacing(-10); // fix JFXDialogLayout spacing
audioPopup.setPopupContent(content);
}
if (!audioPopup.isShowing()) {
// TODO this does not work properly
audioPopup.show(btnAudio, PopupVPosition.BOTTOM, PopupHPosition.RIGHT,
0, -1 * bottomVBox.getHeight());
} else {
audioPopup.hide();
}
} }
@FXML @FXML
@ -371,6 +434,9 @@ public class PlayerController {
playNextMedia(); playNextMedia();
} }
/**
* play the next media
*/
private void playNextMedia() { private void playNextMedia() {
autoplay = false; autoplay = false;
DBController.getInstance().setCurrentTime(media.getStreamUrl(), 0); // reset old video start time DBController.getInstance().setCurrentTime(media.getStreamUrl(), 0); // reset old video start time
@ -382,6 +448,15 @@ public class PlayerController {
} }
} }
/**
* change the audio track
* @param track the index of the audio track
*/
private void setAudioTrack(int track) {
embeddedMediaPlayer.audio().setTrack(track);
currentTrack = track;
}
public double getCurrentTime() { public double getCurrentTime() {
return currentTime; return currentTime;
} }

View File

@ -209,4 +209,3 @@
.scroll-pane > .viewport { .scroll-pane > .viewport {
-fx-background-color: transparent; -fx-background-color: transparent;
} }

View File

@ -0,0 +1,22 @@
/*******************************************************************************
* *
* Slider *
* *
******************************************************************************/
.jfx-slider .slider-value{
-fx-rotate: 0;
}
/*
.jfx-slider > .track {
-fx-background-color: yellow;
}
*/
.jfx-slider .animated-thumb{
-fx-rotate: 0;
-fx-pref-height: 30;
-fx-pref-width: 80;
-fx-background-color: #0F9D58;
-fx-background-radius: 50% 50% 50% 50%;
}