Display Stdout / Stderr in Plugin

• Jun 2, 2012 - 15:02

I'm running an external program from a plugin and I would like to display the output and error (stdio / stderr) returned from the external program.

With the plugin code like this:

var midiSightReader = new QProcess();
midiSightReader.setStandardOutputFile(pluginPath+"/MidiSightReader.log");
midiSightReader.start("java");
midiSightReader.waitForStarted();
midiSightReader.waitForFinished();

... I get the log file created OK and it contains the results of running Java.

However, I want to grab the output and display it in a message box. I have tried various options, but none have worked yet - there is nothing to display.
var midiSightReader = new QProcess();
midiSightReader.start("java");
midiSightReader.waitForStarted();
midiSightReader.waitForFinished();
showMessage("Info2", ""+midiSightReader.readAllStandardOutput().constData);
showMessage("Info2", ""+midiSightReader.readAllStandardError().constData);

//---------------------------------------------------------
// display a message box with error message
//---------------------------------------------------------
function showMessage(title, errorText){
mb = new QMessageBox();
mb.setWindowTitle(title);
mb.text = errorText;
mb.exec();
}

Can anyone give me some clues please?


Comments

In reply to by [DELETED] 5

Thanks.

I was trying something along the lines of:
var args = new Array();
args[0]= pluginPath;
args[1]= file;
var midiSightReader = new QProcess();
midiSightReader.start('java -classpath "'+pluginPath+'/MIDISightReader/MIDISightReader.jar;'+pluginPath+'/MIDISightReader/javaosc.jar" com.dch.sightreader.MIDISightReaderPlugin', args);

... which does not produce any output anywhere!

The trick is to reformat it as:
var midiSightReader = new QProcess();
var args = new Array();
args[0]= "-classpath";
args[1]= pluginPath+"/MIDISightReader/MIDISightReader.jar;"+pluginPath+"/MIDISightReader/javaosc.jar";
args[2]= "com.dch.sightreader.MIDISightReaderPlugin";
args[3]= pluginPath;
args[4]= file;
midiSightReader.start("java", args);

In reply to by DonH

Well, the code above worked, and I can get messages from my Java program, but when I do:
midiSightReader.waitForStarted();
midiSightReader.waitForFinished();

... it does not wait for my Java program to complete. If my Java program errors quickly (e.g. the MIDI keyboard is not plugged in) then I can read the error file from the JavaSript bit of the plugin and it all works fine, but if the Java runs for a longer time, the waitForFinished() call completes too early.

Sounds odd, but perhaps the Java command spawns off my program and then completes, leaving my program running, but as the Java command has completed, the waitForFinished() triggers while my program is still running...?

How does the MuseScore plugin run QProcess? Synchronously in the same thread, or asynchronously?
Perhaps I need to poll the error channel and only complete the plugin JavaScript when a message comes in - my program will then need to return and "error" when it has completed.

In reply to by DonH

I changed the above code to do:
midiSightReader.waitForFinished(-1);

This did wait until the Java had completed, but unfortunately I guess the plugin is running in the GUI thread, so the GUI locks up until my Java code completes.
This means that the OSC commands that my Java is sending to turn MuseScore notes green do not get processed in real time. They get processed after my Java code has completed, which is no use to me for this application.

Any other way to feedback messages from my Java code and show them as message boxes / alerts in MuseScore?

In reply to by [DELETED] 5

This code (https://github.com/lasconic/Audiveris/blob/master/audiveris.js) nearly works for me, but when I write to stderr from my Java, it comes to the JavaScript bit of the plugin as a QByteArray. Your code from the audiversis example just displays the word "QByteArray" - my error text is not displayed.

Is there a way to convert a QByteArray to something that can be displayed, either in your UI code above, or just in a standard messagebox?

In reply to by DonH

As I don't know how to convert a QByteArray to something that can be displayed, I have a not-very-good solution...

In the JavaScript bit of the plugin, I setup the err stream to trigger a message to the user.
midiSightReader.readyReadStandardError.connect(logMessage);

The Java bit of the plugin writes a message to a file, then writes to System.err to trigger the above bit of code.

The JavaScript then reads the message from the file and displays it:
function logMessage()
{
// Display the msg file, which I am using for messages.
var file = new QFile(pluginPath+"/MIDISightReader/MIDISightReader.msg");
var line;
var content ="";
if (file.open(QIODevice.ReadOnly))
{
// File opened successfully
var t = new QTextStream(file); // Use a text stream

do
{
line = t.readLine(); // Line of text excluding '\n'
// Display the line.
content +=line;
content +='\n'; // Add the missing '\n'
} while(line);

// Close the file
file.close();
}
if(content.length > 1)
{
showMessage("Message", content);
}
else
{
showMessage("Message", "MIDISightReader has completed.\n");
}
}

So the JavaScript ignores what is in stderr & displays the message from the file.

If that's a tad confusing, lookout for V1.01 of the MIDISightReader plugin. I'm hoping a mate will test it on Linux & then I'll upload it.

Do you still have an unanswered question? Please log in first to post your question.