add audio track selection popup, slider displays time as h:mm:ss now
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is passing
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			This commit is contained in:
		
							
								
								
									
										4
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								pom.xml
									
									
									
									
									
								
							| @ -51,13 +51,13 @@ | ||||
| 		<dependency> | ||||
| 			<groupId>commons-io</groupId> | ||||
| 			<artifactId>commons-io</artifactId> | ||||
| 			<version>2.6</version> | ||||
| 			<version>2.7</version> | ||||
| 		</dependency> | ||||
|  | ||||
| 		<dependency> | ||||
| 			<groupId>com.jfoenix</groupId> | ||||
| 			<artifactId>jfoenix</artifactId> | ||||
| 			<version>9.0.9</version> | ||||
| 			<version>9.0.10</version> | ||||
| 		</dependency> | ||||
|  | ||||
| 		<dependency> | ||||
|  | ||||
| @ -149,7 +149,7 @@ public class MainWindowController { | ||||
|  | ||||
| 		// load data list in gui | ||||
| 		posterModeStartup(); | ||||
| 		 | ||||
|  | ||||
| 		checkAutoUpdate(); // TODO async | ||||
| 	} | ||||
|  | ||||
|  | ||||
| @ -77,6 +77,7 @@ public class Player { | ||||
| 			pane = (AnchorPane) fxmlLoader.load(); | ||||
| 			stage = new Stage(); | ||||
| 			scene = new Scene(pane); | ||||
| 			scene.getStylesheets().add(getClass().getResource("/css/Player.css").toExternalForm()); | ||||
| 			stage.setScene(scene); | ||||
| 			stage.setTitle("HomeFlix"); | ||||
| 			stage.getIcons().add(new Image(Main.class.getResourceAsStream("/icons/Homeflix_Icon_64x64.png"))); | ||||
|  | ||||
| @ -23,6 +23,8 @@ | ||||
| package org.mosad.homeflix.player; | ||||
|  | ||||
| import java.nio.ByteBuffer; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.Timer; | ||||
| import java.util.TimerTask; | ||||
| import java.util.concurrent.TimeUnit; | ||||
| @ -33,6 +35,7 @@ import org.mosad.homeflix.datatypes.FilmTabelDataType; | ||||
|  | ||||
| import com.jfoenix.controls.JFXButton; | ||||
| import com.jfoenix.controls.JFXDialogLayout; | ||||
| import com.jfoenix.controls.JFXListView; | ||||
| import com.jfoenix.controls.JFXPopup; | ||||
| import com.jfoenix.controls.JFXPopup.PopupHPosition; | ||||
| import com.jfoenix.controls.JFXPopup.PopupVPosition; | ||||
| @ -44,6 +47,7 @@ import javafx.beans.value.ObservableValue; | ||||
| import javafx.event.ActionEvent; | ||||
| import javafx.event.EventHandler; | ||||
| import javafx.fxml.FXML; | ||||
| import javafx.geometry.Insets; | ||||
| import javafx.scene.Cursor; | ||||
| import javafx.scene.control.Label; | ||||
| import javafx.scene.image.Image; | ||||
| @ -54,11 +58,14 @@ import javafx.scene.image.WritableImage; | ||||
| import javafx.scene.input.MouseEvent; | ||||
| import javafx.scene.layout.AnchorPane; | ||||
| import javafx.scene.layout.HBox; | ||||
| import javafx.scene.layout.Pane; | ||||
| import javafx.scene.layout.VBox; | ||||
| import javafx.scene.media.MediaView; | ||||
| import javafx.scene.text.Text; | ||||
| import javafx.util.StringConverter; | ||||
| import uk.co.caprica.vlcj.factory.MediaPlayerFactory; | ||||
| 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.videosurface.CallbackVideoSurface; | ||||
| import uk.co.caprica.vlcj.player.embedded.videosurface.VideoSurfaceAdapters; | ||||
| @ -107,6 +114,8 @@ public class PlayerController { | ||||
| 	private long endTime = 0; | ||||
| 	private long skipTime = 0; | ||||
| 	private long duration = 0; | ||||
| 	private List<TrackDescription> tracks = new ArrayList<>(); | ||||
| 	private int currentTrack = 0; | ||||
| 	 | ||||
| 	private int season = 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 fullscreenExit = new Image("icons/baseline_fullscreen_exit_white_48dp.png"); | ||||
| 	 | ||||
| 	private JFXPopup audioPopup; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * create a new PlayerWindow object | ||||
| 	 * @param player	the player object (needed for closing action) | ||||
| @ -150,6 +161,11 @@ public class PlayerController { | ||||
| 		initPlayerWindow(); | ||||
| 		initMediaPlayer(); | ||||
| 		initTimeSlider(); | ||||
| 		 | ||||
| 		 | ||||
| 		Pane thumb = (Pane) timeSlider.lookup(".thumb"); | ||||
| 		System.out.println(thumb.getChildren()); | ||||
| 		 | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| @ -162,11 +178,11 @@ public class PlayerController { | ||||
| 			// hide controls timer initialization | ||||
| 			final Timer timer = new Timer(); | ||||
| 			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 | ||||
| 			public void handle(MouseEvent mouseEvent) { | ||||
|  | ||||
| 				 | ||||
| 				// show controls | ||||
| 				if (!showControls) { | ||||
| 					player.getScene().setCursor(Cursor.DEFAULT); | ||||
| @ -181,6 +197,7 @@ public class PlayerController { | ||||
| 				controlAnimationTask = new TimerTask() { | ||||
| 					@Override | ||||
| 					public void run() { | ||||
| 						// TODO a animation would be nice | ||||
| 						hBoxTop.setVisible(false); | ||||
| 						bottomVBox.setVisible(false); | ||||
| 						player.getScene().setCursor(Cursor.NONE); | ||||
| @ -200,12 +217,8 @@ public class PlayerController { | ||||
|  | ||||
| 			@Override | ||||
| 			public void mediaPlayerReady(MediaPlayer mediaPlayer) { | ||||
| 				System.out.println(mediaPlayer.audio().trackCount()); | ||||
| 				 | ||||
| 				mediaPlayer.audio().trackDescriptions().forEach(trackDesc -> { | ||||
| 					System.out.println(trackDesc.description()); | ||||
| 				}); | ||||
| 				 | ||||
| 				tracks = mediaPlayer.audio().trackDescriptions(); | ||||
| 				currentTrack = mediaPlayer.audio().track(); | ||||
| 			} | ||||
| 			 | ||||
| 			@Override | ||||
| @ -226,7 +239,7 @@ public class PlayerController { | ||||
| 			@Override | ||||
| 			public void lengthChanged(MediaPlayer mediaPlayer, long 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>() { | ||||
| 			@Override | ||||
| 			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() { | ||||
| @ -283,7 +325,7 @@ public class PlayerController { | ||||
| 	private void updateControls() { | ||||
| 		// update slider position, if the mouse does not press on the time | ||||
| 		if (!mousePressed) { | ||||
| 			timeSlider.setValue((currentTime / 1000) / 60); | ||||
| 			timeSlider.setValue(currentTime / 1000); | ||||
| 		} | ||||
| 		 | ||||
| 		// update endTime label | ||||
| @ -341,17 +383,38 @@ public class PlayerController { | ||||
| 	 | ||||
| 	@FXML | ||||
| 	void btnAudioAction(ActionEvent event) { | ||||
| 		// TODO move to separate class "AudioPopup" | ||||
| 		 | ||||
| 		JFXDialogLayout content = new JFXDialogLayout(); | ||||
| 		content.setHeading(new Text("Test")); | ||||
| 		content.setBody(new Text("Hallo 123")); | ||||
| 		content.setPrefSize(150, 200); | ||||
|  | ||||
| 		JFXPopup popup = new JFXPopup(); | ||||
| 		popup.setPopupContent(content); | ||||
| 		popup.show(btnAudio, PopupVPosition.BOTTOM, PopupHPosition.RIGHT, | ||||
| 				0, -1 * bottomVBox.getHeight()); | ||||
| 		if (audioPopup == null) { | ||||
| 			audioPopup = new JFXPopup(); | ||||
| 			 | ||||
| 			JFXListView<String> list = new JFXListView<String>(); | ||||
| 			tracks.forEach(track -> { | ||||
| 				list.getItems().add(track.description()); | ||||
| 			}); | ||||
| 			 | ||||
| 			list.getSelectionModel().select(currentTrack); | ||||
| 			list.setOnMouseClicked(ev -> { | ||||
| 				setAudioTrack(list.getSelectionModel().getSelectedIndex()); | ||||
| 				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 | ||||
| @ -371,6 +434,9 @@ public class PlayerController { | ||||
| 		playNextMedia(); | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * play the next media | ||||
| 	 */ | ||||
| 	private void playNextMedia() { | ||||
| 		autoplay = false; | ||||
| 		DBController.getInstance().setCurrentTime(media.getStreamUrl(), 0); // reset old video start time | ||||
| @ -381,6 +447,15 @@ public class PlayerController { | ||||
| 			autoplay = true; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * 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() { | ||||
| 		return currentTime; | ||||
|  | ||||
| @ -209,4 +209,3 @@ | ||||
| .scroll-pane > .viewport { | ||||
|    -fx-background-color: transparent; | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										22
									
								
								src/main/resources/css/Player.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/main/resources/css/Player.css
									
									
									
									
									
										Normal 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%; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user