Results 1 to 20 of 21

Thread: emit a signal from inside a callback routine

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Nov 2007
    Location
    Italy
    Posts
    694
    Thanks
    59
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default emit a signal from inside a callback routine

    Hi to all,
    I' writing an audio editor using fmod and Qt.
    Hi have a fmod callback that's called by the fmod engine when a sound is stopped to play and from it I would emit a signal.
    Here the callback that's part of a class:

    Qt Code:
    1. class AudioDevice : public QObject
    2. {
    3. Q_OBJECT
    4.  
    5. public:
    6. static FMOD_RESULT F_CALLBACK endCallback(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type,
    7. unsigned int commanddata1, unsigned int commanddata2)
    8. {
    9. (void)commanddata1; // Unused (to avoid warnings)
    10. (void)commanddata2; // Unused (to avoid warnings)
    11.  
    12. SoundData* currentSound;
    13.  
    14. switch(type)
    15. {
    16. case FMOD_CHANNEL_CALLBACKTYPE_END:
    17. {
    18. FMOD_RESULT result;
    19. FMOD::Channel *currentChannel = (FMOD::Channel *)channel;
    20.  
    21. void *ud = NULL;
    22. result = currentChannel->getUserData( &ud );
    23.  
    24. currentSound = (SoundData*)ud;
    25.  
    26. /* inform that sound stopped */
    27. emit( soundStopped() );// <------- THIS ONE
    28. break;
    29. }
    30. default:
    31. break;
    32. }
    33.  
    34. return FMOD_OK;
    35. }
    36. public slots:
    37. // Initialize the audio system
    38. bool init();
    39.  
    40. signals:
    41. void soundStopped();
    42. ..more code...
    To copy to clipboard, switch view to plain text mode 


    The compiler don't like the emit call.
    It says
    error C2352: 'AudioDevice::soundStopped' : illegal call of non-static member function
    How can I do?

    Best
    Franco Amato

  2. #2
    Join Date
    Feb 2007
    Location
    Karlsruhe, Germany
    Posts
    469
    Thanks
    17
    Thanked 90 Times in 88 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: emit a signal from inside a callback routine

    Hi!

    The compiler is correct. You are calling a non static member from inside a static function. That's a no go. What would be the this object of that call?

    Your callback probably cannot be non-static, so you will have to reference your audiodevice in another way.

    Usually you would use the "user-data" of the callback for that. When you set the callback up, you can pass a pointer to your Audiodevice as commanddata1.

    Qt Code:
    1. class AudioDevice : public QObject
    2. { Q_OBJECT
    3. friend FMOD_RESULT F_CALLBACK endCallback(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type,
    4. unsigned int commanddata1, unsigned int commanddata2);
    5. signals:
    6. void soundStopped();
    7. protected:
    8. void DoEndCallBack() {emit soundStopped();}
    9. }
    10.  
    11. ..
    12.  
    13. FMOD_RESULT F_CALLBACK endCallback(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type,
    14. unsigned int commanddata1, unsigned int commanddata2)
    15. {
    16. AudioDevice* ad = dynamic_cast<AudioDevice*>(commanddata1);
    17. if (ad)
    18. ad->DoEndCallBack();
    19. ..
    20. }
    To copy to clipboard, switch view to plain text mode 

    Using the friends approach you can even declare the DoEndCallBack protected..

    HIH

    Johannes
    Last edited by JohannesMunk; 8th December 2009 at 02:57.

  3. #3
    Join Date
    Nov 2007
    Location
    Italy
    Posts
    694
    Thanks
    59
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: emit a signal from inside a callback routine

    Quote Originally Posted by JohannesMunk View Post
    Hi!

    The compiler is correct. You are calling a non static member from inside a static function. That's a no go. What would be the this object of that call?

    Your callback probably cannot be non-static, so you will have to reference your audiodevice in another way.

    Usually you would use the "user-data" of the callback for that. When you set the callback up, you can pass a pointer to your Audiodevice as commanddata1.

    Qt Code:
    1. class AudioDevice : public QObject
    2. { Q_OBJECT
    3. friend FMOD_RESULT F_CALLBACK endCallback(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type,
    4. unsigned int commanddata1, unsigned int commanddata2);
    5. signals:
    6. void soundStopped();
    7. protected:
    8. void DoEndCallBack() {emit soundStopped();}
    9. }
    10.  
    11. ..
    12.  
    13. FMOD_RESULT F_CALLBACK endCallback(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type,
    14. unsigned int commanddata1, unsigned int commanddata2)
    15. {
    16. AudioDevice* ad = dynamic_cast<AudioDevice*>(commanddata1);
    17. if (ad)
    18. ad->DoEndCallBack();
    19. ..
    20. }
    To copy to clipboard, switch view to plain text mode 

    Using the friends approach you can even declare the DoEndCallBack protected..

    HIH

    Johannes
    Hi thank you very much.
    I didn't understand. What does the DoEndCallback do?
    Sorry but in this case commanddata1 and commanddata2 are always 0.
    This is the part where I use the userdata:
    Qt Code:
    1. case FMOD_CHANNEL_CALLBACKTYPE_END:
    2. {
    3. FMOD_RESULT result;
    4. FMOD::Channel *currentChannel = (FMOD::Channel *)channel;
    5.  
    6. void *ud = NULL;
    7. result = currentChannel->getUserData( &ud ); //<---USERDATA
    8.  
    9. currentSound = (SoundData*)ud;
    10.  
    11. /* inform that sound stopped */
    12. currentSound->soundFinished(); //<-- I call a routine instead of emiting signals
    13. break;
    14. }
    To copy to clipboard, switch view to plain text mode 
    but I don't cast it to an AudioDevice type. AudioDevice is a singleton.
    I cast to a SoundData type ( in my example )..

    Is a bit difficult. May be I can not use signals in this case
    Last edited by franco.amato; 8th December 2009 at 05:19.
    Franco Amato

  4. #4
    Join Date
    Sep 2009
    Location
    Tashkent, Uzbekistan
    Posts
    107
    Thanks
    1
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: emit a signal from inside a callback routine

    Hi. When I met the same problem I solved that with startTimer/killTimer and void timerEvent ( QTimerEvent * event ) reimplementation. Then what you can do is to set any Boolean variable (or QMutex based variable if you have multiple access) to true (lock) accordingly and process that inside timerEvent.

    Typical solution might be:

    Qt Code:
    1. static const int timeScale = 50; // 50 Msec
    2.  
    3. class A: public QObject
    4. {
    5. Q_OBJECT
    6.  
    7. public:
    8.  
    9. Q_INVOKABLE A( QObject * parent = 0 )
    10. : QObject(parent),
    11. m_check(false),
    12. m_timer(0)
    13. {
    14. m_timer = startTimer(timeScale);
    15. }
    16. ~A()
    17. {
    18. if (m_timer > 0)
    19. killTimer(m_timer);
    20. }
    21.  
    22. public slots:
    23.  
    24. void handler()
    25. {
    26. if (m_check)
    27. return;
    28. // do something here
    29. m_check = true;
    30. }
    31.  
    32. protected:
    33. void timerEvent ( QTimerEvent * event)
    34. {
    35. if (m_check)
    36. {
    37. // do something
    38. emit some_signal(some_args);
    39. m_check != m_check; // Just quicker
    40. }
    41. }
    42. private:
    43.  
    44. bool m_check;
    45. int m_timer;
    46. }
    To copy to clipboard, switch view to plain text mode 

    Good luck.
    Last edited by Tanuki-no Torigava; 8th December 2009 at 05:51.

  5. #5
    Join Date
    Nov 2007
    Location
    Italy
    Posts
    694
    Thanks
    59
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: emit a signal from inside a callback routine

    Quote Originally Posted by Tanuki-no Torigava View Post
    Hi. When I met the same problem I solved that with startTimer/killTimer and void timerEvent ( QTimerEvent * event ) reimplementation. Then what you can do is to set any Boolean variable (or QMutex based variable if you have multiple access) to true (lock) accordingly and process that inside timerEvent.

    Typical solution might be:

    Qt Code:
    1. static const int timeScale = 50; // 50 Msec
    2.  
    3. class A: public QObject
    4. {
    5. Q_OBJECT
    6.  
    7. public:
    8.  
    9. Q_INVOKABLE A( QObject * parent = 0 )
    10. : QObject(parent),
    11. m_check(false),
    12. m_timer(0)
    13. {
    14. m_timer = startTimer(timeScale);
    15. }
    16. ~A()
    17. {
    18. if (m_timer > 0)
    19. killTimer(m_timer);
    20. }
    21.  
    22. public slots:
    23.  
    24. void handler()
    25. {
    26. if (m_check)
    27. return;
    28. // do something here
    29. m_check = true;
    30. }
    31.  
    32. protected:
    33. void timerEvent ( QTimerEvent * event)
    34. {
    35. if (m_check)
    36. {
    37. // do something
    38. emit some_signal(some_args);
    39. m_check != m_check; // Just quicker
    40. }
    41. }
    42. private:
    43.  
    44. bool m_check;
    45. int m_timer;
    46. }
    To copy to clipboard, switch view to plain text mode 

    Good luck.
    I don't know how to adapt your code for my purpose, but how can be possible to connect
    a slot of an object that's created when the gui is started with a signal of an object that is created later?
    I get an error
    Franco Amato

  6. #6
    Join Date
    Sep 2009
    Location
    Tashkent, Uzbekistan
    Posts
    107
    Thanks
    1
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: emit a signal from inside a callback routine

    I don't know how to adapt your code for my purpose, but how can be possible to connect
    a slot of an object that's created when the gui is started with a signal of an object that is created later?
    I get an error
    That is easy. Let's say you create object B from some method of the object A, so it will look like that:

    Qt Code:
    1. A::someMethod()
    2. {
    3. B* b = new B(this);
    4. connect(b, SIGNAL(b_signal(mask)), this, SLOT(signal_handler);
    5.  
    6. }
    To copy to clipboard, switch view to plain text mode 

    So, you get the idea.

  7. #7
    Join Date
    Nov 2007
    Location
    Italy
    Posts
    694
    Thanks
    59
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: emit a signal from inside a callback routine

    Quote Originally Posted by Tanuki-no Torigava View Post
    That is easy. Let's say you create object B from some method of the object A, so it will look like that:

    Qt Code:
    1. A::someMethod()
    2. {
    3. B* b = new B(this);
    4. connect(b, SIGNAL(b_signal(mask)), this, SLOT(signal_handler);
    5.  
    6. }
    To copy to clipboard, switch view to plain text mode 

    So, you get the idea.
    Hi yes,
    but what the key "mask" means?
    Seems that I have to connect after the new
    Franco Amato

  8. #8
    Join Date
    Feb 2007
    Location
    Karlsruhe, Germany
    Posts
    469
    Thanks
    17
    Thanked 90 Times in 88 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: emit a signal from inside a callback routine

    Hi there!

    You seem to miss the point of the commanddata.. That is data you pass along / define once when you call the callback-setup! You seem to pass 0 at the moment, that is why its zero. Just pass a pointer to your AudioDevice and it should work. That pointer-data then is passed to the callback each time it is called. At least that is, how callbacks usually work..

    You should have mentioned, that AudioDevice is a singleton.. Because than you can call the DoEndCallBack directly, even if your callback doesn't provide a user-defined-data (which I think it does => commanddata).

    protected:
    void DoEndCallBack() {emit soundStopped();}

    DoEndCallback just emits the soundStopped signal, as I defined it... But you can of course code it directly, see below:

    Let me give you a more complete Callback scenario:

    Qt Code:
    1. class TDAQCaptureThread : public QThread
    2. {
    3. friend int32 CVICALLBACK DoneCallback(TaskHandle taskHandle, int32 status, void *callbackData);
    4. Q_OBJECT
    5. signals:
    6. void Finished();
    7. protected:
    8. void run();
    9. };
    10.  
    11. #include "DAQCaptureThread.h"
    12.  
    13. int32 CVICALLBACK DoneCallback(TaskHandle taskHandle, int32 status, void *callbackData);
    14.  
    15. void TDAQCaptureThread::run()
    16. {
    17. ...
    18.  
    19. DAQmxRegisterDoneEvent(taskHandle,1,DoneCallback,this);
    20.  
    21. ..
    22.  
    23. DAQmxStartTask(taskHandle);
    24.  
    25. exec();
    26.  
    27. ...
    28.  
    29. }
    30.  
    31. int32 CVICALLBACK DoneCallback(TaskHandle taskHandle, int32 status, void *callbackData)
    32. {
    33. ..
    34.  
    35. emit ((TDAQCaptureThread*)callbackData)->Finished();
    36.  
    37. ...
    38.  
    39. return 0;
    40. }
    To copy to clipboard, switch view to plain text mode 

    The DAQmxRegisterDoneEvent is defined int the used DAQmx library as follows:

    Qt Code:
    1. int32 __CFUNC DAQmxRegisterDoneEvent(TaskHandle task, uInt32 options, DAQmxDoneEventCallbackPtr callbackFunction, void *callbackData);
    To copy to clipboard, switch view to plain text mode 

    This callbackData is what I'm talking about.. If you decide one day to have several AudioDevices :->

    HIH

    Johannes

  9. #9
    Join Date
    Nov 2007
    Location
    Italy
    Posts
    694
    Thanks
    59
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: emit a signal from inside a callback routine

    Quote Originally Posted by JohannesMunk View Post
    Hi there!

    You seem to miss the point of the commanddata.. That is data you pass along / define once when you call the callback-setup! You seem to pass 0 at the moment, that is why its zero. Just pass a pointer to your AudioDevice and it should work. That pointer-data then is passed to the callback each time it is called. At least that is, how callbacks usually work..

    You should have mentioned, that AudioDevice is a singleton.. Because than you can call the DoEndCallBack directly, even if your callback doesn't provide a user-defined-data (which I think it does => commanddata).

    protected:
    void DoEndCallBack() {emit soundStopped();}

    DoEndCallback just emits the soundStopped signal, as I defined it... But you can of course code it directly, see below:

    Let me give you a more complete Callback scenario:

    Qt Code:
    1. class TDAQCaptureThread : public QThread
    2. {
    3. friend int32 CVICALLBACK DoneCallback(TaskHandle taskHandle, int32 status, void *callbackData);
    4. Q_OBJECT
    5. signals:
    6. void Finished();
    7. protected:
    8. void run();
    9. };
    10.  
    11. #include "DAQCaptureThread.h"
    12.  
    13. int32 CVICALLBACK DoneCallback(TaskHandle taskHandle, int32 status, void *callbackData);
    14.  
    15. void TDAQCaptureThread::run()
    16. {
    17. ...
    18.  
    19. DAQmxRegisterDoneEvent(taskHandle,1,DoneCallback,this);
    20.  
    21. ..
    22.  
    23. DAQmxStartTask(taskHandle);
    24.  
    25. exec();
    26.  
    27. ...
    28.  
    29. }
    30.  
    31. int32 CVICALLBACK DoneCallback(TaskHandle taskHandle, int32 status, void *callbackData)
    32. {
    33. ..
    34.  
    35. emit ((TDAQCaptureThread*)callbackData)->Finished();
    36.  
    37. ...
    38.  
    39. return 0;
    40. }
    To copy to clipboard, switch view to plain text mode 

    The DAQmxRegisterDoneEvent is defined int the used DAQmx library as follows:

    Qt Code:
    1. int32 __CFUNC DAQmxRegisterDoneEvent(TaskHandle task, uInt32 options, DAQmxDoneEventCallbackPtr callbackFunction, void *callbackData);
    To copy to clipboard, switch view to plain text mode 

    This callbackData is what I'm talking about.. If you decide one day to have several AudioDevices :->

    HIH

    Johannes
    In this case commanddata1 and commanddata2 are not the user data ( fmod callbacks ). In this case they are 0. User data are sent by another routine setUserdata and I got it from inside the callback by getUserdData() .

    Thank you
    Franco Amato

  10. #10
    Join Date
    Feb 2007
    Location
    Karlsruhe, Germany
    Posts
    469
    Thanks
    17
    Thanked 90 Times in 88 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: emit a signal from inside a callback routine

    All right, I give up :->

    So your solution is to just emit the signal through the singleton?

    Qt Code:
    1. class AudioDevice : public QObject
    2. { Q_OBJECT
    3. friend FMOD_RESULT F_CALLBACK endCallback(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type,
    4. unsigned int commanddata1, unsigned int commanddata2);
    5.  
    6. public:
    7. static AudioDevice* singleton()
    8. {
    9. if (!instance)
    10. instance = new AudioDevice();
    11. return instance;
    12. }
    13. signals:
    14. void soundStopped();
    15.  
    16. protected:
    17. AudioDevice() {}
    18.  
    19. private:
    20. static AudioDevice *instance;
    21. };
    22.  
    23. AudioDevice* AudioDevice::instance = 0;
    24.  
    25. FMOD_RESULT F_CALLBACK endCallback(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type,
    26. unsigned int commanddata1, unsigned int commanddata2)
    27. {
    28. ..
    29. emit AudioDevice::singleton()->soundStopped();
    30. ..
    31. }
    To copy to clipboard, switch view to plain text mode 
    HIH

    Johannes

  11. #11
    Join Date
    Nov 2007
    Location
    Italy
    Posts
    694
    Thanks
    59
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: emit a signal from inside a callback routine

    Quote Originally Posted by JohannesMunk View Post
    All right, I give up :->

    So your solution is to just emit the signal through the singleton?

    Qt Code:
    1. class AudioDevice : public QObject
    2. { Q_OBJECT
    3. friend FMOD_RESULT F_CALLBACK endCallback(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type,
    4. unsigned int commanddata1, unsigned int commanddata2);
    5.  
    6. public:
    7. static AudioDevice* singleton()
    8. {
    9. if (!instance)
    10. instance = new AudioDevice();
    11. return instance;
    12. }
    13. signals:
    14. void soundStopped();
    15.  
    16. protected:
    17. AudioDevice() {}
    18.  
    19. private:
    20. static AudioDevice *instance;
    21. };
    22.  
    23. AudioDevice* AudioDevice::instance = 0;
    24.  
    25. FMOD_RESULT F_CALLBACK endCallback(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type,
    26. unsigned int commanddata1, unsigned int commanddata2)
    27. {
    28. ..
    29. emit AudioDevice::singleton()->soundStopped();
    30. ..
    31. }
    To copy to clipboard, switch view to plain text mode 
    HIH

    Johannes
    Hi I didn't well understand the difference between your last code and the code you suggested to me before.
    Can you explain to me?
    Best Regards
    Franco Amato

Similar Threads

  1. how to emit signal in a static function ?
    By cxl2253 in forum Qt Programming
    Replies: 32
    Last Post: 7th July 2016, 21:36
  2. emit qt signal is very slow how it can be optimized?
    By sawerset in forum Qt Programming
    Replies: 8
    Last Post: 30th December 2008, 09:21
  3. pthread instead QThread
    By brevleq in forum Qt Programming
    Replies: 8
    Last Post: 23rd December 2008, 07:16
  4. Connection of custon signals/slots
    By brevleq in forum Qt Programming
    Replies: 2
    Last Post: 23rd December 2008, 07:04
  5. how to know which button emit the signal?
    By coder1985 in forum Qt Programming
    Replies: 2
    Last Post: 12th January 2008, 14:26

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
  •  
Qt is a trademark of The Qt Company.