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.