Using java Process builder to play wav file - java

I would like to send the following command below from a java program, but not overly bothered about reading the response. any idea how I can do this
the command below plays the wav file from the command prompt
aplay ~/javafx/examples/PrayerTime/src/Audio/athan1.wav
I am trying the code below but it is not playing anything! from my java program
ProcessBuilder processBuilder = new ProcessBuilder("bash", "-c", "aplay ~/javafx/examples/PrayerTime/src/Audio/athan1.wav");
try {
Process process = processBuilder.start();
} catch (IOException ex) {
Logger.getLogger(JavaFXApplication4.class.getName()).log(Level.SEVERE, null, ex);
}

Andrew is absolutely right when he writes ignoring the output is the core of the problem.
When you start a process via processBuilder.start(), you are basically launching another process that has a life of its own. It's fire and forget. The only feedback you get via thrown exceptions is when the actual lauching didn't succeed. It says nothing about whether the launched process succeeded in what it was supposed to do.
Since you don't see an error message, the launching of the process went fine.
Now, using aplay and ~ suggests, that you are on some kind of Unix, probably Linux. There a process prints regular output to the standard out stream and error output to standard error stream. It also returns an exit code, that indicates whether things went smoothly or not. Both the exit code (you can get it from the process object by using waitFor()) and the error stream (also available from the process object) give you all the necessary info whether a process succeeded and if not, why not.
That all said, you might really want to use Runtime.exec() as it is much less complicated—at least until you know how to call your process without error.

Related

Can Clojure Capture Standard Out of Existing Process?

In a Clojure program, how do you read from standard out? I want to do that, or pipe the standard output, to an input stream that I create. The standard output in Clojure is a java.io.PrintWriter .
I have a Samza job, started by a Clojure program. There's also an nrepl server to which I can remotely connect. After connecting, I need to be able to tap into and tail standard out (to which jobs write their output).
1) As per this SO question, with-out-str (see here) lets us temporarily bind *out* (to a java.io.StringWriter), so that your executed code writes to a string. But that doesn't let me tap into the existing *out*.
2) If you look at clojure.java.shell (see here), it gets the JVM's Runtime and exec's a Process on it. From that process, you can get its standard output stream. But again, that's not the default standard out (*out*) I'm looking for.
3) This SO question gets close to what I'm trying to do. But again, I'm connecting to an existing process, and want to tail out its standard output.
Is this possible in Clojure (see here)? Has anyone solved this?
Process output is not a publish subscribe model, so in effect when a process puts a character into it's output buffer, exactly one process gets to pull it off that buffer. If you have a program that was started by a shell that shell process if reading it's output and writing it to a terminal (or reading and ignoring it). If you attach your process after the process that started it and start trying to grab the data, you will most likely not get anything because the parent process will get it first. I just tried this from two terminals:
Terminal 1:
cat
Terminal 2:
ps -ef | grep cat
tail -f /proc/24547/fd/2
Terminal 1:
hello
Terminal 2:
< nothing >
The string "hello" printed to terminal 1, the process that started it.
It's tempting then to say "well what if nobody reads the output, then it will be there for me to get". While this sounds good it runs into the problem that these are fixed sized buffers, so as soon as the output buffer is full the process that is trying to write to it blocks (is prevented from running at all) until someone reads the output to unblock it.
The general solution is to pipe the process you want to tail later to the tee command which writes the output to a file and passes it to whatever was reading it.
command-to-watch arg1 arg2 | tee logfile.potentially-huge
Though if you go this route you should rotate the log file before your disk fills. Make sure you empty the log file with exactly this command
echo > logfile.potentially-huge
or use your program to make a truncate call to the file. simply deleting the file will remove it's name from the log directory without deleting it, it will silently continue to grow taking up disk space and the new file will get no output ever.
This is basically why we built log libraries like log4j (in the 90s) and syslog (in the 80s).
If you still want to get hackish crazy on this, turn to tmux, it can do anything, and changes the way people work with text. In all seriousness you should change the way the other process creates it's output to make it easier to get.

Java receives an error executing Ruby script; Terminal doesn't

This is a forked problem off of this question: flac: "ERROR: input file has an ID3v2 tag" (it doesn't). I've solved the initial issue there but that didn't resolve one problem I was having, so I'm going to introduce it separately here.
I'm using a Ruby gem called speech2text to convert an audio file into (approximated) text. Calling it on the command line works fine (Mac Terminal). However, the following Java code:
String[] cmd = {"speech2text", "tmp/audio/pop-test-audio.wav"};
ProcessBuilder builder = new ProcessBuilder(cmd);
builder.redirectErrorStream(true);
Process process = builder.start();
Only receives this back from the process streams:
/Library/Ruby/Gems/1.8/gems/speech2text-0.3.4/lib/speech/audio_inspector.rb:50:in `initialize': undefined method `first' for nil:NilClass (NoMethodError)
from /Library/Ruby/Gems/1.8/gems/speech2text-0.3.4/lib/speech/audio_splitter.rb:77:in `new'
from /Library/Ruby/Gems/1.8/gems/speech2text-0.3.4/lib/speech/audio_splitter.rb:77:in `initialize'
from /Library/Ruby/Gems/1.8/gems/speech2text-0.3.4/lib/speech/audio_to_text.rb:15:in `new'
from /Library/Ruby/Gems/1.8/gems/speech2text-0.3.4/lib/speech/audio_to_text.rb:15:in `to_text'
from /Library/Ruby/Gems/1.8/gems/speech2text-0.3.4/bin/speech2text:11
from /usr/bin/speech2text:19:in `load'
from /usr/bin/speech2text:19
I don't know anything about Ruby, hence my lightweight use of the library through Java. I really can't tell what's going on here, but I know that it works when executed in exactly the same way from the Terminal. Has anyone got any idea what might be causing this?
You could also ditch the terminal and try JRuby. It's just as fast as the normal Ruby VM and is easier to integrate with Java.
I have had similar issues trying to run jslint.js (for node.js). I actually did better running bash first, then print writing in my commands that way, but even that had problems as I recall.
Basically the problem is that executing things with Java can fail when environment settings that would otherwise be available are not loaded. This can be a tough one to solve.

Missing command line output from Java process in Windows

I have some simple code that uses Java apache exec classes to run external processes.
Executor ex = new DefaultExecutor();
ex.setStreamHandler(new PumpStreamHandler(System.out, System.out, System.in));
CommandLine cl = new CommandLine(
"C:\\program.exe");
ex.execute(cl);
}
For certain command line programs, this works as expected and gets all the program's output into the "out" stream while accepting my own text into the "in" stream. However, for other programs, the output of the process is visible running manually from command line, but I don't get anything coming in when I run via java process.
I would like to eventually write to the stdin and retrieve and analyze stdout within the code itself.
If there a reason that I don't know of, why some programs seem to output text on the command line, yet when I run them as java processes, I don't receive anything through the streams?
This is happening in Windows.
Out of process code will not go to the same command line output unless you explicitly configure it to do so. Also, as a general rule it is better to use a logging library like log4j than to do println statements.

Running a continuous batch process in Java

I have a batch file which performs the operation of listening to the microphone and converting it to text (i am using pocket sphinx).
The command I am using to run the batch file is pocketsphinx_continuous.exe -dict <dict name> -lm <language model> -hmm <acoustic model location>. The batch file starts off and keeps listening to the microphone. Whenever we finish speaking a sentence it converts it into text on the command prompt. Since this continuously running we terminate this task by Ctrl-C.
I was trying to make this into a standalone Java application. I wanted to run this batch file through Java, so i used Runtime.getRuntime().exec("cmd /c start pocketsphinx_continuous.exe ...") with all the parameters. However strangely, it starts the batch process in a separate command prompt but immediately exits. I tried to use process.waitfor(), however it simply starts executing the batch process and then terminates. I havent called process.destroy, so i am unable to figure out why it exits the batch process.
The other question is since the batch file is running continuously, after every spoken sentence has been transcribed , I wish to get the output in my Java application. I know i can redirect the batch process to a file and then read the file, was just wondering if there is a more direct process. Could you please help me figure out where I am making a mistake.
You should use Process.getInputStream() and Process.getErrorStream() to find out what messages it prints out.
If it is exiting instantly, you might need to get the exit code (Process.waitFor()) and check the error logs from the error stream.
Also, if you can post some of your code we might be able to help. In general, these problems are due to incorrectly configured paths or command strings.
A possible fix would be to use the ProcessBuilder from Java 1.5 thusly:
// Note the lack of "cmd \c" - you shouldn't need to run it in a cmd window!
ProcessBuilder pb = new ProcessBuilder("pocketsphinx_continuous.exe",
"dict", "1121.dic",
"-lm", "1121.lm",
"-hmm", "hub4/hmm");
Process p = pb.start();
// TODO for you:
// 1. Create Threads to handle the input
// 2. Store the Process instance so that you can call p.destroy() later.
// 3. If interested, have a Thread doing p.waitFor() to get the exit code.
As Joachim Sauer mentioned in the comments, this Javaworld article explains a lot of the gotchas associated with the Process API, so have a read through. I haven't had a chance to play with the improvements made in JDK7 to the Process API, and by the looks of things Oracle are improving it again for JDK8 (JEP 102).
You can also use Timer and TimerTask to schedule your batch scan process in background. You can use this to specify infinite running task.

Java runtime.exec causes program crash

I am trying to run an external program Decoder.exe using a java:
Runtime.getRuntime().exec("C:\fullpath-and-so-on\Decoder.exe -h"); like so:
try{
Process p = Runtime.getRuntime().exec("C:\\fullpath-and-so-on\\Decoder.exe -h");
}
catch(Exception e){
e.printStackTrace();
}
This works for all other programs I've tried. But whenever I execute it from java the Decoder.exe crashes. The java executes fine and does not generate any exceptions but the called program Decodes.exe stops working. The program Decoder.exe executes perfectly when run in a separate cmd window.
Have anyone had any experience with a similar problem? What differs when java runs exec and when a program is run in cmd.exe? Is there a known workaround or am I just making a mistake somewhere?
Very thankful for any help!
BR,
Fredrik
Stops working you say?
Is the decoder.exe writing output to stderr or stdout? You must in that case read those streams, since the buffers for the streams are very small, and the execution will halt if those buffers get full.
This is a great article, it's old, but it still holds:
When Runtime.exec() won't
this tutorial can help you with that http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=1
and
ProcessBuilder
and
Oracle API
maybe my question Pass String as params from one Java App to another

Categories

Resources