Launch VLC in Java and connect to it via rc interf

2019-04-29 18:41发布

问题:

I've already seen this thread, but I'm still having an issue: starting vlc player in java It appears the Java bindings for VLC are no longer under active development and do not support everything possible on the command line anyway.

Given the following code, I can't launch VLC from a Java application on Mac OS 10.5.8 (Java 1.6) and then connect to it via the rc interface through the Terminal or another Java application.

public class Main {

public static void main(String[] args) {
    String s = null;


    try {
        //Process p = Runtime.getRuntime().exec("/Applications/VLC.app/Contents/MacOS/VLC -I telnet --telnet-host=localhost:4442 -I rc --rc-host=localhost:4444");
        //Process p = Runtime.getRuntime().exec("/Applications/VLC.app/Contents/MacOS/VLC -I rc --rc-host=localhost:4444");

        //ProcessBuilder pb = new ProcessBuilder("/Applications/VLC.app/Contents/MacOS/VLC","-I rc","--rc-host=localhost:4444");
        ProcessBuilder pb = new ProcessBuilder("/Applications/VLC.app/Contents/MacOS/VLC","-IRC","--rc-host=localhost:4444");
        Process p = pb.start();

        StreamGobbler errorGobbler = new StreamGobbler(p.getErrorStream(), false);
        StreamGobbler inputGobbler = new StreamGobbler(p.getInputStream(), false);
        errorGobbler.start();
        inputGobbler.start();

        System.out.println("Waiting: \n"+p.waitFor());       
        System.out.println("All done here");
        //p.destroy();
        //System.exit(0);

  } catch (IOException ioe) {
    ioe.printStackTrace();
  } catch (Exception ie) {
    ie.printStackTrace();
  }
}
}

class StreamGobbler extends Thread {
InputStream is;
boolean discard;
StreamGobbler(InputStream is, boolean discard) {
  this.is = is;
  this.discard = discard;
}
public void run() {
 try {
   InputStreamReader isr = new InputStreamReader(is);
   BufferedReader br = new BufferedReader(isr);
   String line=null;
   while ( (line = br.readLine()) != null)
     if(!discard)
       System.out.println(line);    
   }
 catch (IOException ioe) {
   ioe.printStackTrace();  
 }

} }

Here is the Java application using the Apache Commons Net package that I'm trying to connect to the above app running on the same machine:

public class TelnetTest {
public static void main(String args[]) {


    TelnetClient tl = new TelnetClient();
    try {
        tl.connect("localhost", 4444);
        if(tl.isConnected()) {
            System.out.println("Connected successfully!");

            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(tl.getOutputStream()));
            bw.write("quit");
            bw.flush();

        } else {
            System.err.println("Problem with connection");
        }
    } catch(Exception e) {
        System.err.println("Telnet connection threw an exception: "+e.getMessage());
    }
}
}

The latter app works fine if I start VLC using the commands from the first app in the Terminal. Likewise, I can't connect to the first app from the Terminal using "telnet localhost 4444" in the Terminal.

The only difference I can find is in the output from VLC. When running in the terminal:

[0x2786e8] main interface error: no interface module matched "globalhotkeys,none"
[0x2786e8] main interface error: no suitable interface module
[0x201b28] main libvlc error: interface "globalhotkeys,none" initialization failed
Remote control interface initialized. Type `help' for help.

When executing via the top Java application:

[0x4009178] main interface error: no interface module matched "globalhotkeys,none"
[0x4009178] main interface error: no suitable interface module
[0x2017a8] main libvlc error: interface "globalhotkeys,none" initialization failed
[0x4009178] main interface error: no suitable interface module
[0x2017a8] main libvlc error: interface "default" initialization failed

Can anyone help me out here? I'm at a loss. Thank you very much.

回答1:

You can run VLC as a subprocess and feed it commands through the process output stream. You need to flush the stream and sleep for a little while after each command. The following code doesn't do everything - but it does allow me to play different files in VLC under control of Java.

     String vlcParameters = String.format(
           "-I rc --rc-fake-tty --video-on-top --disable-screensaver --no-video-title-show " +
           "--no-mouse-events --no-keyboard-events --no-fullscreen --no-video-deco " +
           "--x11-display \"%s\" --video-x %d --video-y %d --width %d --height %d",
           ":0.0", // X11 display
           top,      // X
           left,      //Y
           width,    //Width
           height     //Height
           );

     ProcessBuilder pb = new ProcessBuilder("vlc", vlcParameters);

     pb.redirectErrorStream(true);

     vlcProcess = pb.start();

// Later - clear current playlist

        writer.write("clear\n".getBytes());
        writer.flush();
        Thread.sleep(10);

        String playListCommand = String.format(
              "add file://%s\n",
              filePath);

        writer.write(playListCommand.getBytes());
        writer.flush();

        Thread.sleep(milliDuration - 10);

Note - you will need another thread to read the output from VLC so it doesn't block:

     Thread inputThread = new Thread(new Runnable()
        {

        @Override
        public void run()
           {
           InputStream in = vlcProcess.getInputStream();

           BufferedReader bufin = new BufferedReader(new InputStreamReader(in));

           try
              {
              while (true)
                 {
                 String line = bufin.readLine();

                 if (line == null)
                    {
                    System.out.writeln("End of data from VLC");
                    }

                 System.out.writeln("VLC OUTPUT:" + line);
                 }
              }
           catch (IOException ex)
              {
              //...
              }
           }
        },
        "VLC stdout reader");

     inputThread.start();


回答2:

Found the solution on another forum: http://forums.sun.com/thread.jspa?threadID=5145675

You have to pass the "--rc-fake-tty" argument to VLC when running under Linux or Mac apparently.



回答3:

Since vlc opens a new DOS window in rc mode, during writer.flush() the code complains that the pipe was closed. this was also verified as the inputThread prints "VLC OUTPUT:nullEnd of data from VLC". Is there a way to avoid it, to link to the newly opened vlc rc window?

Regards

Shahid