Results 1 to 11 of 11

Thread: using threads to eliminate a never ending loop

  1. #1
    Join Date
    Aug 2011
    Posts
    35
    Thanks
    5

    Default 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:
    Qt Code:
    1. void wave::on_write_loop(snd_pcm_t *handles, signed short *samples , snd_pcm_channel_area_t *areas)
    2. {
    3. double freq = ui->frequency->text().toDouble();
    4. double ampl = ui->amplitude->text().toDouble();
    5. double phase = 0;
    6. signed short *ptr;
    7. int err, cptr;
    8. while (1) {
    9. generate_sine(0, period_size, &phase, freq, ampl);
    10. ptr = samples;
    11. cptr = period_size;
    12. while (cptr > 0) {
    13. err = snd_pcm_writei(hspdif, ptr, cptr);
    14. if (err == -EAGAIN)
    15. continue;
    16. if (err < 0) {
    17. if (xrun_recovery(hspdif, err) < 0) {
    18. printf("Write error: %s ", snd_strerror(err));
    19. exit(EXIT_FAILURE);
    20. }
    21. break; /* skip one period */
    22. }
    23. ptr += err * channels;
    24. cptr -= err;
    25. }
    26. }
    27.  
    28. }
    29.  
    30.  
    31. wave::wave(QWidget *parent) :
    32. QMainWindow(parent),
    33. ui(new Ui::wave)
    34. {
    35. ui->setupUi(this);
    36. //setup();
    37. mThread = new MyThread(this);
    38. 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*)));
    39. }
    40.  
    41. wave::~wave()
    42. {
    43. delete ui;
    44.  
    45. }
    46.  
    47.  
    48. void wave::on_pushButton_clicked()
    49. {
    50.  
    51. //Generate
    52. mThread->start();
    53.  
    54. }
    55.  
    56.  
    57. void wave::on_pushButton_2_clicked()
    58. {
    59. //Terminate
    60. mThread->Stop = true;
    61.  
    62. }
    To copy to clipboard, switch view to plain text mode 

    wave.h:
    Qt Code:
    1. #ifndef WAVE_H
    2. #define WAVE_H
    3. #include "ui_wave.h"
    4. #include <alsa/asoundlib.h>
    5. #include <QMainWindow>
    6. #include <QObject>
    7. #include "mythread.h"
    8.  
    9. namespace Ui {
    10. class wave;
    11. }
    12.  
    13. class wave : public QMainWindow
    14. {
    15. Q_OBJECT
    16.  
    17. public:
    18. explicit wave(QWidget *parent = 0);
    19. ~wave();
    20. MyThread *mThread;
    21.  
    22. private slots:
    23. void on_pushButton_clicked();
    24.  
    25. void on_pushButton_2_clicked();
    26.  
    27. void setup();
    28.  
    29. private:
    30. Ui::wave *ui;
    31.  
    32. public slots:
    33. void on_write_loop(snd_pcm_t*, signed short*, snd_pcm_channel_area_t*);
    34. ;
    35.  
    36. #endif // WAVE_H
    To copy to clipboard, switch view to plain text mode 

    MyThread.cpp:
    Qt Code:
    1. void MyThread::run()
    2. {
    3. QMutex mutex;
    4. mutex.lock();
    5. if (this->Stop)
    6. mutex.unlock();
    7.  
    8. const char *device = "plughw:0,0";
    9.  
    10. snd_pcm_hw_params_alloca(&hwparams);
    11. snd_pcm_sw_params_alloca(&swparams);
    12.  
    13. int err = snd_output_stdio_attach(&output, stdout, 0);
    14. printf( "snd_output_stdio_attach err=%d\n", err);
    15. err = snd_pcm_open(&hspdif, device, SND_PCM_STREAM_PLAYBACK, 0);
    16. printf( "snd_pcm_open err=%d\n", err);
    17. err = set_hwparams(hspdif, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
    18. printf( "set_hwparams err=%d\n", err);
    19. err = set_swparams(hspdif, swparams);
    20. printf( "set_swparams err=%d\n", err);
    21.  
    22. samples = new signed short [period_size * channels * snd_pcm_format_physical_width(format)];
    23. printf( "samples array_size=%d\n", int( period_size * channels * snd_pcm_format_physical_width(format)) );
    24.  
    25. areas = new snd_pcm_channel_area_t [channels];
    26. printf( "areas channels=%d\n", channels);
    27. for (unsigned int chn = 0; chn < channels; chn++) {
    28. areas[chn].addr = samples;
    29. areas[chn].first = chn * snd_pcm_format_physical_width(format);
    30. areas[chn].step = channels * snd_pcm_format_physical_width(format);
    31. }
    32. emit write_loop(hspdif, samples, areas);
    33. }
    To copy to clipboard, switch view to plain text mode 

    MyThread.h:
    Qt Code:
    1. #ifndef MYTHREAD_H
    2. #define MYTHREAD_H
    3. #include <alsa/asoundlib.h>
    4. #include <QThread>
    5.  
    6. class MyThread : public QThread
    7. {
    8. Q_OBJECT
    9. public:
    10. explicit MyThread(QObject *parent = 0);
    11. void run();
    12. bool Stop;
    13.  
    14. signals:
    15. void write_loop(snd_pcm_t*, signed short*, snd_pcm_channel_area_t*);
    16.  
    17. public slots:
    18. };
    19.  
    20. #endif // MYTHREAD_H
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Dec 2008
    Location
    France
    Posts
    93
    Thanked 23 Times in 22 Posts
    Qt products
    Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android

    Default Re: using threads to eliminate a never ending loop

    Your source is a bit complicated...

    You use QThread in a stange way.

    Try this :

    1. Put the QThread::run() content in your wave constructor.
    2. Remove your class MyThread and any reference to QThread
    3. In your UI class add :
      Qt Code:
      1. signals:
      2. void startWave(snd_pcm_t*, signed short*, snd_pcm_channel_area_t*);
      3. private:
      4. QThread *thread;
      To copy to clipboard, switch view to plain text mode 
      .
      Add the following code your constructor :
      Qt Code:
      1. thread=new QThread();
      2. thread.start();
      3. Wave *wave = new Wave();
      4. wave->moveToThread(thread);
      5. connect(this, SIGNAL(startWave(snd_pcm_t*, signed short*, snd_pcm_channel_area_t*)), wave, SLOT(on_write_loop(snd_pcm_t*, signed short*, snd_pcm_channel_area_t*)));
      To copy to clipboard, switch view to plain text mode 

      And emit your signal when you want to start playing.


    That should work without subclassing QThread.

    Code not tested i have to leave fast.

    Good luck

  3. The following user says thank you to nix for this useful post:

    duma (12th August 2011)

  4. #3
    Join Date
    Aug 2011
    Posts
    35
    Thanks
    5

    Default Re: using threads to eliminate a never ending loop

    Quote Originally Posted by nix View Post
    Your source is a bit complicated...

    You use QThread in a stange way.

    Try this :

    1. Put the QThread::run() content in your wave constructor.
    2. Remove your class MyThread and any reference to QThread
    3. In your UI class add :
      Qt Code:
      1. signals:
      2. void startWave(snd_pcm_t*, signed short*, snd_pcm_channel_area_t*);
      3. private:
      4. QThread *thread;
      To copy to clipboard, switch view to plain text mode 
      .
      Add the following code your constructor :
      Qt Code:
      1. thread=new QThread();
      2. thread.start();
      3. Wave *wave = new Wave();
      4. wave->moveToThread(thread);
      5. connect(this, SIGNAL(startWave(snd_pcm_t*, signed short*, snd_pcm_channel_area_t*)), wave, SLOT(on_write_loop(snd_pcm_t*, signed short*, snd_pcm_channel_area_t*)));
      To copy to clipboard, switch view to plain text mode 

      And emit your signal when you want to start playing.


    That should work without subclassing QThread.

    Code not tested i have to leave fast.

    Good luck
    Hey thanks alot. I did as you said and I'm running into the error:
    error: request for member ‘start’ in ‘((wave*)this)->wave::thread’, which is of non-class type ‘QThread*’

  5. #4
    Join Date
    Dec 2008
    Location
    France
    Posts
    93
    Thanked 23 Times in 22 Posts
    Qt products
    Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android

    Default Re: using threads to eliminate a never ending loop

    I made a mistake in the code I give you try
    Qt Code:
    1. thread->start()
    To copy to clipboard, switch view to plain text mode 
    of course.

  6. #5
    Join Date
    Aug 2011
    Posts
    35
    Thanks
    5

    Default Re: using threads to eliminate a never ending loop

    Quote Originally Posted by nix View Post
    I made a mistake in the code I give you try
    Qt Code:
    1. thread->start()
    To copy to clipboard, switch view to plain text mode 
    of course.
    I am now getting this error:
    Qt Code:
    1. QMetaObject::connectSlotsByName: No matching signal for on_write_loop(snd_pcm_t*,signed short*,snd_pcm_channel_area_t*)
    2. Wave: pcm_params.c:2286: snd_pcm_hw_refine: Assertion `pcm && params' failed.
    3. The program has unexpectedly finished.
    To copy to clipboard, switch view to plain text mode 

    also, I think you mean:
    Qt Code:
    1. thread = new QThread();
    2. thread->start();
    3. wave *Wave = new wave();
    4. Wave->moveToThread(thread);
    5. connect(this, SIGNAL(startWave(snd_pcm_t*, signed short*, snd_pcm_channel_area_t*)), Wave, SLOT(on_write_loop(snd_pcm_t*, signed short*, snd_pcm_channel_area_t*)));
    To copy to clipboard, switch view to plain text mode 


    Added after 5 minutes:


    Quote Originally Posted by duma View Post
    I am now getting this error:
    Qt Code:
    1. QMetaObject::connectSlotsByName: No matching signal for on_write_loop(snd_pcm_t*,signed short*,snd_pcm_channel_area_t*)
    2. Wave: pcm_params.c:2286: snd_pcm_hw_refine: Assertion `pcm && params' failed.
    3. The program has unexpectedly finished.
    To copy to clipboard, switch view to plain text mode 

    also, I think you mean:
    Qt Code:
    1. thread = new QThread();
    2. thread->start();
    3. wave *Wave = new wave();
    4. Wave->moveToThread(thread);
    5. connect(this, SIGNAL(startWave(snd_pcm_t*, signed short*, snd_pcm_channel_area_t*)), Wave, SLOT(on_write_loop(snd_pcm_t*, signed short*, snd_pcm_channel_area_t*)));
    To copy to clipboard, switch view to plain text mode 

    Got rid of the first error:QMetaObject::connectSlotsByName: No matching signal for on_write_loop(snd_pcm_t*,signed short*,snd_pcm_channel_area_t*)
    I changed on_write_loop to onWriteLoop. Because a function with format on_Foo_Bar look for a children named Foo and connect that slot to Foo’s Bar signal.

    Now working on the second error. Any help would be appreciated. Thanks
    Last edited by duma; 12th August 2011 at 19:43.

  7. #6
    Join Date
    Dec 2008
    Location
    France
    Posts
    93
    Thanked 23 Times in 22 Posts
    Qt products
    Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android

    Default Re: using threads to eliminate a never ending loop

    My mistake.

    The initialization of your pcm is on GUI thread and the use in the new thread that's bad, it should be the same. So you have to put the init in the Wave object and do it after the moveToThread.
    So create a new slot used as on_write_loop or put the init in on_write_loop.

  8. #7
    Join Date
    Aug 2011
    Posts
    35
    Thanks
    5

    Default Re: using threads to eliminate a never ending loop

    Quote Originally Posted by nix View Post
    My mistake.

    The initialization of your pcm is on GUI thread and the use in the new thread that's bad, it should be the same. So you have to put the init in the Wave object and do it after the moveToThread.
    So create a new slot used as on_write_loop or put the init in on_write_loop.
    I am getting the following errors:
    ../Wave/wave.cpp:310:9: error: expected unqualified-id before ‘->’ token
    ../Wave/wave.cpp:311:5: error: ‘Wave’ was not declared in this scope
    ../Wave/wave.cpp:311:16: error: expected primary-expression before ‘=’ token
    ../Wave/wave.cpp:311:22: error: expected type-specifier before ‘Wave’
    ../Wave/wave.cpp:311:22: error: expected ‘;’ before ‘Wave’

    Also, I don't believe we can create a “wave” object inside of a “wave” and, and then move that second object into a thread. Excuse me if I am wrong.

  9. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: using threads to eliminate a never ending loop

    Get rid of the thread completely, read the [wiki]Keeping the GUI Responsive[/wiki] article and employ the "step by step" pattern to your problem. Also consider making your code more "C++-ish" and less "C-ish".
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  10. #9
    Join Date
    Aug 2011
    Posts
    35
    Thanks
    5

    Default Re: using threads to eliminate a never ending loop

    Quote Originally Posted by wysota View Post
    Get rid of the thread completely, read the [wiki]Keeping the GUI Responsive[/wiki] article and employ the "step by step" pattern to your problem. Also consider making your code more "C++-ish" and less "C-ish".
    Thanks for the reply. this seems like exactly what i need. Although, if I apply the step by step method, a time limit will be placed on my event loop. But i want my loop to remain infinite so that it doesn't stop running and only stops when I click the STOP pushButton.

  11. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: using threads to eliminate a never ending loop

    Read the article again, I think you didn't understand every part of it. If something is unclear, ask. In short, there is no time limit on your whole operation, only on a single iteration of it.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  12. The following user says thank you to wysota for this useful post:

    duma (15th August 2011)

  13. #11
    Join Date
    Aug 2011
    Posts
    35
    Thanks
    5

    Default Re: using threads to eliminate a never ending loop

    Quote Originally Posted by wysota View Post
    Read the article again, I think you didn't understand every part of it. If something is unclear, ask. In short, there is no time limit on your whole operation, only on a single iteration of it.
    Got it working. thanks alot

Similar Threads

  1. Resizing QTableView to eliminate horizontal scroll bar?
    By russford in forum Qt Programming
    Replies: 7
    Last Post: 18th March 2010, 07:21
  2. Replies: 10
    Last Post: 15th January 2010, 14:35
  3. Emulator Starting and ending
    By mcwar in forum Qt for Embedded and Mobile
    Replies: 1
    Last Post: 13th January 2010, 13:22
  4. signal ending nowhere...
    By miwarre in forum Newbie
    Replies: 2
    Last Post: 2nd September 2009, 16:38
  5. signal and slot across threads having event loop
    By travis in forum Qt Programming
    Replies: 6
    Last Post: 5th November 2007, 23:56

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.