xeruf
xeruf

Reputation: 2990

Correct way to check if JavaFX MediaPlayer can play a file

Currently, this is how I check if a file is playable through the JavaFX MediaPlayer, since it's the way it is done internally.

import static com.sun.media.jfxmedia.MediaManager.canPlayContentType;
import static com.sun.media.jfxmediaimpl.MediaUtils.filenameToContentType;

public boolean isPlayable(String filename) {
    return canPlayContentType(filenameToContentType(filename));
}

the problem is that the packages that contain these Methods "are not API" and not accessible on Java 9 anymore. I know that there are workarounds, but I wonder if there is an actually correct, future-proof way of doing this?

I want this method to populate a Library with all the playable content within a directory:

Files.find(folderPath, Integer.MAX_VALUE, (path, attr) -> 
        attr.isRegularFile() && isPlayable(path.toFile().getName()))
        .forEach(path -> addSong(path));

Upvotes: 2

Views: 1151

Answers (2)

user28775
user28775

Reputation: 169

Try this

//make a class like this
public class FindSongs extends SimpleFileVisitor<Path> {
    public static LinkedList<Path> songPaths = new LinkedList<>();
    @Override
    public FileVisitResult visitFile(Path path, BasicFileAttributes attr) {
        try{
            //System.out.println(path.toString());
            Media media = new Media(path.toUri().toString());
            MediaPlayer mediaPlayer = new MediaPlayer(media);
            mediaPlayer.dispose();
            songPaths.add(path);
        }catch(Exception ex){
            //ex.printStackTrace();
            System.out.println("not playable: "+path.toString());
        }
        
        return CONTINUE;
    }
}

//run this
Files.walkFileTree(Paths.get(args[0]), new FindSongs());

Then use FindSongs.songPaths variable for the list of all your songs. :)

Upvotes: 0

Naman
Naman

Reputation: 31878

I went through the documentation of javafx.media module for the sake of finding any such built-in API and was unable to find one.


A look at the existing Implementation of filenameToContentType(String filename), which is somewhat:-

if (extension.equals(FILE_TYPE_AIF) || extension.equals(FILE_TYPE_AIFF)) {
    contentType = CONTENT_TYPE_AIFF;
} else if ... other content types

That eventually checks if the current file extension is one of the supported container type and returns the content types based on the same.

The other piece on the board crucially was canPlayContentType(String contentType) which seems to be relying eventually on the supportedContentTypes for each platform as defined in the NativeMediaManager class.


Though I haven't tested the solution as proposed below primarily due to unawareness of the overview of the task that you intend to perform eventually. Yet, the closest to your current implementation and what Basic PlayBack guidelines suggests as well, was to try


Further, the exception type MediaException.Type MEDIA_UNSUPPORTED states that

Indicates that this media type is not supported by this platform.

Drawing from the analogy with this and your current solution, you could probably make use of the this:

private static boolean isPlayable(String filename) {
    try {
        Media media = new Media(filename);
    } catch (MediaException e) {
        if (e.getType() == MediaException.Type.MEDIA_UNSUPPORTED) {
            return false;
        }
    }
    return true;
}

PS: Though I believe this could be further optimized if you actually start making use of the Media constructed(as in the above stub) right away in your piece of code instead of just dropping it.

Upvotes: 1

Related Questions