0

I have an Arraylist path containing paths to different .mp3 files. My current solution plays the clips as expected however plays them simultaneously. I wish for the media to complete it's play-through before reaching the end of the loop and increasing i. I've had a Google and explored similar questions on here but none of the solutions seem to work as expected. See the current solution below:

public static void play(ArrayList path) {
        for(int i = 0; i < path.size(); i++) {
            String file = Main.gameDir + "/assets/sound/" + path.get(i) + ".mp3";
            Media sound = new Media(new File(file).toURI().toString());
            MediaPlayer mediaPlayer = new MediaPlayer(sound);
            mediaPlayer.play();
        }
}

I have tried getting the status, but this always returns UNKNOWN.

All and any help appreciated.

Sam Walker
  • 21
  • 3
  • Check out [my answer here](https://stackoverflow.com/a/61297536/6395627). It uses `MediaView` but you should be able to easily adapt it for pure audio. Basically, the solution is to not use a loop but instead react to when one `MediaPlayer` ends and play the next one. – Slaw Jun 17 '20 at 03:48

1 Answers1

0

As you have discovered, MediaPlayer#Play(Media) plays the sounds simultaneously. What you want to achieve is playing another sound if the current one has ended. You can do so by registering an event handler via MediaPlayer#setOnEndOfMedia(Runnable). In your event listener, you could fetch the next sound and play it, for example this way:

public static void play(List<String> paths) {
    LinkedList<Media> sounds = paths.stream().serial()
        .map(path -> Main.gameDir + "/assets/sound/" + path + ".mp3")
        .map(file -> new Media(new File(file).toURI().toString()))
        .collect(Collectors.toList(LinkedList::new));
    [ThisClass].play(sounds);
}

public static void play(LinkedList<Media> sounds) {
    if (sounds.isEmpty())
        return;
    MediaPlayer player = new MediaPlayer(sounds.poll());
    player.setOnEndOfMedia(() -> [ThisClass].play(sounds));
    player.play();
}

You need to replace [ThisClass] with your own class name. I also took the liberty of adding a generic parameter to the List you are providing and made it less specific (no need for ArrayList, List is enough), and replaced your explicit loop with streams.

Polygnome
  • 7,639
  • 2
  • 37
  • 57