Search code examples
javajavafxurimedia-player

Difficulty with URI syntax and conversion to string


My friend and I have been working on a Java project to create a simple media player using the Media, MediaPlayer, and MediaView classes. However, from the start we've had issues successfully opening the video that we're using as a test file. After many angry runtime exceptions, we finally figured out that the source of our problem was the String being passed into each object (Media needs a String that represents the File Path in a URI format). After some modifications, we found that the following URI worked on my computer to open the File:

Media m = new Media("file:///C:/Users/mewww/Google%20Drive/Java/SmartPlay/EXO-MonsterMV.mp4");
MediaPlayer mp = new MediaPlayer(m);
MediaView mv = new MediaView(mp);

However, we later tried to implement an Open method that would allow the user to choose which File (as a File object) they wanted to play. When we did this, we used the following to open the file:

File currentFile = new File(null);

FileChooser fc = new FileChooser();
fc.setTitle("Open");
currentFile = fc.showOpenDialog(null);

Media m = new Media(currentFile.toURI().toString());
MediaPlayer mp = new MediaPlayer(m);
MediaView mv = new MediaView(mp);

This started giving us runtime exceptions again and so we used a println into the console to find out what the problem was. The string being used was now two "/"s short of what it was supposed to be as:

"file:/C:/Users/mewww/Google%20Drive/Java/SmartPlay/EXO-MonsterMV.mp4"

However, even after modifying the string, we still received the same runtime error as soon as the file was selected:

Exception in Application start method
java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(LauncherImpl.java:182)

We then commented the whole Open method out and went back to our original code, but continue to receive the same errors.

Our full code is available here:

SmartPlay class

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.paint.Color;
import java.io.File;
import javafx.stage.FileChooser;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.application.Platform;

public class SmartPlay extends Application {
    File currentFile;
    Scene scene;

  @Override
  public void start(Stage primary) {
    primary.setTitle("SmartPlay");
    selectCurrentFileToOpen();
  //Player(currentFile.toURI().toString().substring(0,5)+"//"+currentFile.toURI().toString().substring(5));
    Player player = new Player("file:///C:/Users/mewww/Google%20Drive/Java/SmartPlay/EXOMonsterMV.mp4");

    scene = new Scene(player, 720, 480, Color.BLACK);
    player.setTop(makeMenus());

    primary.setScene(scene);
    primary.show();
  }

  private MenuBar makeMenus() {
      MenuBar mb = new MenuBar();
      Menu fileMenu = new Menu("File");
      MenuItem openItem = new MenuItem("Open...");
      openItem.setOnAction(e -> {
          selectCurrentFileToOpen();
          scene.setRoot(new Player(currentFile.toURI()));
      });
      MenuItem quitItem = new MenuItem("Quit");
      quitItem.setOnAction(e -> Platform.exit());
      fileMenu.getItems().addAll(openItem, quitItem);
      return mb;
  }

  public boolean selectCurrentFileToOpen() {
      FileChooser fc = new FileChooser();
      fc.setTitle("Open");
      currentFile = fc.showOpenDialog(null);
      return true;
  }

  public void stop() {
  }

  public static void main(String[] args) {
      launch(args);
  }
}

Player class

import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import java.net.URI;

public class Player extends BorderPane {
    Media m;
    MediaPlayer mp;
    MediaView mv;
    Pane p;
    MediaBar bar;

    public Player(String file) {
        m = new Media(file);
        mp = new MediaPlayer(m);
        mv = new MediaView(mp);

        p = new Pane();
        p.getChildren().addAll(mv);
        setCenter(p);

        bar = new MediaBar(mp);

        setBottom(bar);

        setStyle("-fx-background-color:#cccccc");

        mp.play();
    }
}

MediaBar class

import javafx.scene.layout.HBox;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.media.MediaPlayer;
import javafx.scene.layout.Priority;
import javafx.scene.control.Slider;
import javafx.scene.control.Label;
import javafx.scene.control.Button;
import javafx.util.Duration;

public class MediaBar extends HBox {
    Slider time = new Slider();
    Slider vol = new Slider();

    Button playButton = new Button("Pause");
    Button halfSpeed = new Button("0.5x");
    Button normalSpeed = new Button("1.0x");
    Button doubleSpeed = new Button("2.0x");

    Label volume = new Label("Volume: ");
    Label nowTime;

    MediaPlayer player;

    public MediaBar(MediaPlayer play) {
        player = play;

        setAlignment(Pos.CENTER);
        setPadding(new Insets(5,10,5,10));

        vol.setPrefWidth(70);
        vol.setMinWidth(30);
        vol.setValue(100);

        nowTime = new Label(formatTime(player.getCurrentTime()) + "/" + formatTime(player.getTotalDuration()));
        HBox.setHgrow(time, Priority.ALWAYS);

        playButton.setPrefWidth(30);

        getChildren().addAll(playButton,time,nowTime,volume,vol);        
    }

    public static String formatTime(Duration duration) {  //StackOverflow: Jon Skeet
        long seconds = (long) duration.toSeconds();
        long absSeconds = Math.abs(seconds);
        String positive = String.format(
            "%d:%02d:%02d",
            //absSeconds / 3600,
            (absSeconds % 3600) / 60,
            absSeconds % 60);
        return seconds < 0 ? "-" + positive : positive;
    }
}

Solution

  • So I ran your code in command line and I was able to get a more specific debug error. So it seems like the time formatting you do in your MediaBar is causing the error. I don't know exactly what you are trying to do with that but the way you format the time is incorrect. If you comment it out as well as the other things you use to add the time formatting the URI path will be correct and your video should run fine. I know that for the formatting you are missing a '%02d'. As for what you are formatting I am not too sure so I cannot help you there.