Stacked
Stacked

Reputation: 861

Launch multiple instances of external console application in QT and capture output?

I am learning Qt and manged to use the following code from tutorials to launch external application and process output received from it :

void Dialog::on_startButton_clicked()
{

    QString program = "C:/Program Files/ffmpeg/bin/ffmpeg.exe";
    mTranscodingProcess = new QProcess(this);
    connect(mTranscodingProcess, SIGNAL(started()), this, SLOT(processStarted()));
connect(mTranscodingProcess,SIGNAL(readyReadStandardOutput()),this,SLOT(readyReadStandardOutput()));
    connect(mTranscodingProcess, SIGNAL(finished(int)), this, SLOT(encodingFinished()));


    QStringList arguments;
    QString input = "myfile_path_1";
    QString input2 = "myfile_path_2";

    arguments << "-y" << "-i" << input << "-i" << input2 << "-c" << "copy" << "output.avi" ;

    qDebug() << arguments;

    mTranscodingProcess->setProcessChannelMode(QProcess::MergedChannels);
    mTranscodingProcess->start(program, arguments);
}

This works as expected and I can capture and process output from readyReadStandardOutput() and encodingFinished() slots in my app.

Now my question is : How to launch additional jobs of the above and receive separate updates from each instance.

Upvotes: 3

Views: 1349

Answers (1)

Jeremy Friesner
Jeremy Friesner

Reputation: 73379

Launching the additional jobs and receiving updates is easy enough; you just execute the code you posted above multiple times.

The only slightly tricky part (and I think the core of your question) is how to tell, when your readReadyStandardOutput() (or etc) slot is called, which of the several QProcess objects was the one that called it.

There are several ways to deal with that. In no particular order:

  • You could declare different slots for each QProcess object (e.g. readReadyStandardOutput1(), readReadyStandardOutput2(), etc) and connect each QProcess to different slots. (Not really recommended unless you only have a very small number of QProcesses)

  • You could create a separate ProcessLauncher class that derives from QObject, and create one ProcessLauncher object for each task you want to launch. Have each ProcessLauncher object create its own QProcess object and connect the QProcess's signals to the ProcessLauncher's slots. Since there is a 1:1 relationship between each ProcessLauncher and its QProcess, the ProcessLauncher would know that its slots were being called by its own QProcess and no other.

  • You could use a QSignalMapper object to help you differentiate the signals from each other.

  • Or, if you don't mind subverting the object-oriented nature of the signals-and-slots paradigm, your slot methods can call QObject::sender() to find out which QProcess it is that emitted the signal, and alter their behavior based on sender()'s return value.

Upvotes: 5

Related Questions