[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_OBJECT

    public:
    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@



  • Your on_write_loop is still in your mainWindow object and will be executed in the default thread.
    Also, it is recommended not to subclass QThread, but to create a class for handling your logic and then calling moveToThread on that.



  • 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.



  • If you run it in a debugger, you'll see the line of code where it bailed out.



  • got it working. Thanks for all the help.


  • Moderators

    Be sure and mark the topic [Solved]! Thanks!



  • I am sure. Thanks



  • 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);

    }@


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.