July 25, 2011

Julien M Julien M
Lab Rat
311 posts

Reimplementing winEvent: getting stuck in API call

Page  
1

I am trying to build a bridge between two API:

  • one communicates through sendMessages
  • the other one is accessible through an activeX

This is what I do:

  1.     HRESULT hr = pMJ.GetActiveObject(L"MediaJukebox Application");
  2.     pPlayback = pMJ->GetPlayback();
  3.     pPlayback->Play();

The Play() call works perfectly.
Then I connect a pushButton to a slot that will also call pPlayback->Play(), it works.

Finally I reimplement winEvent(…) to receive message from the other program.

  1. bool Bridge::winEvent(MSG *message, long *result)
  2. {
  3.     if( message->message == WM_USER )
  4.     {
  5.         pPlayback->Play();
  6.  
  7.         *result = 0; // keep the event from qt
  8.         return true;
  9.     }
  10.  
  11.     // give the event to qt
  12.     return false;
  13. }
Here for some reason, the Play() call never returns. I’m stuck indefinitely in it!
In the meantime I can click my pushButton, and this one will work. But within winEven(…) it doesn’t.

What is the issue there? Am I triggering an infinite recursion?

19 replies

July 25, 2011

Gerolf Gerolf
Robot Herder
3253 posts

Hi neFAST,

are you in an infinite loop (which could mean Play also emits a WM_USER event) or does it only “not work”? You should check the window, that gets the message here. Which type has bridge? Widget? QApplication derived? …

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

July 25, 2011

Julien M Julien M
Lab Rat
311 posts

Thanks for your help.
How can I check the window that gets the message?
Bridge is a QMainWindow

EDIT: I tried a mutex-like in winEvent(…)

  1.     if( message->message == WM_USER )
  2.     {
  3.         if( !CDArtMutex )
  4.             CDArtMutex = true;
  5.         else
  6.             return false;
  7.         pPlayback->Pause();
  8.         emit handleCDArtEventUser((int)message->lParam, (int)message->wParam, result);
  9.         *result = 0;
  10.         CDArtMutex = false;
  11.         return true;
  12.     }

This does not solve the issue.

July 26, 2011

Gerolf Gerolf
Robot Herder
3253 posts

The point is that you only check one members of message…
message also more members:

  • hwnd Handle to the window whose window procedure receives the message.
  • message Specifies the message identifier.
  • wParam Specifies additional information about the message. The exact meaning depends on the value of the message member.
  • lParam Specifies additional information about the message. The exact meaning depends on the value of the message member.
  • time Specifies the time at which the message was posted.
  • pt Specifies the cursor position, in screen coordinates, when the message was posted.

you could compare hwnd with the winID() [doc.qt.nokia.com] of your main window.

Why the mutex does not work is also simple: if play doies not send the event but post it, it will arrive after you exited the event handler…

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

July 26, 2011

Julien M Julien M
Lab Rat
311 posts

I’m not sure to understand your 2 remarks:
1. ok let’s say I detect event sent by my main window. What should I do? Discard them?
2. what would be the problem if the event posted by play() arrive later on?

Sorry for these silly questions, I feel kinda lost.

July 27, 2011

Gerolf Gerolf
Robot Herder
3253 posts

Each WM_USER evtn is handled by you regardless who is the receiver of the event. Afterwards you throw it away by returning true (handled).
And for each WM_USER event you call ->play().

I suggest the following:

  1. if( (message->message == WM_USER ) && (message->hwnd == winId()) )
  2. {
  3.     pPlayback->Pause();
  4.     emit handleCDArtEventUser((int)message->lParam, (int)message->wParam, result);
  5.     *result = 0;
  6.     return true;
  7. }

Doing this you only react on WM_USER messages send to Your window.

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

July 27, 2011

Julien M Julien M
Lab Rat
311 posts

I will try to filter messages addressed to my winId.
But I still don’t understand why I have this strange behavior. I have run the msvc debugger step by step. When I reach play() and press the “next step” button, it never returns from play().
I simplified my code to post it in a more readable format. I already perform some filterning, but not on the winId. So maybe this will fix the issue.

EDIT: filtering with the winId() did not solve my issue…

July 27, 2011

Julien M Julien M
Lab Rat
311 posts

I stepped into the Play() call and found this:

  1. inline HRESULT IMJPlaybackAutomation::Play ( ) {
  2.     return _com_dispatch_method(this, 0xf, DISPATCH_METHOD, VT_EMPTY, NULL, NULL);
  3. }

July 27, 2011

Gerolf Gerolf
Robot Herder
3253 posts
neFAST wrote:
I stepped into the Play() call and found this: @inline HRESULT IMJPlaybackAutomation::Play ( ) { return _com_dispatch_method(this, 0xf, DISPATCH_METHOD, VT_EMPTY, NULL, NULL); }@

This only shows that play is a COM call, but what does it do internally?

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

July 27, 2011

Julien M Julien M
Lab Rat
311 posts

I don’t know I do not have access to this source code.
I suspect that when I call play() from my winEvent(…) reimplementation I am not in the main thread and this causes the problem.

July 27, 2011

Gerolf Gerolf
Robot Herder
3253 posts

your events of UI widgets are always in the main thread, onlöy if sendEvent is used and not post event, it is possible to be outside the main thread.
But typically in Qt, everything that is UI relevant happens in the main thread, and this includes the events handlers. This is a MUST.

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

July 27, 2011

Julien M Julien M
Lab Rat
311 posts

Ok then what could explain that play() returns correctly when started in a slot connected to a button in my GUI. And it blocks when called within winEvent()?

July 27, 2011

Julien M Julien M
Lab Rat
311 posts

You were right, everything stays in the main thread. How can I figure out if the COM control fires an event that is caught by winEvent in a recursive way?

With our without my stupid mutex, the test() call is never reached !?

  1. if( message->message == WM_USER && message->hwnd == winId() )
  2.     {
  3.         if( !CDArtMutex )
  4.         {
  5.             CDArtMutex=true;
  6.  
  7.             pPlayback->Play();
  8.             test();
  9.             CDArtMutex=false;
  10.             *result = 0;
  11.             return true;
  12.         }
  13.         else
  14.         {
  15.             // give the event to qt
  16.             return false;
  17.         }
  18.     }

July 27, 2011

Gerolf Gerolf
Robot Herder
3253 posts

That can have multiple reasons, and I can’t tell you from that small code fragment. If you provide a small, minimal example showing this that can be compiled, then perhaps.

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

July 27, 2011

Julien M Julien M
Lab Rat
311 posts

My code is really minimal but it is a bridge between 2 applications: if you want to test it you will have to fire messages. Keep in mind it is windows only.
I uploaded an archive here: hotfile [hotfile.com]
You will see that I got something working with QTimer::singleshot() but this is not a real solution since I can’t pass any arguments to my slots. So it is working for Play() but not for other calls.
Thanks again for your kind help!

July 27, 2011

Gerolf Gerolf
Robot Herder
3253 posts

i,

I looked a bit into your code but saw no direct bug, but I also have no idea how this CDART and JRMC stuff works, sorry.

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

Page  
1

  ‹‹ QRegExp - how to parse (G)UID?      [solved] QGraphicsView in a QTabWidget ››

You must log in to post a reply. Not a member yet? Register here!