package de.calette.mephisto3.ui; import callete.api.Callete; import callete.api.services.music.model.Album; import callete.api.services.music.model.PlaylistItem; import callete.api.services.music.model.Song; import callete.api.services.music.player.PlaybackChangeEvent; import callete.api.services.music.player.PlaybackChangeListener; import callete.api.services.music.player.PlaylistChangeEvent; import callete.api.services.music.player.PlaylistChangeListener; import callete.api.util.DateUtil; import de.calette.mephisto3.resources.ResourceLoader; import de.calette.mephisto3.util.ComponentUtil; import de.calette.mephisto3.util.TransitionUtil; import javafx.application.Platform; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.control.ProgressBar; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.text.Text; import org.apache.commons.lang.StringUtils; import java.util.Timer; import java.util.TimerTask; /** * Displays the current status of the media player. */ public class MusicPlayerStatusBox extends BorderPane implements PlaylistChangeListener, PlaybackChangeListener { public static final int COVER_SIZE = 52; private Image defaultBackground = new Image(ResourceLoader.getResource("player-background.png"), COVER_SIZE, COVER_SIZE, false, true); private ImageView imageView; private Label nameLabel; private Label titleLabel; private Label albumInfoLabel; private ProgressBar progress; private Text totalDurationLabel; private Text currentDurationLabel; private Timer timer; private int currentDuration; public MusicPlayerStatusBox() { VBox spacer = new VBox(); this.setOpacity(0); spacer.setMinHeight(332); setTop(spacer); setLeft(createImageBox()); setCenter(createStatusBox()); } public void showPlayer() { Callete.getMusicPlayer().getPlaylist().addChangeListener(this); Callete.getMusicPlayer().addPlaybackChangeEventListener(this); TransitionUtil.createInFader(this).play(); } public void hidePlayer() { Callete.getMusicPlayer().getPlaylist().removeChangeListener(this); Callete.getMusicPlayer().removePlaybackChangeEventListener(this); TransitionUtil.createOutFader(this).play(); } //---------- Helper ------------------------------------------------------- private Node createStatusBox() { VBox status = new VBox(2); status.setMaxWidth(240); status.setMinWidth(240); status.setPadding(new Insets(3, 3, 0, 5)); nameLabel = ComponentUtil.createCustomLabel("", "player-name-label", status); titleLabel = ComponentUtil.createCustomLabel("", "player-title-label", status); albumInfoLabel = ComponentUtil.createCustomLabel("", "player-albuminfo-label", status); BorderPane statusBox = new BorderPane(); statusBox.getStyleClass().add("player-status-panel"); statusBox.setLeft(status); HBox progressWrapper = new HBox(5); progressWrapper.setPadding(new Insets(20, 10, 0, 0)); statusBox.setCenter(progressWrapper); progress = new ProgressBar(); progress.setOpacity(0); progress.setProgress(0); progress.setMinWidth(280); progress.setMaxWidth(280); HBox durationWrapper = new HBox(); durationWrapper.setMinWidth(30); durationWrapper.setAlignment(Pos.BASELINE_CENTER); currentDurationLabel = ComponentUtil.createText("", "", durationWrapper); HBox totalDurationWrapper = new HBox(); totalDurationWrapper.setAlignment(Pos.BASELINE_CENTER); totalDurationWrapper.setMinWidth(30); totalDurationLabel = ComponentUtil.createText("", "", totalDurationWrapper); progressWrapper.getChildren().add(durationWrapper); progressWrapper.getChildren().add(progress); progressWrapper.getChildren().add(totalDurationWrapper); HBox spacer = new HBox(); spacer.setMinWidth(10); progressWrapper.getChildren().add(spacer); return statusBox; } private Node createImageBox() { HBox wrapper = new HBox(5); wrapper.getStyleClass().add("player-status-panel"); wrapper.setPadding(new Insets(4, 2, 2, 4)); HBox imageBox = new HBox(); imageBox.setMaxHeight(42); imageBox.getStyleClass().add("player-status-image"); imageView = new ImageView(defaultBackground); imageBox.getChildren().add(imageView); wrapper.getChildren().add(imageBox); return wrapper; } public void setImage(Image image) { if(image == null) { this.imageView.setImage(defaultBackground); } else { this.imageView.setImage(image); } } @Override public void playlistChanged(final PlaylistChangeEvent e) { Platform.runLater(() -> { PlaylistItem activeItem = e.getActiveItem(); if(!(activeItem instanceof Song)) { cancelProgress(); return; } final Song song = (Song) e.getActiveItem(); Album album = song.getAlbum(); nameLabel.setText(song.getName()); titleLabel.setText(song.getArtist()); String info = ""; if(album.getYear() > 0) { info = String.valueOf(album.getYear()); } if(!StringUtils.isEmpty(album.getGenre())) { if(info.length() > 0) { info += ", "; } info += album.getGenre(); } albumInfoLabel.setText(info); progress.setOpacity(1); //reset progress to zero progress.setProgress(0); currentDurationLabel.setText("0:00 "); totalDurationLabel.setText(" " + song.getDuration()); //reset timer if(timer != null) { timer.purge(); timer.cancel(); timer = null; } }); } @Override public void playbackChanged(PlaybackChangeEvent event) { PlaylistItem activeItem = event.getActiveItem(); if(!(activeItem instanceof Song)) { cancelProgress(); return; } final Song song = (Song) event.getActiveItem(); final Album album = song.getAlbum(); //reset timer if(timer != null) { timer.purge(); timer.cancel(); timer = null; } timer = new Timer(); currentDuration = 0; timer.schedule(new TimerTask() { @Override public void run() { Platform.runLater(new Runnable() { @Override public void run() { currentDuration++; String time = DateUtil.formatTime(currentDuration); if(currentDuration * 1000 <= song.getDurationMillis()) { currentDurationLabel.setText(time+" "); } long duration = song.getDurationMillis() / 1000; double progressValue = 1.0 / duration; progressValue = progress.getProgress() + progressValue; progress.setProgress(progressValue); if(progressValue > 1) { timer.purge(); timer.cancel(); timer = null; progress.setProgress(0); } } }); } }, 0, 1000); Platform.runLater(new Runnable() { @Override public void run() { ImageView cover = ComponentUtil.loadAlbumCover(album, COVER_SIZE, COVER_SIZE); setImage(cover.getImage()); } }); } public boolean isPlaying() { return timer != null; } private void cancelProgress() { if(timer != null) { timer.purge(); timer.cancel(); timer = null; } Platform.runLater(new Runnable() { @Override public void run() { setImage(null); nameLabel.setText(""); titleLabel.setText(""); albumInfoLabel.setText(""); progress.setProgress(0); currentDurationLabel.setText(""); totalDurationLabel.setText(""); progress.setOpacity(0); } }); } }