Multiple devices not getting SI_SKIP_EVENT

Post questions, comments and feedback to our 3Dconnexion Windows Development Team.

Moderator: Moderators

Post Reply
heisters
Posts: 8
Joined: Fri Mar 04, 2016 12:30 pm

Multiple devices not getting SI_SKIP_EVENT

Post by heisters »

I have multiple devices almost working. I create a hidden window on a secondary thread, and open the devices on that thread. I have verified that I can open two devices, each has a different SiHdl address, and device id. I can address the LED on each device independently. The only issue is that SiGetEvent seems to always return SI_IS_EVENT for one device, despite different devices initiating the events. Which device it returns SI_IS_EVENT for appears to be random, and changes when the application is restarted even though the devices are always grabbed in sequential order.

Here is the event processing loop: https://github.com/heisters/Cinder-3DCo ... n.cpp#L120
Here is where the devices are opened: https://github.com/heisters/Cinder-3DCo ... n.cpp#L241

The 3DxTest demo has some mentions of multiple devices. As far as I could tell, it creates a separate window for every device, and thereby a separate event queue for each device. Is this truly necessary? Is there some way I can get multiple devices working using the same event queue?
UtaSH
Moderator
Moderator
Posts: 3754
Joined: Mon Nov 27, 2006 10:34 am
Location: Munich, Germany
Contact:

Re: Multiple devices not getting SI_SKIP_EVENT

Post by UtaSH »

Moving the topic to the Developer's Forum.
jwick
Moderator
Moderator
Posts: 3331
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA
Contact:

Re: Multiple devices not getting SI_SKIP_EVENT

Post by jwick »

3DxTest does not handle multiple devices individually. The puzzle demo does. Here is the relevant event processing code. You have to ask about each device. The device handles were previously opened and saved in an array.

Code: Select all

    // Loop through all the devices.
    SiGetEventWinInit (&eData, msg.message, msg.wParam, msg.lParam);
    for(int devID=0; devID <= MAX_DEVICE_INDEX; devID++)
	  {
		  if (devHdls[devID] != SI_NO_HANDLE)
		  {
			  if (SiGetEvent (devHdls[devID], 0, &eData, &event) == SI_IS_EVENT)
			  {
				  SiDispatch (devHdls[devID], &eData, &event, &DspHandlers);
			  }
		  }
	  }
SI_SKIP_EVENT means ignore it. The driver probably swallowed it or it was removed for some other reason.
Just respond to the SI_MOTION_EVENT, buttons, etc. If the user hotplugs a device you get a SI_DEVICE_CHANGE_EVENT.
There is no order guarantee, but I think you can get the portname if you want to see which port the device is on. That should be unique.
heisters
Posts: 8
Joined: Fri Mar 04, 2016 12:30 pm

Re: Multiple devices not getting SI_SKIP_EVENT

Post by heisters »

ok, thanks for the info about SI_SKIP_EVENT. I had assumed it would be returned if I called SiGetEvent on a message that was not associated with the passed handle. Based on the documentation: "If SiGetEvent returns a value of SI_SKIP_EVENT, this indicates the event is indeed a 3DxWare event, but should not be processed because it is not associated with the specified 3DxWare handle."

The code you pasted looks pretty analogous to mine, with the main functional difference being that you use SiDispatch whereas I use a custom event dispatcher. Is there any way I can look at the rest of the code? I couldn't find the puzzle demo in the SDK directory, and the only reference I could find to it online was a forum post that ended with it being taken off the FTP.

Comparing the port name seems like a good approach. I had hoped to get the device handle associated with each event and compare those, but if the port name is easier to get, that would work too. The only issue is that I don't see ANY information identifying the device originating the event in the documentation on the SiSpwEvent structure, except for SI_DEVICE_CHANGE_EVENT events. I logged the deviceChangeEventData devID and portName for the button down events, and they appear to be the same, regardless of which device originated the event.
heisters
Posts: 8
Joined: Fri Mar 04, 2016 12:30 pm

Re: Multiple devices not getting SI_SKIP_EVENT

Post by heisters »

I've discovered that changing my call to SiGrabDevice to use "soft capture" causes SiGetEvent to only return SI_IS_EVENT when the passed device handle matches the originating device. This is how I had expected it to work in the first place, and it allows me to correctly identify the originating device.

Not sure if this is a bug in the SDK, but it certainly is counter-intuitive.

You can see the updated code here: https://github.com/heisters/Cinder-3DCo ... nexion.cpp. While this does contain some Cinder-specific code, it may be useful to others as a reference.
jwick
Moderator
Moderator
Posts: 3331
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA
Contact:

Re: Multiple devices not getting SI_SKIP_EVENT

Post by jwick »

Which is counter-intuitive? With SiGrabDevice or without SiGrabDevice?

What were you passing to SiGrabDevice? What were you hoping to achieve with this call?
heisters
Posts: 8
Joined: Fri Mar 04, 2016 12:30 pm

Re: Multiple devices not getting SI_SKIP_EVENT

Post by heisters »

It's counter-intuitive that any call to SiGrabDevice would change the behavior of SiGetEvent in any way. I was calling SiGrabDevice like so:

Code: Select all

SiGrabDevice( device.handle, SPW_TRUE )
Changing that to:

Code: Select all

SiGrabDevice( device.handle, SPW_FALSE )
... fixed my message pump.

I had wanted an exclusive claim on the devices so that other applications couldn't steal their input. This is "mission-critical" code, and any interruption in the message stream would be disastrous.
jwick
Moderator
Moderator
Posts: 3331
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA
Contact:

Re: Multiple devices not getting SI_SKIP_EVENT

Post by jwick »

If it is mission critical, you should not be using this driver. You shouldn't be using Windows frankly. But you should at least be using a method of communicating with the device without the driver in the way. It in no way guarantees anything and does a lot of other things that you don't want like scaling the data depending on how you process it. You should be opening the device(s) directly so there is as little as possible between the device and your application.

Maybe SiGrabDevice should have a different behavior for multiple device aware applications. I don't know which is right. Since you pass a hdl, should all data from all devices go there? Then I would have to add a way for you to tell which device sent the data. Or should it mean that focus never leaves the app, but device data gets delivered through the individual hdls that were registered for the same app?

Currently, it only works predictably with SPW_TRUE and a single application connection. This is the only way it is currently used that I know of. And it is used for connections that don't get focus -- background apps. In that case, all device data is folded together and no matter what the user is doing, focus-wise, the data always goes to this one connection.

It's a work in progress.
Post Reply