qt4 signal is not emitted - qt

I have a QT4 application which wraps libssh2 in order to communicate with the embedded devices on the network. The following snippet is making me crazy for a while.
SSHClient ssh_client(host, 22);
try {
ssh_client.connect_to_host(USERNAME, PASSWORD);
ssh_client.receive_file(file_name, file_path);
} catch(const SSHException &excp) {
qDebug() << "test";
emit console(excp.what());
return;
}
I put breakpoints to qDebug() << "test"; and emit console(excp.what()); in debugger, however, they never get hit even though an SSHException is thrown. If i put a breakpoint to the return; statement, it stops with no problem.
The output is also strange. qDebug() << "test" does what it is supposed to do, but, emit console(excp.what()); is not emitting a signal. And when the control reaches to the return; statement, it returns, again with no problem.

Related

how to start QTimer so that the GUI does not hangs-RestartStoppedProcess()-code

I have made new QTimer object in my class's ctor. When the application starts the timer also starts with the specified time. This timer keeps a track of all the process IDs and if finds that a particular process-id is not active(killed from task manager) then it restarts that particular process. Now the issue is my application lags a-bit due to this QTimer object and only after the timeout, the application becomes smooth. But after 5 seconds the timer starts again and the application starts lagging again. What is the best alternative to start a QTimer object apart from ctor of a class?
qTimer = new QTimer(0);
connect(qTimer, SIGNAL(timeout()), this, SLOT(RestartStoppedProcess()), Qt::DirectConnection);
connect(qTimer, SIGNAL(destroyed()), qTimer, SLOT(deleteLater()), Qt::DirectConnection);
qTimer->setTimerType(Qt::VeryCoarseTimer);
qTimer->start(5000);
void ProcessMonitor::RestartStoppedProcess()
{
try
{
QProcess *objMonitorProcess = new QProcess(this);
connect(objMonitorProcess, SIGNAL(finished(int,QProcess::ExitStatus)), objMonitorProcess, SLOT(deleteLater()));
for(int i = 0; i < ui->twShowProcess->rowCount(); i++)
{
#ifdef Q_WS_LIN
// objMonitorProcess->start("pidof", QStringList() << (ui->twShowProcess->item(i, 0)->text()), QIODevice::ReadOnly);
objMonitorProcess->start("pidof "+ (ui->twShowProcess->item(i, 0)->text()), QIODevice::ReadOnly);
#elif Q_WS_WIN
QString cmd("wmic process where ");
QString qszFilters("\"processid=\'");
QString qszSubFilters = qszFilters.append(ui->twShowProcess->item(i, 1)->text().append("\'").append("\"").append(" get name"));
cmd.append(qszSubFilters);
objMonitorProcess->start(cmd.toStdString().c_str(), QIODevice::ReadOnly);
#else
QString qszProcessName = ui->twShowProcess->item(i, 0)->text().split(".").takeFirst();
objMonitorProcess->start("pgrep", QStringList() << qszProcessName, QIODevice::ReadOnly);
#endif
if((objMonitorProcess->waitForStarted(4000) == true) && (objMonitorProcess->state() == QProcess::Running))
{
if(objMonitorProcess->waitForFinished(3000) == false)
continue;
else
{
QString qszProcessStatus = ui->twShowProcess->item(i, 3)->text();
if(qszProcessStatus.compare("Running") == 0)
{
QString qszStandardOutput, qszStandardError;
qszStandardOutput.clear(); qszStandardError.clear();
qszStandardOutput = QString(objMonitorProcess->readAllStandardOutput());
qszStandardError = QString(objMonitorProcess->readAllStandardError());
if(qszStandardError.simplified().compare("No Instance(s) Available.", Qt::CaseInsensitive) == 0 && qszStandardOutput.simplified().isEmpty() == true)
{
ui->twShowProcess->selectRow(i);
if(ui->twShowProcess->selectedItems().at(0)->text().compare("LTtagdb.exe", Qt::CaseInsensitive) == 0 ||
ui->twShowProcess->selectedItems().at(0)->text().compare("LTmessagebroker.exe", Qt::CaseInsensitive) == 0)
this->StopAllApplicationsForcefully();
else
this->on_actionStop_triggered();
if(this->ptrobjContextMenu->isVisible())
this->ptrobjContextMenu->close();
ui->twShowProcess->clearSelection();
if(mobj_ProcessLogMap.mobj_ProcessAndLogMapping.contains(ui->twShowProcess->item(i, 8)->text()) == true)
{
mobj_ProcessLogMap.mobj_ProcessAndLogMapping.remove(ui->twShowProcess->item(i, 8)->text());
mobj_ProcessLogMap.mobj_ProcessAndLogMapping.insert(ui->twShowProcess->item(i, 8)->text(), QString(""));
}
else
this->mobj_ProcessLogMap.mobj_ProcessAndLogMapping.insert(ui->twShowProcess->item(i, 8)->text(), QString(""));
}
if(ui->twShowProcess->item(i, 0)->text() == "LThistdb.exe")
{
if(IsServiceRunning(QString("LThistdb.exe")) == false)
this->on_actionStopPostgreSQL_DB_Server_triggered();
}
qszStandardOutput.clear();
}
}
}
else
break;
#ifdef Q_WS_WIN
cmd.clear();
qszFilters.clear();
qszSubFilters.clear();
#endif
}
}
catch(QProcess::ProcessError pError)
{
QMessageBox objCrashExit;
objCrashExit.information(this, "Crashed", "Process error returned code: " + QString::number(pError));
}
catch(...)
{
QMessageBox objCrashExit;
objCrashExit.information(this, "Unknown Crash", "Unknown crash exit-child process may not be running correctly!");
}
}
QTimer runs in the UI thread so it blocks your UI if it takes a long time to execute. A simple solution is to just run your "processing" stuff in another background thread, the easiest way to do that in Qt might be using QtConcurrent::run like this from your timeout slot called from the QTimer:
QtConcurrent::run(yourProcessingFunction);
You can obviously create your own Thread and use the build in QTimer from QObject::startTimer(...), but that is more work usually.
The problem is likely due to the amount of work being done by RestartStoppedProcess.
As the documentation for QTimer states, when discussing the called slot:
It should be written in such a way that it always returns quickly (typically after processing one data item) so that Qt can deliver events to the user interface and stop the timer as soon as it has done all its work.
As you've witnessed with your application, a heavy workload with a QTimer on the main thread can cause lag in the Gui. The Qt documentation goes on to state:
This is the traditional way of implementing heavy work in GUI applications, but as multithreading is nowadays becoming available on more and more platforms, we expect that zero-millisecond QTimer objects will gradually be replaced by QThreads.
With this in mind, I suggest refactoring your code so that RestartStoppedProcess functions in a separate thread. There's a great tutorial on "How to Really Truly Use QThread" here.

gstreamer-1.0 stopping and starting recording pipeline via GUI

I'm trying to write simple video recorder, based on gstreamer framework for my own customboard with ARM processor and Wayland+Qt as window subsystem.
I've created class RecordBin with rec_start slot and rec_stop public method:
void RecordBin::rec_start ()
{
/* Set pipeline to the PLAYING state */
gst_element_set_state (record_pipeline, GST_STATE_PLAYING);
g_print ("setting playing state\n");
/* Start main loop context */
g_main_loop_run (rec_loop);
}
void RecordBin::rec_stop ()
{
/* Set pipeline to the NULL state */
change_ret = gst_element_set_state (record_pipeline, GST_STATE_NULL);
/* Quit from main loop context */
g_main_loop_quit (rec_loop);
}
This is my slot in mainwindow for play/stop button clicking:
void MainWindow::on_recordButton_clicked ()
{
if (!is_recording) {
if (window_is_opened == false) {
cout << "start recording" << endl;
/* Start recording */
window_is_opened = true;
emit start_recording ();
} else {
cout << "playing window already opened" << endl;
}
} else {
cout << "recording reset" << endl;
/* Stop recording */
record_bin->rec_stop ();
window_is_opened = false;
}
}
RecordBin class is working in a separate thread (it's realized via QThread), so that glib mainloop context don't blocking Qt main window.
I can't use rec_stop method as slot, because rec_loop blocks the message handling, and when recording starts, it can't be stopped via signal.
But direct call rec_stop is thread unsafe.
Can anybody help me with two questions:
1. How I should change pipeline state from another thread?
2. Is it correct to stop recording via changing pipeline state to NULL? Probably I should to send EOS signal on the bus and handling it?
gst_element_set_state() is marked as MT safe, so it can be stopped from any thread. I had a problem with setting gst_element_set_state() to NULL: filesink at the end of pipeline wasn't completing the output files correctly (had to use EOS and catch another event that was confirming that the filesink has got that EOS). But NULL works fine for players.
Overall, I'd get rid of the glib mainloop. You can use gst_bus_set_sync_handler() to set a callback. In the callback, emit a Qt signal to RecordBin. The RecordBin will be a QObject that lives in the main Qt thread. Process the arriving GstMessage* in its slot.

QTcpSocket connecting results in UnknownSocketError with errorString "UnknownError"

Problem
I am unable to get any further information regarding this error:
QAbstractSocket::UnknownSocketError
The QT QAbstractSocket::SocketError provides only a basic explanation that some error has occurred
An unidentified error occurred.
enum value = -1
Calling QTcpSocket::errorString() provides this:
"Unknown error"
There is one question regarding this here on SO but provides no real solution to solving the issue (and what was suggested I have done)
I have absoltely no idea how to further progress with this error, since each time my client attempts to connect (after calling connectToHost()) I get this error.
Code:
//Server
//...
if (tcpServer.listen(QHostAddress().AnyIPv4, 5000)) {
qDebug() << "tcpserver started on port : 5000";
}
else{
qDebug() << "tcpserver failed to start";
}
//...
I also went on to explicitly set the server ip to localhost and port 5000, but without success.
//Client
//...
tcp_con = new QTcpSocket(new QObject());
tcp_con->connectToHost("127.0.0.1", 5000);
switch (tcp_con->error()) {
//...
case QAbstractSocket::UnknownSocketError:
qDebug() << "tcp error UnknownSocketError closed : " << tcp_con->errorString();
return;
//...
}
Client debug output:
tcp error UnknownSocketError closed : "Unknown error"
Any advice?
p.s. I looked for some stacktrace/backtrace option, didn't find anything - if there is, please leave a comment
It is wrong to check an error immediately after the connectToHost(), because this is not a complete action, and the errorString() will always return "Unknown error". You have to call the QAbstractSocket::waitForConnected() method like this:
tcp_con->connectToHost("127.0.0.1", 5000);
if (tcp_con->waitForConnected(1000))
qDebug("Connected!");
Or you can don't call the waitForConnected() and asynchronously wait while the signal connected() will be emitted:
connect(tcp_con, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(onError(QAbstractSocket::SocketError)));
connect(tcp_con, SIGNAL(connected()),
this, SLOT(onConnect()));
//...
void MyClass::onConnect()
{
qDebug() << "Connected!";
}
void MyClass::onError(QAbstractSocket::SocketError)
{
QTcpSocket* sock = (QTcpSocket*)sender();
qDebug() << "Socket error:" << sock->errorString();
}

Qt5 WebSockets test app not connecting to test service

I wanted to open a qt websocket to the test service in ws://echo.websocket.org but I got the error QAbstractSocket::RemoteHostClosedError
I am connecting the signal error(QAbstractSocket::SocketError socketError) to a slot in my code in order to read the error number then look for it in here
My code looks like this
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Controller w;
w.initializeWebSocket("ws://echo.websocket.org", true);
w.show();
return a.exec();
}
Controller::Controller(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
}
void Controller::initializeWebSocket(QString url, bool debug)
{
m_webSocketURL = url;
m_webSocketDebug = debug;
if(m_webSocketDebug)
std::cout << "WebSocket server: " << m_webSocketURL.toStdString() << std::endl;
QObject::connect(&m_webSocket, SIGNAL(connected()), this, SLOT(onConnected()));
QObject::connect(&m_webSocket, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
QObject::connect(&m_webSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));
QObject::connect(&m_webSocket, SIGNAL(textMessageReceived(QString)), this, SLOT(onTextMessageReceived(QString)));
m_webSocket.open(QUrl(m_webSocketURL));
}
void Controller::onConnected()
{
if (m_webSocketDebug)
std::cout << "WebSocket connected" << std::endl;
m_webSocket.sendTextMessage(QStringLiteral("Rock it with HTML5 WebSocket"));
}
void Controller::onDisconnected()
{
if (m_webSocketDebug)
std::cout << "WebSocket disconnected" << std::endl;
}
void Controller::onError(QAbstractSocket::SocketError error)
{
std::cout << error << std::endl;
}
void Controller::onTextMessageReceived(QString message)
{
if (m_webSocketDebug)
std::cout << "Message received:" << message.toStdString() << std::endl;
m_webSocket.close();
}
Im new to websockets so I have no idea where could the problem be. Can anyone give advise?
Opening websocket at "ws://echo.websocket.org" works for me just fine.
These handlers are sufficient in my project:
connect(&webSocket, SIGNAL(connected()), this, SLOT(onConnected()));
connect(&webSocket, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
connect(&webSocket, SIGNAL(textMessageReceived(const QString&)), this, SLOT(onTextMessageReceived(const QString&)));
I also just realized that I don't connect error() signal yet the program code is quite reliable for more than a year already and in case of disconnect there is a connection restore kick in. Maybe I should connect error() signal as well for infrequent strange cases.
The error QAbstractSocket::RemoteHostClosedError can be just a correct thing to get. Try to get the echo within reasonable time. The websocket farm we use in our project is holding the connection for up to 50 minutes so we do ping-pong between the client and the server to keep the connection live before this period expires.
// you can try that immediately after opening the web socket and also using some QTimer
m_webSocket.sendTextMessage("Pong!");
Try that and see the text reply as long as you are playing some public echo service.
Well, I verified your code and it seems to work fine. The error you give indicates a host related issue. It may be due to firewall, isp or other blocks/issues.
WebSocket server: ws://echo.websocket.org
WebSocket connected
Message received:Rock it with HTML5 WebSocket
WebSocket disconnected
I do like to point out that it's preferred to keep a pointer to a QWebSocket 'object'. It's very convenient to declare m_webSocket as QWebSocket *, and add m_webSocket = new QWebSocket(this). It's good practice to treat objects as objects. You don't want to accidentally try to 'copy' an QWebSocket directly. Also, due to the internals of Qt, you may eventually run into problems if this "Controller" object is destroyed while the QWebSocket is still attached to other objects (although I think Qt is prepared for it).

Qt QAudioOutput StateChnged always on ActiveState (Qt 5.1 Windows MinGW)

I have a derived class from QObject that has a bunch of concatenated WAVE files in a QByteArray as a member variable.
I want to play specific files in that array (provided that I have the offset of it) through a QAudioOuput.
Here is the code of the PlaySound Method:
void DRMUtils::PlaySound(int offset){
mAudioFormat = new QAudioFormat(GetFormat(offset));
mAudioOut = new QAudioOutput(*mAudioFormat);
mBufferedAudio = new QBuffer();
mBufferedAudio->setData(GetSound(offset));
mBufferedAudio->open(QIODevice::ReadOnly);
connect(mAudioOut, SIGNAL(stateChanged(QAudio::State)), this, SLOT(handleAudioStateChanged(QAudio::State)));
mAudioOut->start(mBufferedAudio);
}
I get the file format from the 44 first bytes (WAVE standard) with GetFormat(offset) and I get the data in QByteArray format with GetSound(offset)
Everything seems to work fine (I can hear the sample play), but the state of QAudioFormat never changes from "ActiveState"
Here is my slot code:
void DRMUtils::handleAudioStateChanged(QAudio::State newState)
{
qDebug() << "State: " << newState;
switch (newState) {
case QAudio::IdleState:
// Finished playing
mAudioOut->stop();
mBufferedAudio->close();
delete mAudioOut;
delete mBufferedAudio;
delete mAudioFormat;
qDebug() << "DELETED!";
break;
case QAudio::StoppedState:
// Stopped for other
qDebug() << "STOPPED!";
if (mAudioOut->error() != QAudio::NoError) {
// Error handling
qDebug() << "STOPPED ERROR!";
}
break;
default:
// ... other cases as appropriate
qDebug() << "DEFAULT!";
break;
}
}
My Debug output is always:
State: ActiveState
DEFAULT!
Do I have to "cap" the mBufferedAudio in some way that QAudioOutput "knows" when the sample is completed?
Also, I anybody can tell me when why when I initialize mAudioOut like this (declaring the parent):
mAudioOut = new QAudioOutput(*mAudioFormat, this);
instead of (not declaring the parent):
mAudioOut = new QAudioOutput(*mAudioFormat);
I don't get any output to the speakers (with parent declared).
Thanks
May be this gets deleted? So mAudioOut is deleted too when the parent is specified. It would also explain why you don't receive state changes (if the object gets deleted, the slot cannot be called anymore).

Resources