Site iconJava PDF Blog

JavaFX MP3 Music Player – embedding sound in your application

At IDR Solutions I have been spending alot of time working with Java PDF Viewer as part our Java PDF Library.  Having spent that time working with JavaFX I thought it would be a good idea to see what you can do with JavaFX. Therefore in this article I will show you how to create simple MP3 player in JavaFX. In part one of a series of articles I will be concentrating on one of the JavaFX features which is embedded sound.

This tutorial won’t be step by step explanation but I will just explain how to add the main functionality. If you are a beginner and you are looking for precise explanation of how to build this and similar applications in JavaFX please check my  previous articles: “How to write a Media Player in JavaFX using NetBeans IDE – Part 1“, “How to write a Media Player in JavaFX using NetBeans IDE – Part 2” and “How to write a WebBrowser plugin in JavaFX for the NetBeans IDE“. So Lets start!

Sending the file location

There are two ways in which you can send the file location:

1. Add  path of the vidio that you want to play

 path = "F:/MusicPlayer/src/musicplayer/adcBicycle_-_02_-_poor_economic_policies.mp3";
 media = new Media(new File(path).toURI().toString());
 mediaPlayer = new MediaPlayer(media);
 mediaPlayer.setAutoPlay(true);
 mediaView = new MediaView(mediaPlayer);

The song used for this application and many other can be found here.

2. Use FileChooser

FileChooser fc = new FileChooser();
fc.getExtensionFilters().add(new FileChooser.ExtensionFilter("*.mp3"));
File file = fc.showOpenDialog(null);
path = file.getAbsolutePath();
path = path.replace("\\", "/");
media = new Media(new File(path).toURI().toString());
mediaPlayer.stop();
mediaPlayer = new MediaPlayer(media);
mediaPlayer.setAutoPlay(true);
mediaView.setMediaPlayer(mediaPlayer);

FileChooser alowes you to select the file location that has the mp3 extantion. You can also add many other extantion of files that you wish to open such as: mp4, flv, mpeg.

Application functionality

To add the functionality to my application I used some of the code found in the tutorial provided by Oracle: “Introduction to JavaFX Media“. If you are looking for more information and tutorials on JavaFX, in my opinion Oracle website is the best place to visit.

Play/Pouse Button

Image PlayButtonImage = new Image(getClass().getResourceAsStream("Play 50x50.png"));
Image PauseButtonImage = new Image(getClass().getResourceAsStream("Pause 50x50.png"));
ImageView imageViewPlay = new ImageView(PlayButtonImage);
ImageView imageViewPause = new ImageView(PauseButtonImage);

playButton.setGraphic(imageViewPlay);
playButton.setOnAction(new EventHandler() {
public void handle(ActionEvent e) {
updateValues();
Status status = mediaPlayer.getStatus();

if (status == Status.PAUSED
|| status == Status.READY
|| status == Status.STOPPED) {

mediaPlayer.play();
playButton.setGraphic(imageViewPlay);

} else {
mediaPlayer.pause();
playButton.setGraphic(imageViewPause);
}
}
});

Reload Button

reloadButton.setOnAction((ActionEvent e) -> {
mediaPlayer.seek(mediaPlayer.getStartTime());
});

Files Button

To add functionality to the Files Button use the FileChoser code provided above.

 Slider

slider = new Slider();
HBox.setHgrow(slider, Priority.ALWAYS);
slider.setMinSize(300, 50);

slider.valueProperty().addListener(new InvalidationListener() {
public void invalidated(Observable ov) {
if (slider.isValueChanging()) {
// multiply duration by percentage calculated by slider position
if (duration != null) {
mediaPlayer.seek(duration.multiply(slider.getValue() / 100.0));
}
updateValues();

}
}
});

mediaPlayer.currentTimeProperty().addListener(new ChangeListener() {

@Override
public void changed(ObservableValue observable, Duration oldValue, Duration newValue) {
updateValues();
}
});

Time

time = new Label();
time.setTextFill(Color.YELLOW);
time.setPrefWidth(80);

mediaPlayer.currentTimeProperty().addListener((Observable ov) -> {
updateValues();
});

mediaPlayer.setOnReady(() -> {
duration = mediaPlayer.getMedia().getDuration();
updateValues();
});

UpdateValues method

protected void updateValues() {
if (time != null && slider != null && duration != null) {
Platform.runLater(new Runnable() {
public void run() {
Duration currentTime = mediaPlayer.getCurrentTime();
time.setText(formatTime(currentTime, duration));
slider.setDisable(duration.isUnknown());
if (!slider.isDisabled() && duration.greaterThan(Duration.ZERO) && !slider.isValueChanging()) {
slider.setValue(currentTime.divide(duration).toMillis() * 100.0);
}

}
});
}
}

FormatTime method

private static String formatTime(Duration elapsed, Duration duration) {
int intElapsed = (int) floor(elapsed.toSeconds());
int elapsedHours = intElapsed / (60 * 60);
if (elapsedHours > 0) {
intElapsed -= elapsedHours * 60 * 60;
}
int elapsedMinutes = intElapsed / 60;
int elapsedSeconds = intElapsed - elapsedHours * 60 * 60
- elapsedMinutes * 60;

if (duration.greaterThan(Duration.ZERO)) {
int intDuration = (int) floor(duration.toSeconds());
int durationHours = intDuration / (60 * 60);
if (durationHours > 0) {
intDuration -= durationHours * 60 * 60;
}
int durationMinutes = intDuration / 60;
int durationSeconds = intDuration - durationHours * 60 * 60
- durationMinutes * 60;
if (durationHours > 0) {
return format("%d:%02d:%02d/%d:%02d:%02d",
elapsedHours, elapsedMinutes, elapsedSeconds,
durationHours, durationMinutes, durationSeconds);
} else {
return format("%02d:%02d/%02d:%02d",
elapsedMinutes, elapsedSeconds, durationMinutes,
durationSeconds);
}
} else {
if (elapsedHours > 0) {
return format("%d:%02d:%02d", elapsedHours,
elapsedMinutes, elapsedSeconds);
} else {
return format("%02d:%02d", elapsedMinutes,
elapsedSeconds);
}
}
}

 Advantages and disadvantages

There are many advantages of building Music Player in JavaFX as you can use CSS to create advanced looking application. The only disadvantage I found was that I couldn’t select multiple songs to be played one after the other. Therefore my application allows you to only play one song at a time.

If you found a solution for that issue please leave a comment. I will be more than happy to look at them.