JavaFX provides comprehensive media playback capabilities through its Media, MediaPlayer, and MediaView classes. This guide covers everything from basic audio/video playback to advanced features and custom media players.
Basic Media Playback
1. Simple Audio Player
SimpleAudioPlayer.java:
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.Slider; import javafx.scene.layout.VBox; import javafx.stage.Stage; import javafx.scene.media.Media; import javafx.scene.media.MediaPlayer; import javafx.util.Duration; public class SimpleAudioPlayer extends Application { private MediaPlayer mediaPlayer; private Label statusLabel; private Slider volumeSlider; private Slider progressSlider; @Override public void start(Stage primaryStage) { // Create UI components Button playButton = new Button("Play"); Button pauseButton = new Button("Pause"); Button stopButton = new Button("Stop"); Button loadButton = new Button("Load Audio"); statusLabel = new Label("No media loaded"); volumeSlider = new Slider(0, 100, 50); progressSlider = new Slider(0, 100, 0); // Layout VBox root = new VBox(10); root.setStyle("-fx-padding: 20; -fx-alignment: center;"); root.getChildren().addAll( statusLabel, playButton, pauseButton, stopButton, loadButton, new Label("Volume:"), volumeSlider, new Label("Progress:"), progressSlider ); // Event handlers playButton.setOnAction(e -> playMedia()); pauseButton.setOnAction(e -> pauseMedia()); stopButton.setOnAction(e -> stopMedia()); loadButton.setOnAction(e -> loadMedia()); volumeSlider.valueProperty().addListener((obs, oldVal, newVal) -> setVolume(newVal.doubleValue())); Scene scene = new Scene(root, 400, 300); primaryStage.setTitle("JavaFX Audio Player"); primaryStage.setScene(scene); primaryStage.show(); } private void loadMedia() { try { // Replace with your audio file path String audioFile = getClass().getResource("/audio/sample.mp3").toString(); Media media = new Media(audioFile); if (mediaPlayer != null) { mediaPlayer.dispose(); } mediaPlayer = new MediaPlayer(media); setupMediaPlayer(); statusLabel.setText("Media loaded: " + getFileName(audioFile)); } catch (Exception e) { statusLabel.setText("Error loading media: " + e.getMessage()); } } private void setupMediaPlayer() { mediaPlayer.setOnReady(() -> { statusLabel.setText("Media ready to play"); progressSlider.setMax(mediaPlayer.getTotalDuration().toSeconds()); }); mediaPlayer.currentTimeProperty().addListener((obs, oldTime, newTime) -> { if (!progressSlider.isValueChanging()) { progressSlider.setValue(newTime.toSeconds()); } }); progressSlider.valueProperty().addListener((obs, oldVal, newVal) -> { if (progressSlider.isValueChanging()) { mediaPlayer.seek(Duration.seconds(newVal.doubleValue())); } }); mediaPlayer.setOnEndOfMedia(() -> { statusLabel.setText("Playback finished"); mediaPlayer.stop(); }); mediaPlayer.setVolume(volumeSlider.getValue() / 100.0); } private void playMedia() { if (mediaPlayer != null) { mediaPlayer.play(); statusLabel.setText("Playing..."); } } private void pauseMedia() { if (mediaPlayer != null) { mediaPlayer.pause(); statusLabel.setText("Paused"); } } private void stopMedia() { if (mediaPlayer != null) { mediaPlayer.stop(); statusLabel.setText("Stopped"); } } private void setVolume(double volume) { if (mediaPlayer != null) { mediaPlayer.setVolume(volume / 100.0); } } private String getFileName(String path) { return path.substring(path.lastIndexOf("/") + 1); } public static void main(String[] args) { launch(args); } } 2. Basic Video Player
BasicVideoPlayer.java:
import javafx.application.Application; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.Slider; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.media.Media; import javafx.scene.media.MediaPlayer; import javafx.scene.media.MediaView; import javafx.stage.Stage; import javafx.util.Duration; public class BasicVideoPlayer extends Application { private MediaPlayer mediaPlayer; private MediaView mediaView; private Label statusLabel; private Slider volumeSlider; private Slider progressSlider; private Button playButton; @Override public void start(Stage primaryStage) { // Create MediaView mediaView = new MediaView(); mediaView.setFitWidth(800); mediaView.setFitHeight(450); mediaView.setPreserveRatio(true); // Create control buttons playButton = new Button("Play"); Button pauseButton = new Button("Pause"); Button stopButton = new Button("Stop"); Button loadButton = new Button("Load Video"); statusLabel = new Label("No video loaded"); volumeSlider = new Slider(0, 100, 50); progressSlider = new Slider(0, 100, 0); // Control panel HBox buttonBox = new HBox(10, playButton, pauseButton, stopButton, loadButton); buttonBox.setAlignment(Pos.CENTER); VBox controlBox = new VBox(10); controlBox.setPadding(new Insets(10)); controlBox.getChildren().addAll( statusLabel, buttonBox, new Label("Volume:"), volumeSlider, new Label("Progress:"), progressSlider ); // Main layout BorderPane root = new BorderPane(); root.setCenter(mediaView); root.setBottom(controlBox); // Event handlers playButton.setOnAction(e -> playMedia()); pauseButton.setOnAction(e -> pauseMedia()); stopButton.setOnAction(e -> stopMedia()); loadButton.setOnAction(e -> loadMedia()); volumeSlider.valueProperty().addListener((obs, oldVal, newVal) -> setVolume(newVal.doubleValue())); Scene scene = new Scene(root, 850, 600); primaryStage.setTitle("JavaFX Video Player"); primaryStage.setScene(scene); primaryStage.show(); } private void loadMedia() { try { // Replace with your video file path String videoFile = getClass().getResource("/video/sample.mp4").toString(); Media media = new Media(videoFile); if (mediaPlayer != null) { mediaPlayer.dispose(); } mediaPlayer = new MediaPlayer(media); mediaView.setMediaPlayer(mediaPlayer); setupMediaPlayer(); statusLabel.setText("Video loaded: " + getFileName(videoFile)); } catch (Exception e) { statusLabel.setText("Error loading video: " + e.getMessage()); } } private void setupMediaPlayer() { mediaPlayer.setOnReady(() -> { statusLabel.setText("Video ready to play"); // Set initial volume mediaPlayer.setVolume(volumeSlider.getValue() / 100.0); }); mediaPlayer.currentTimeProperty().addListener((obs, oldTime, newTime) -> { if (!progressSlider.isValueChanging() && mediaPlayer.getTotalDuration().greaterThan(Duration.ZERO)) { double progress = (newTime.toMillis() / mediaPlayer.getTotalDuration().toMillis()) * 100; progressSlider.setValue(progress); } }); progressSlider.valueProperty().addListener((obs, oldVal, newVal) -> { if (progressSlider.isValueChanging() && mediaPlayer.getTotalDuration().greaterThan(Duration.ZERO)) { Duration seekTime = mediaPlayer.getTotalDuration().multiply(newVal.doubleValue() / 100.0); mediaPlayer.seek(seekTime); } }); mediaPlayer.setOnPlaying(() -> { playButton.setText("Pause"); statusLabel.setText("Playing..."); }); mediaPlayer.setOnPaused(() -> { playButton.setText("Play"); statusLabel.setText("Paused"); }); mediaPlayer.setOnStopped(() -> { playButton.setText("Play"); statusLabel.setText("Stopped"); }); mediaPlayer.setOnEndOfMedia(() -> { statusLabel.setText("Playback finished"); mediaPlayer.stop(); }); mediaPlayer.setVolume(volumeSlider.getValue() / 100.0); } private void playMedia() { if (mediaPlayer != null) { if (mediaPlayer.getStatus() == MediaPlayer.Status.PLAYING) { mediaPlayer.pause(); } else { mediaPlayer.play(); } } } private void pauseMedia() { if (mediaPlayer != null) { mediaPlayer.pause(); } } private void stopMedia() { if (mediaPlayer != null) { mediaPlayer.stop(); } } private void setVolume(double volume) { if (mediaPlayer != null) { mediaPlayer.setVolume(volume / 100.0); } } private String getFileName(String path) { return path.substring(path.lastIndexOf("/") + 1); } public static void main(String[] args) { launch(args); } } Advanced Media Player with FXML
3. FXML-based Advanced Media Player
media-player.fxml:
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <?import javafx.scene.media.MediaView?> <?import javafx.geometry.Insets?> <BorderPane xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.controller.MediaPlayerController" stylesheets="@../css/media-player.css"> <center> <MediaView fx:id="mediaView" fitWidth="${controller.mediaWidth}" fitHeight="${controller.mediaHeight}" preserveRatio="true"/> </center> <bottom> <VBox spacing="10" style="-fx-background-color: #2c3e50;"> <!-- Progress bar --> <HBox spacing="10" alignment="CENTER" style="-fx-padding: 5 10 0 10;"> <Label fx:id="currentTimeLabel" text="00:00" style="-fx-text-fill: white; -fx-font-size: 12;"/> <Slider fx:id="progressSlider" HBox.hgrow="ALWAYS"/> <Label fx:id="totalTimeLabel" text="00:00" style="-fx-text-fill: white; -fx-font-size: 12;"/> </HBox> <!-- Control buttons --> <HBox spacing="15" alignment="CENTER" style="-fx-padding: 0 10 10 10;"> <Button fx:id="playPauseButton" text="Play" onAction="#togglePlayPause" style="-fx-background-color: #3498db; -fx-text-fill: white;"/> <Button fx:id="stopButton" text="Stop" onAction="#stopMedia" style="-fx-background-color: #e74c3c; -fx-text-fill: white;"/> <Button fx:id="muteButton" text="Mute" onAction="#toggleMute" style="-fx-background-color: #95a5a6; -fx-text-fill: white;"/> <Label text="Volume:" style="-fx-text-fill: white;"/> <Slider fx:id="volumeSlider" prefWidth="100" value="50"/> <ComboBox fx:id="playbackRateComboBox" promptText="Speed" prefWidth="80"/> <Button fx:id="fullscreenButton" text="Fullscreen" onAction="#toggleFullscreen" style="-fx-background-color: #9b59b6; -fx-text-fill: white;"/> </HBox> </VBox> </bottom> <top> <MenuBar> <Menu text="File"> <items> <MenuItem text="Open Media File..." onAction="#openMediaFile"/> <MenuItem text="Open URL..." onAction="#openMediaURL"/> <SeparatorMenuItem/> <MenuItem text="Exit" onAction="#exitApplication"/> </items> </Menu> <Menu text="Playback"> <items> <MenuItem text="Loop" onAction="#toggleLoop"/> <MenuItem text="Auto Play" onAction="#toggleAutoPlay"/> </items> </Menu> <Menu text="View"> <items> <CheckMenuItem text="Always on Top" onAction="#toggleAlwaysOnTop"/> <CheckMenuItem text="Show Controls" selected="true" onAction="#toggleControlsVisibility"/> </items> </Menu> </MenuBar> </top> </BorderPane> 4. Advanced Media Player Controller
MediaPlayerController.java:
package com.example.controller; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.*; import javafx.scene.media.Media; import javafx.scene.media.MediaPlayer; import javafx.scene.media.MediaView; import javafx.stage.FileChooser; import javafx.stage.Stage; import javafx.util.Duration; import javafx.event.ActionEvent; import javafx.beans.value.ChangeListener; import javafx.collections.FXCollections; import java.io.File; import java.net.URL; import java.util.ResourceBundle; public class MediaPlayerController implements Initializable { @FXML private MediaView mediaView; @FXML private Slider progressSlider; @FXML private Slider volumeSlider; @FXML private Button playPauseButton; @FXML private Button stopButton; @FXML private Button muteButton; @FXML private Button fullscreenButton; @FXML private Label currentTimeLabel; @FXML private Label totalTimeLabel; @FXML private ComboBox<Double> playbackRateComboBox; private MediaPlayer mediaPlayer; private boolean isMuted = false; private boolean isPlaying = false; private double originalVolume; private Stage primaryStage; // Properties for binding private double mediaWidth = 800; private double mediaHeight = 450; @Override public void initialize(URL location, ResourceBundle resources) { setupPlaybackRateComboBox(); setupEventHandlers(); } public void setPrimaryStage(Stage stage) { this.primaryStage = stage; setupFullscreenHandling(); } private void setupPlaybackRateComboBox() { playbackRateComboBox.setItems(FXCollections.observableArrayList( 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0 )); playbackRateComboBox.setValue(1.0); playbackRateComboBox.valueProperty().addListener((obs, oldRate, newRate) -> { if (mediaPlayer != null) { mediaPlayer.setRate(newRate); } }); } private void setupEventHandlers() { volumeSlider.valueProperty().addListener((obs, oldVal, newVal) -> { if (mediaPlayer != null) { mediaPlayer.setVolume(newVal.doubleValue() / 100.0); } }); progressSlider.valueProperty().addListener((obs, oldVal, newVal) -> { if (progressSlider.isValueChanging() && mediaPlayer != null) { Duration seekTime = mediaPlayer.getTotalDuration().multiply(newVal.doubleValue() / 100.0); mediaPlayer.seek(seekTime); } }); } private void setupFullscreenHandling() { if (primaryStage != null) { primaryStage.fullScreenProperty().addListener((obs, oldVal, newVal) -> { if (newVal) { // Entering fullscreen mediaWidth = primaryStage.getWidth(); mediaHeight = primaryStage.getHeight(); } else { // Exiting fullscreen mediaWidth = 800; mediaHeight = 450; } }); } } @FXML private void openMediaFile(ActionEvent event) { FileChooser fileChooser = new FileChooser(); fileChooser.setTitle("Open Media File"); fileChooser.getExtensionFilters().addAll( new FileChooser.ExtensionFilter("Media Files", "*.mp4", "*.avi", "*.mkv", "*.mov", "*.wmv", "*.mp3", "*.wav", "*.aac"), new FileChooser.ExtensionFilter("Video Files", "*.mp4", "*.avi", "*.mkv", "*.mov", "*.wmv"), new FileChooser.ExtensionFilter("Audio Files", "*.mp3", "*.wav", "*.aac", "*.flac"), new FileChooser.ExtensionFilter("All Files", "*.*") ); File selectedFile = fileChooser.showOpenDialog(primaryStage); if (selectedFile != null) { loadMedia(selectedFile.toURI().toString()); } } @FXML private void openMediaURL(ActionEvent event) { TextInputDialog dialog = new TextInputDialog("https://"); dialog.setTitle("Open Media URL"); dialog.setHeaderText("Enter Media URL"); dialog.setContentText("URL:"); dialog.showAndWait().ifPresent(url -> { if (!url.isEmpty()) { loadMedia(url); } }); } private void loadMedia(String mediaUrl) { try { // Clean up previous media player if (mediaPlayer != null) { mediaPlayer.dispose(); } Media media = new Media(mediaUrl); mediaPlayer = new MediaPlayer(media); mediaView.setMediaPlayer(mediaPlayer); setupMediaPlayerListeners(); } catch (Exception e) { showError("Error loading media", "Could not load media: " + e.getMessage()); } } private void setupMediaPlayerListeners() { mediaPlayer.setOnReady(() -> { Duration totalDuration = mediaPlayer.getTotalDuration(); totalTimeLabel.setText(formatTime(totalDuration)); // Reset UI progressSlider.setValue(0); playPauseButton.setText("Play"); isPlaying = false; }); mediaPlayer.currentTimeProperty().addListener((obs, oldTime, newTime) -> { if (!progressSlider.isValueChanging()) { double progress = (newTime.toMillis() / mediaPlayer.getTotalDuration().toMillis()) * 100; progressSlider.setValue(progress); currentTimeLabel.setText(formatTime(newTime)); } }); mediaPlayer.setOnPlaying(() -> { playPauseButton.setText("Pause"); isPlaying = true; }); mediaPlayer.setOnPaused(() -> { playPauseButton.setText("Play"); isPlaying = false; }); mediaPlayer.setOnStopped(() -> { playPauseButton.setText("Play"); isPlaying = false; progressSlider.setValue(0); currentTimeLabel.setText("00:00"); }); mediaPlayer.setOnEndOfMedia(() -> { if (mediaPlayer.getCycleCount() == 1) { mediaPlayer.stop(); } }); mediaPlayer.setOnError(() -> { String errorMessage = mediaPlayer.getError().getMessage(); showError("Media Error", "An error occurred during playback: " + errorMessage); }); // Set initial volume mediaPlayer.setVolume(volumeSlider.getValue() / 100.0); } @FXML private void togglePlayPause(ActionEvent event) { if (mediaPlayer != null) { if (isPlaying) { mediaPlayer.pause(); } else { mediaPlayer.play(); } } } @FXML private void stopMedia(ActionEvent event) { if (mediaPlayer != null) { mediaPlayer.stop(); } } @FXML private void toggleMute(ActionEvent event) { if (mediaPlayer != null) { if (isMuted) { mediaPlayer.setMute(false); muteButton.setText("Mute"); volumeSlider.setValue(originalVolume * 100); } else { originalVolume = mediaPlayer.getVolume(); mediaPlayer.setMute(true); muteButton.setText("Unmute"); } isMuted = !isMuted; } } @FXML private void toggleFullscreen(ActionEvent event) { if (primaryStage != null) { primaryStage.setFullScreen(!primaryStage.isFullScreen()); } } @FXML private void toggleLoop(ActionEvent event) { if (mediaPlayer != null) { MenuItem menuItem = (MenuItem) event.getSource(); if (mediaPlayer.getCycleCount() == MediaPlayer.INDEFINITE) { mediaPlayer.setCycleCount(1); menuItem.setText("Loop"); } else { mediaPlayer.setCycleCount(MediaPlayer.INDEFINITE); menuItem.setText("Stop Looping"); } } } @FXML private void toggleAutoPlay(ActionEvent event) { // Implementation for auto-play toggle } @FXML private void toggleAlwaysOnTop(ActionEvent event) { if (primaryStage != null) { CheckMenuItem menuItem = (CheckMenuItem) event.getSource(); primaryStage.setAlwaysOnTop(menuItem.isSelected()); } } @FXML private void toggleControlsVisibility(ActionEvent event) { CheckMenuItem menuItem = (CheckMenuItem) event.getSource(); // Implementation to show/hide controls } @FXML private void exitApplication(ActionEvent event) { if (mediaPlayer != null) { mediaPlayer.dispose(); } System.exit(0); } private String formatTime(Duration duration) { int minutes = (int) duration.toMinutes(); int seconds = (int) duration.toSeconds() % 60; return String.format("%02d:%02d", minutes, seconds); } private void showError(String title, String message) { Alert alert = new Alert(Alert.AlertType.ERROR); alert.setTitle(title); alert.setHeaderText(null); alert.setContentText(message); alert.showAndWait(); } // Property getters for FXML binding public double getMediaWidth() { return mediaWidth; } public double getMediaHeight() { return mediaHeight; } } CSS Styling for Media Player
5. Media Player CSS
media-player.css:
/* Root styles */ .root { -fx-font-family: "Segoe UI", Arial, sans-serif; -fx-background-color: #34495e; } /* Media View */ .media-view { -fx-background-color: black; } /* Control buttons */ .button { -fx-background-radius: 4px; -fx-border-radius: 4px; -fx-cursor: hand; -fx-font-size: 12px; -fx-padding: 8 15 8 15; -fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.2), 4, 0, 0, 2); } .button:hover { -fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.3), 6, 0, 0, 3); } .button:pressed { -fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.1), 2, 0, 0, 1); } /* Play/Pause button */ #playPauseButton { -fx-background-color: #27ae60; -fx-text-fill: white; } #playPauseButton:hover { -fx-background-color: #229954; } /* Stop button */ #stopButton { -fx-background-color: #e74c3c; -fx-text-fill: white; } #stopButton:hover { -fx-background-color: #c0392b; } /* Mute button */ #muteButton { -fx-background-color: #95a5a6; -fx-text-fill: white; } #muteButton:hover { -fx-background-color: #7f8c8d; } /* Fullscreen button */ #fullscreenButton { -fx-background-color: #9b59b6; -fx-text-fill: white; } #fullscreenButton:hover { -fx-background-color: #8e44ad; } /* Slider styles */ .slider { -fx-background-color: transparent; } .slider .track { -fx-background-color: #7f8c8d; -fx-background-radius: 2px; -fx-pref-height: 4px; } .slider .thumb { -fx-background-color: #3498db; -fx-background-radius: 8px; -fx-pref-height: 16px; -fx-pref-width: 16px; } .slider .thumb:hover { -fx-background-color: #2980b9; } /* Progress slider specific */ #progressSlider .track { -fx-background-color: #34495e; } #progressSlider .track { -fx-background-color: linear-gradient(to right, #3498db 0%, #3498db 50%, #7f8c8d 50%, #7f8c8d 100%); } /* Volume slider specific */ #volumeSlider .track { -fx-background-color: #7f8c8d; } /* ComboBox styles */ .combo-box { -fx-background-color: #2c3e50; -fx-border-color: #34495e; -fx-border-radius: 4px; -fx-text-fill: white; } .combo-box .list-cell { -fx-background-color: #2c3e50; -fx-text-fill: white; } .combo-box .list-view { -fx-background-color: #2c3e50; } .combo-box .list-cell:hover { -fx-background-color: #3498db; } /* Label styles */ .label { -fx-text-fill: #ecf0f1; } /* Menu bar styles */ .menu-bar { -fx-background-color: #2c3e50; } .menu { -fx-text-fill: white; } .menu-item { -fx-background-color: #2c3e50; } .menu-item:hover { -fx-background-color: #3498db; } .menu-item .label { -fx-text-fill: white; } Advanced Features
6. Equalizer and Audio Effects
AudioEqualizer.java:
import javafx.scene.media.EqualizerBand; import javafx.scene.media.MediaPlayer; public class AudioEqualizer { private MediaPlayer mediaPlayer; private EqualizerBand[] bands; public AudioEqualizer(MediaPlayer mediaPlayer) { this.mediaPlayer = mediaPlayer; initializeEqualizer(); } private void initializeEqualizer() { if (mediaPlayer.getAudioEqualizer() != null) { mediaPlayer.getAudioEqualizer().setEnabled(true); bands = new EqualizerBand[10]; // Create 10 equalizer bands for (int i = 0; i < bands.length; i++) { bands[i] = new EqualizerBand(); bands[i].setBandwidth(1.0); bands[i].setCenterFrequency(calculateFrequency(i)); bands[i].setGain(0.0); mediaPlayer.getAudioEqualizer().getBands().add(bands[i]); } } } private double calculateFrequency(int bandIndex) { // Calculate frequencies from 32Hz to 16kHz return 32.0 * Math.pow(2, bandIndex); } public void setBandGain(int band, double gain) { if (bands != null && band >= 0 && band < bands.length) { bands[band].setGain(gain); } } public void setPreset(String presetName) { if (bands == null) return; switch (presetName.toLowerCase()) { case "flat": setFlatPreset(); break; case "rock": setRockPreset(); break; case "pop": setPopPreset(); break; case "jazz": setJazzPreset(); break; case "classical": setClassicalPreset(); break; } } private void setFlatPreset() { for (EqualizerBand band : bands) { band.setGain(0.0); } } private void setRockPreset() { double[] gains = {4.0, 3.0, 2.0, 1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0}; applyGains(gains); } private void setPopPreset() { double[] gains = {-1.0, 0.0, 2.0, 3.0, 3.0, 2.0, 1.0, 0.0, -1.0, -2.0}; applyGains(gains); } private void setJazzPreset() { double[] gains = {2.0, 1.0, 0.0, -1.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0}; applyGains(gains); } private void setClassicalPreset() { double[] gains = {3.0, 2.0, 1.0, 0.0, -1.0, -2.0, -1.0, 0.0, 1.0, 2.0}; applyGains(gains); } private void applyGains(double[] gains) { for (int i = 0; i < Math.min(bands.length, gains.length); i++) { bands[i].setGain(gains[i]); } } } 7. Playlist Management
PlaylistManager.java:
import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.media.Media; import javafx.scene.media.MediaPlayer; import javafx.util.Duration; import java.io.File; import java.util.ArrayList; import java.util.List; public class PlaylistManager { private ObservableList<MediaItem> playlist; private int currentIndex = -1; private MediaPlayer currentPlayer; public PlaylistManager() { playlist = FXCollections.observableArrayList(); } public void addMedia(String mediaUrl) { MediaItem item = new MediaItem(mediaUrl); playlist.add(item); } public void addMediaFiles(List<File> files) { for (File file : files) { addMedia(file.toURI().toString()); } } public void removeMedia(int index) { if (index >= 0 && index < playlist.size()) { playlist.remove(index); if (currentIndex >= index) { currentIndex--; } } } public void play(int index) { if (index >= 0 && index < playlist.size()) { stopCurrent(); currentIndex = index; MediaItem item = playlist.get(currentIndex); try { Media media = new Media(item.getMediaUrl()); currentPlayer = new MediaPlayer(media); currentPlayer.play(); currentPlayer.setOnEndOfMedia(() -> { playNext(); }); } catch (Exception e) { System.err.println("Error playing media: " + e.getMessage()); playNext(); } } } public void playNext() { if (playlist.isEmpty()) return; int nextIndex = (currentIndex + 1) % playlist.size(); play(nextIndex); } public void playPrevious() { if (playlist.isEmpty()) return; int prevIndex = (currentIndex - 1 + playlist.size()) % playlist.size(); play(prevIndex); } public void stopCurrent() { if (currentPlayer != null) { currentPlayer.stop(); currentPlayer.dispose(); currentPlayer = null; } } public void shufflePlaylist() { FXCollections.shuffle(playlist); currentIndex = -1; } public ObservableList<MediaItem> getPlaylist() { return playlist; } public MediaPlayer getCurrentPlayer() { return currentPlayer; } public int getCurrentIndex() { return currentIndex; } public MediaItem getCurrentMedia() { if (currentIndex >= 0 && currentIndex < playlist.size()) { return playlist.get(currentIndex); } return null; } } class MediaItem { private String mediaUrl; private String title; private Duration duration; public MediaItem(String mediaUrl) { this.mediaUrl = mediaUrl; this.title = extractTitle(mediaUrl); } private String extractTitle(String url) { // Extract filename from URL String[] parts = url.split("/"); return parts[parts.length - 1]; } // Getters and setters public String getMediaUrl() { return mediaUrl; } public String getTitle() { return title; } public Duration getDuration() { return duration; } public void setDuration(Duration duration) { this.duration = duration; } @Override public String toString() { return title; } } Key Features Summary
- Basic Playback: Play, pause, stop, seek functionality
- Volume Control: Mute, volume slider, audio normalization
- Progress Tracking: Real-time progress updates and seeking
- Playback Rate: Variable speed playback
- Fullscreen Support: Toggle fullscreen mode
- Playlist Management: Queue and manage multiple media files
- Equalizer: Audio effects and presets
- Error Handling: Robust error handling and user feedback
- Custom Styling: CSS-based UI customization
- File Support: Multiple media formats (MP4, AVI, MP3, WAV, etc.)
JavaFX provides a powerful, flexible framework for media playback that can be customized to create professional-grade media players with advanced features.