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?
Multiple devices not getting SI_SKIP_EVENT
Moderator: Moderators
Re: Multiple devices not getting SI_SKIP_EVENT
Moving the topic to the Developer's Forum.
Uta
3Dconnexion
3Dconnexion
Re: Multiple devices not getting SI_SKIP_EVENT
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.
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.
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);
}
}
}
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.
Re: Multiple devices not getting SI_SKIP_EVENT
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.
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.
Re: Multiple devices not getting SI_SKIP_EVENT
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.
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.
Re: Multiple devices not getting SI_SKIP_EVENT
Which is counter-intuitive? With SiGrabDevice or without SiGrabDevice?
What were you passing to SiGrabDevice? What were you hoping to achieve with this call?
What were you passing to SiGrabDevice? What were you hoping to achieve with this call?
Re: Multiple devices not getting SI_SKIP_EVENT
It's counter-intuitive that any call to SiGrabDevice would change the behavior of SiGetEvent in any way. I was calling SiGrabDevice like so:
Changing that to:
... 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.
Code: Select all
SiGrabDevice( device.handle, SPW_TRUE )
Code: Select all
SiGrabDevice( device.handle, SPW_FALSE )
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.
Re: Multiple devices not getting SI_SKIP_EVENT
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.
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.