I have List<MediaPlayer>
that is populating by
private List<MediaPlayer> players() {
for (String file : path.list((dir1, name) -> {
if (name.endsWith(SUPPORTED_VIDEO_FILE_EXTENSIONS)){
return true;
}
return false;
})) {
players.add(createPlayer(Paths.get(path + "/" + file).toUri().toString()));
System.out.println(Paths.get(path + "/" + file).toUri().toString());
}
return players;
}
In my case size of List<MediaPlayer>
is 3. Than i use it there
if (currentNumOfVideo == -1) {
currentNumOfVideo = 0;
}
mv = new MediaView();
MediaPlayer currentPlayer = players.get(currentNumOfVideo);
mv.setMediaPlayer(currentPlayer);
currentPlayer.play();
players.get(currentNumOfVideo).setOnEndOfMedia(() -> {
players.get(currentNumOfVideo).stop();
if (currentNumOfVideo < players.size()) {
currentNumOfVideo += 1;
mv.setMediaPlayer(players.get(currentNumOfVideo));
players.get(currentNumOfVideo).play();
} else {
currentNumOfVideo = 0;
mv.setMediaPlayer(players.get(currentNumOfVideo));
players.get(currentNumOfVideo).play();
}
});
First video playing, when it ends second video starts. After second video MediaPlayer stops and didn't play third video.
I understand that because of my setOnEndOfMedia
that is only on first MediaPlayer. When the second video starts it doesn't have setOnEndOfMedia
. How can I setOnEndOfMedia
on every video in my List<MediaPlayer>
.
Personally, I would not create all the MediaPlayer
instances ahead-of-time. Instead, get a list of Media
objects or at least the URIs pointing to the media. Then create a method which is responsible for playing the next video when the current video ends. That method will dispose the old MediaPlayer
, create the next MediaPlayer
, and configure it to call the same method upon completion. For example:
import java.util.List;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.stage.Stage;
public class Main extends Application {
private MediaView mediaView;
private List<Media> media;
private int curIndex;
@Override
public void start(Stage primaryStage) throws Exception {
media = ...; // get media from somewhere
mediaView = new MediaView();
primaryStage.setScene(new Scene(new StackPane(mediaView), 720, 480));
primaryStage.show();
playNextVideo();
}
private void playNextVideo() {
disposePlayer();
if (curIndex == media.size()) {
return; // no more videos to play
}
MediaPlayer player = new MediaPlayer(media.get(curIndex++));
player.setAutoPlay(true); // play ASAP
player.setOnEndOfMedia(this::playNextVideo); // play next video when this one ends
mediaView.setMediaPlayer(player);
}
private void disposePlayer() {
MediaPlayer player = mediaView.getMediaPlayer();
if (player != null) {
player.dispose(); // release resources
}
}
}
This may cause a pause between videos. If that's not acceptable you could create the next MediaPlayer
ahead-of-time, either at the same time as the current MediaPlayer
or when the current player reaches a certain timestamp (e.g. 10 seconds before the end). But I still wouldn't create all the MediaPlayer
instances ahead-of-time.