Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt Creator and other tools
  4. [SOLVED] using threads to eliminate a never ending loop
Forum Updated to NodeBB v4.3 + New Features

[SOLVED] using threads to eliminate a never ending loop

Scheduled Pinned Locked Moved Qt Creator and other tools
9 Posts 5 Posters 5.0k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • O Offline
    O Offline
    ogopa
    wrote on last edited by
    #1

    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@

    1 Reply Last reply
    0
    • L Offline
      L Offline
      loladiro
      wrote on last edited by
      #2

      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.

      1 Reply Last reply
      0
      • D Offline
        D Offline
        dangelog
        wrote on last edited by
        #3

        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

        Software Engineer
        KDAB (UK) Ltd., a KDAB Group company

        1 Reply Last reply
        0
        • O Offline
          O Offline
          ogopa
          wrote on last edited by
          #4

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

          1 Reply Last reply
          0
          • G Offline
            G Offline
            goetz
            wrote on last edited by
            #5

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

            http://www.catb.org/~esr/faqs/smart-questions.html

            1 Reply Last reply
            0
            • O Offline
              O Offline
              ogopa
              wrote on last edited by
              #6

              got it working. Thanks for all the help.

              1 Reply Last reply
              0
              • M Offline
                M Offline
                mlong
                wrote on last edited by
                #7

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

                Software Engineer
                My views and opinions do not necessarily reflect those of anyone -- living or dead, real or fictional -- in this universe or any other similar multiverse node. Void where prohibited. Your mileage may vary. Caveat emptor.

                1 Reply Last reply
                0
                • O Offline
                  O Offline
                  ogopa
                  wrote on last edited by
                  #8

                  I am sure. Thanks

                  1 Reply Last reply
                  0
                  • O Offline
                    O Offline
                    ogopa
                    wrote on last edited by
                    #9

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

                    }@

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved