[SOLVED] using threads to eliminate a never ending loop
-
Hi guys,
I have a program in Qt Creator which outputs a sine wave with the click of a pushButton. However, due to a never ending while loop in my pushButton function, the application freezes when I click the pushButton. So I am using threads for my function and ending the while loop by eliminating the thread with the click of another pushButton(pushButton2).
I build my code with no errors. however, when I run it, the pushButton does not generate a sine wave and I get the following message:
@QMetaObject::connectSlotsByName: No matching signal for on_write_loop(snd_pcm_t*,signed short*,snd_pcm_channel_area_t*)@Any help would be greatly appreciated.
My code snippets are below:
wave.cpp:
@void wave::on_write_loop(snd_pcm_t *handles, signed short *samples , snd_pcm_channel_area_t *areas)
{
double freq = ui->frequency->text().toDouble();
double ampl = ui->amplitude->text().toDouble();
double phase = 0;
signed short ptr;
int err, cptr;
while (1) {
generate_sine(0, period_size, &phase, freq, ampl);
ptr = samples;
cptr = period_size;
while (cptr > 0) {
err = snd_pcm_writei(hspdif, ptr, cptr);
if (err == -EAGAIN)
continue;
if (err < 0) {
if (xrun_recovery(hspdif, err) < 0) {
printf("Write error: %s ", snd_strerror(err));
exit(EXIT_FAILURE);
}
break; / skip one period */
}
ptr += err * channels;
cptr -= err;
}
}}
wave::wave(QWidget parent) :
QMainWindow(parent),
ui(new Ui::wave)
{
ui->setupUi(this);
//setup();
mThread = new MyThread(this);
connect(mThread, SIGNAL(write_loop(snd_pcm_t, signed short*, snd_pcm_channel_area_t*)), this, SLOT(on_write_loop(snd_pcm_t*, signed short*, snd_pcm_channel_area_t*)));
}wave::~wave()
{
delete ui;}
void wave::on_pushButton_clicked()
{//Generate
mThread->start();}
void wave::on_pushButton_2_clicked()
{
//Terminate
mThread->Stop = true;}@
wave.h:
@#ifndef WAVE_H
#define WAVE_H
#include "ui_wave.h"
#include <alsa/asoundlib.h>
#include <QMainWindow>
#include <QObject>
#include "mythread.h"namespace Ui {
class wave;
}class wave : public QMainWindow
{
Q_OBJECTpublic:
explicit wave(QWidget *parent = 0);
~wave();
MyThread *mThread;private slots:
void on_pushButton_clicked();void on_pushButton_2_clicked(); void setup();
private:
Ui::wave *ui;public slots:
void on_write_loop(snd_pcm_t*, signed short*, snd_pcm_channel_area_t*);
;#endif // WAVE_H@
MyThread.cpp:
@void MyThread::run()
{
QMutex mutex;
mutex.lock();
if (this->Stop)
mutex.unlock();const char *device = "plughw:0,0"; snd_pcm_hw_params_alloca(&hwparams); snd_pcm_sw_params_alloca(&swparams); int err = snd_output_stdio_attach(&output, stdout, 0); printf( "snd_output_stdio_attach err=%d\n", err); err = snd_pcm_open(&hspdif, device, SND_PCM_STREAM_PLAYBACK, 0); printf( "snd_pcm_open err=%d\n", err); err = set_hwparams(hspdif, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); printf( "set_hwparams err=%d\n", err); err = set_swparams(hspdif, swparams); printf( "set_swparams err=%d\n", err); samples = new signed short [period_size * channels * snd_pcm_format_physical_width(format)]; printf( "samples array_size=%d\n", int( period_size * channels * snd_pcm_format_physical_width(format)) ); areas = new snd_pcm_channel_area_t [channels]; printf( "areas channels=%d\n", channels); for (unsigned int chn = 0; chn < channels; chn++) { areas[chn].addr = samples; areas[chn].first = chn * snd_pcm_format_physical_width(format); areas[chn].step = channels * snd_pcm_format_physical_width(format); } emit write_loop(hspdif, samples, areas);
}@
MyThread.h:
@#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <alsa/asoundlib.h>
#include <QThread>class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = 0);
void run();
bool Stop;signals:
void write_loop(snd_pcm_t*, signed short*, snd_pcm_channel_area_t*);public slots:
};#endif // MYTHREAD_H@
-
Unless you plan not to use the connectSlotsByName feature, don't name your slots on_Foo_Bar (which will look for a children named Foo and connect that slot to Foo's Bar signal. It's very likely that you don't have a children named "write" with a signal named "loop"). And setupUi() WILL call connectSlotsByName.
http://doc.qt.nokia.com/4.7/qmetaobject.html#connectSlotsByName
-
[quote author="peppe" date="1313161135"]Unless you plan not to use the connectSlotsByName feature, don't name your slots on_Foo_Bar (which will look for a children named Foo and connect that slot to Foo's Bar signal. It's very likely that you don't have a children named "write" with a signal named "loop"). And setupUi() WILL call connectSlotsByName.
http://doc.qt.nokia.com/4.7/qmetaobject.html#connectSlotsByName[/quote]
Ahh, yes, I see what you mean. I have corrected that. Thank you. However, I have a new problem now. My application terminates the moment I click the pushButton.. I get the message:
The program has unexpectedly finished. -
Here is the solution:
mythread.h:
@#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>class MyThread : public QThread
{
Q_OBJECT
protected:
void run();
public:
explicit MyThread(QObject *parent = 0);
};
#endif // MYTHREAD_H
@mythread.cpp:
@#include "wave.h"
#include "mythread.h"MyThread::MyThread(QObject *parent) :
QThread(parent)
{
}
void MyThread::run()
{
onWriteLoop();
}@
wave.cpp:
@wave::wave(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::wave)
{
ui->setupUi(this);
setup();thread = new MyThread();
}
wave::~wave()
{
delete ui;
delete thread;
}void wave::on_pushButton_clicked()
{
//Generate
freq = ui->frequency->text().toDouble();
ampl = ui->amplitude->text().toDouble();
thread->start();
ui->pushButton->setEnabled(false);
ui->pushButton->setStyleSheet("background-color: gray");
ui->pushButton_2->setStyleSheet("background-color: rgb(255, 192, 192);"
"color: red;");
ui->pushButton_2->setEnabled(true);
}void wave::on_pushButton_2_clicked()
{
//Terminate
thread->terminate();
ui->pushButton_2->setEnabled(false);
ui->pushButton_2->setStyleSheet("background-color: gray");
ui->pushButton->setStyleSheet("background-color: rgb(192, 255, 208);"
"color: green;");
ui->pushButton->setEnabled(true);}@