I'm trying to write a java program to launch multiple processes and redirect stdin to the main program to both those processes, while simultaneously reading the output from those processes to stdout.
At the moment I'm trying to launch vlc
processes and later on plan to be able to control them both separately using different keyboard keys, but I would like to understand how to get this to work for any process, for example like a command line or custom telnet client, so you could spawn two command lines and send the same command inputs to both of them, or programmatically substitute parts of the commands going to each process.
The problem I'm having is that it's unpredictable which end will be sending when, so I need essentially a bidirectional pipe, or both pipes to run simultaneously. I haven't been able to work out how to do that, everything I've tried makes it hang waiting for input from either way.
I can launch the two vlc
processes, and even read both their output, but I can't send stdin to them without the processes hanging waiting for input.
Here's what I have already:
The parent class:
package multiVLC;
import java.nio.file.Path;
import java.nio.file.Paths;
public class multiVLC {
public static void main(String[] args) {
Path video1 = Paths.get("C:\\path\\to\\video1.mkv");
Path video2 = Paths.get("C:\\path\\to\\video2.mkv");
new VLCProcess(video1).start();
new VLCProcess(video2).start();
}
}
And the process:
package multiVLC;
import java.io.*;
import java.nio.file.Path;
import java.util.Scanner;
public class VLCProcess extends Thread {
private Path videofile;
public VLCProcess(Path videofile) {
this.videofile = videofile;
}
public void run() {
try {
String[] cmd = {"C:\\Program Files\\VideoLAN\\VLC\\vlc.exe", videofile.toRealPath().toString()};
ProcessBuilder ps = new ProcessBuilder(cmd);
ps.redirectErrorStream(true); // combine stdErr and stdOut
Process pr = ps.start();
BufferedReader in = new BufferedReader(new InputStreamReader(pr.getInputStream()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(pr.getOutputStream()));
BufferedReader sysin = new BufferedReader(new InputStreamReader(System.in));
String line;
Scanner scanin = new Scanner(in);
Scanner scansysin = new Scanner(sysin);
while (true) { // THIS HANGS
if (scanin.hasNextLine()) {
System.out.println(this.getName() + ":" + scanin.nextLine());
}
if (scansysin.hasNextLine()) {
out.write(scansysin.nextLine());
}
System.out.println("still in loop"); // NEVER PRINTS
}
// while ((line = in.readLine()) != null) { // THIS WORKED TO RUN TWO VLC PROCESSES, BUT DOESN'T REDIRECT STDIN
// System.out.println(this.getName() + ":" + line);
// }
// pr.waitFor(); // not sure if this is needed
} catch (IOException e) {
e.printStackTrace();
}
}
}
How can I correctly handle the pipes both ways?