Caprica Software

vlcj 4.x Tutorial

Basic Events

Building on previous tutorials, we will now add some basic media player event handlers.


Let's Get Started

You should now already have a basic template for how to create a vlcj application, so this tutorial will no longer duplicate all of the code each time - instead we'll just show the new code fragments.


Adding an Event Listener

Media player event listeners are similar to regular Swing event listeners. You simply add an instance of a MediaPlayerEventListener to your media player.

In common with many other Swing event listeners, an equivalent adapter class is provided with default empty implementations for all of the media player event listeners. Your application need then extend (via sub-classing) MediaPlayerEventAdapter and provide bespoke implementations for only the events you are interested in.

We'll start by adding our listener using an empty adapter implementation, and fill in methods for the events we're intersted in later. The listener is added before the frame is shown.

mediaPlayerComponent.mediaPlayer().events().addMediaPlayerEventListener(
new MediaPlayerEventAdapter() {
}
);
frame.setContentPane(contentPane);
frame.setVisible(true);

You can add as many different event listeners as you want. This can be useful when you have different components needing to act on different events.


Add Event Handlers

The basic events usually of interest to all applications are playing, finished and error. There are numerous other events but we will cover just those basic events here:

mediaPlayerComponent.mediaPlayer().addMediaPlayerEventListener(new MediaPlayerEventAdapter() {

@Override
public void playing(MediaPlayer mediaPlayer) {
}

@Override
public void finished(MediaPlayer mediaPlayer) {
}

@Override
public void error(MediaPlayer mediaPlayer) {
}
});

Using Template Methods

The EmbeddedMediaPlayerComponent also provides template methods for all media player events. You may find it more convenient to create a sub-class of EmbeddedMediaPlayerComponent and override the methods you are interested in.

This fragment shows the equivalent template method usage to the listener added previously:

mediaPlayerComponent = new EmbeddedMediaPlayerComponent() {

@Override
public void playing(MediaPlayer mediaPlayer) {
}

@Override
public void finished(MediaPlayer mediaPlayer) {
}

@Override
public void error(MediaPlayer mediaPlayer) {
}
};

It is up to you to choose which method - either one, other or both of adding listeners and overriding template methods.


Important Event Handling Considerations

Event notifications come in on a background thread, and as with all Swing applications you must only change user-interface state on the Swing Event Dispatch Thread. If your code performs any UI operations you must use SwingUtilities#invokeLater.

The threading model is explained more thoroughly in the next tutorial.


Add Event Handler Implementations

The playing event is raised when the media starts playback.

This example invokes a hypothetical showVideoView method to switch the application view to show a component containing the video.

@Override
public void playing(MediaPlayer mediaPlayer) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
showVideoView();
}
});
}

The finished notification is raised when the media has finished playback normally.

This example invokes a hypothetical showDefaultView method to switch the application view to some default view other than the video view.

@Override
public void finished(MediaPlayer mediaPlayer) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
showDefaultView();
}
});
}

The error notification is somewhat more interesting. When playing media it is actually an asynchronous method call - the media player play method will return immediately and LibVLC will asynchronously try and start playing the media. In practical terms, you won't immediately get a success/error indicator until some time later. The way you get the success/error indicator is via the corresponding media player events, i.e. playing or error.

In this tutorial, we'll display a standard error dialog in response to an error.

@Override
public void error(MediaPlayer mediaPlayer) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JOptionPane.showMessageDialog(
frame,
"Failed to play media",
"Error",
JOptionPane.ERROR_MESSAGE
);
}
});
}

All of these event handler implementations update user interface state so must be executed on the Swing Event Dispatch Thread via SwingUtilities.invokeLater - in your own application this may not always be the case for certain events.