I am making a media player using Javafx and VLCJ.
The app contains a list view in which all the Media files. i.e. audio and video that the user selected are listed. Its like a playlist. I want to show the total Play time of the entire playlist. I also want to display the duration of individual media at the side. e.g.
1> my_visiting_video.mp4 | 01:21:35
2> avengers_end_game.flv | 02:13:40
TotalDuration: 03:35:15
above is the sample of my playlist that I would like to display in the app.
Following is what I did
DMediaPlayer.java
import uk.co.caprica.vlcj.factory.MediaPlayerFactory;
import uk.co.caprica.vlcj.javafx.fullscreen.JavaFXFullScreenStrategy;
import uk.co.caprica.vlcj.javafx.videosurface.ImageViewVideoSurface;
import uk.co.caprica.vlcj.player.base.MediaPlayer;
import uk.co.caprica.vlcj.player.base.MediaPlayerEventAdapter;
import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer;
public class DMediaPlayer implements MediaPlayerInterface {
private ImageView mediaView;
private final MediaPlayerFactory mediaPlayerFactory;
private final EmbeddedMediaPlayer embeddedMediaPlayer;
public DMediaPlayer() {
this.mediaPlayerFactory = new MediaPlayerFactory();
this.embeddedMediaPlayer = mediaPlayerFactory.mediaPlayers().newEmbeddedMediaPlayer();
this.mediaView = new ImageView();
this.mediaView.setPreserveRatio(true);
embeddedMediaPlayer.videoSurface().set(new ImageViewVideoSurface(this.mediaView));
}
@Override
public void load(String filePath) throws FileNotFoundException {
embeddedMediaPlayer.media().startPaused(filePath);
embeddedMediaPlayer.controls().setPosition(0f);
}
@Override
public ImageView getMediaView(){
return mediaView;
}
}
The above class returns a ImageView i.e. DMediaPlayer().getMediaView()
and this ImageView is added inside another class that controls all the playbacks, As well as that class has the playlist. For now the playlist only displays the available media files audio/video. It works fine.
But I want to add a new feature in which the list view not only displays the media files but also some additional information like total play time of the entire playlist and the play time of individual media file.
following is what I did.
File[] mediaList; // it is initialized in the constructor
private void updatePlayList(){
CompletableFuture.runAsync(() -> {
long totalDur = 0;
MediaPlayerFactory factory = new MediaPlayerFactory();
EmbeddedMediaPlayer player = factory.mediaPlayers().newEmbeddedMediaPlayer();
for (int i = 0; i < mediaList.length; i++){
long mediaDur = 0;
player.media().startPaused(mediaList[i].getAbsolutePath());
mediaDur = player.status().length();
totalDur += mediaDur;
drawer.addItem(
(i+1) + "> " +
mediaList[i].getName().substring(0, 25) + "..." +
" | " + millisToDuration(mediaDur)
);
}
drawer.getTotalDuration().setText("Total Duration: " + totalDur);
});
}
drawer is a class that controls ListView. everything works fine except the vlcj. It throws the following error.
../include/vlc_xlib.h:46:vlc_xlib_init: Xlib not initialized for threads.
This process is probably using LibVLC incorrectly.
Pass "--no-xlib" to libvlc_new() to fix this.
Exception in thread "ForkJoinPool.commonPool-worker-3" java.lang.IllegalStateException: Not on FX application thread; currentThread = ForkJoinPool.commonPool-worker-3
at javafx.graphics@19/com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:299)
at javafx.graphics@19/com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:458)
at javafx.graphics@19/javafx.scene.Parent$3.onProposedChange(Parent.java:474)
at javafx.base@19/com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:113)
at javafx.base@19/com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:108)
at javafx.controls@19/javafx.scene.control.skin.LabeledSkinBase.updateChildren(LabeledSkinBase.java:282)
at javafx.controls@19/javafx.scene.control.skin.LabeledSkinBase.lambda$new$11(LabeledSkinBase.java:219)
at javafx.controls@19/com.sun.javafx.scene.control.LambdaMultiplePropertyChangeListenerHandler.lambda$new$1(LambdaMultiplePropertyChangeListenerHandler.java:88)
at javafx.base@19/javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:86)
at javafx.base@19/com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:181)
at javafx.base@19/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80)
at javafx.base@19/javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:104)
at javafx.base@19/javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:111)
at javafx.base@19/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:145)
at javafx.base@19/javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:50)
at javafx.base@19/javafx.beans.property.StringProperty.setValue(StringProperty.java:71)
at javafx.controls@19/javafx.scene.control.Labeled.setText(Labeled.java:147)
at com.doruk.dplayer.controllers.PlayerController.lambda$updatePlayList$2(PlayerController.java:108)
at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804)
at java.base/java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1796)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
Now how can I fix this error, or how can I run the vlcj in the background? I mentioned background because, additional window opens that plays the video when I run the app.
or am I following the wrong approach...? is there better way...? all I want is to display the playtime of each media in the list.
I went through several pages in this website but all I could find was to get the total time of the file currently being played. So I followed the above approach. i.e. create a separate media player and start it and then calculate the play time.