Where's the SDK?

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

Moderator: Moderators

kitsu
Posts: 7
Joined: Thu Aug 09, 2007 1:28 pm

Post by kitsu »

Oops, nevermind. I had a beer and everything fell together*. The following code prints out nice floating point value as I move the cap.

Code: Select all

import comtypes.client as client
from ctypes import *

import logging
console = logging.StreamHandler()
console.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
console.setFormatter(formatter)
logging.getLogger('').addHandler(console)

types = { # What others?
	0:"Unknown",
	6:"SpaceNavigator",
	4:"SpaceExplorer",
	25:"SpaceTravler",
	29:"SpacePilot"
}

class POINT(Structure):
    """Point struct used in Win32 api functions."""
    _fields_ = [("x", c_long),
                ("y", c_long)]

class MSG(Structure):
    """Message struct used in Win32 api functions."""
    _fields_ = [("hWnd", c_ulong),
                ("message", c_uint),
                ("wParam", c_ulong),
                ("lParam", c_ulong),
                ("time", c_ulong),
                ("pt", POINT)]
    
def PumpWaitingMessages():
    """Windows API function."""
    user32 = windll.user32
    msg = MSG()
    PM_REMOVE = 0x0001
    while user32.PeekMessageA(byref(msg), 0, 0, 0, PM_REMOVE):
        user32.TranslateMessage(byref(msg))
        user32.DispatchMessageA(byref(msg))

def GetMessage():
    """Windows API function."""
    #BOOL GetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax);
    user32 = windll.user32
    msg = MSG()
    user32.GetMessageW(byref(msg), None, 0, 0)
    return msg

def DispatchMessage(msg):
    """Windows API function."""
    user32 = windll.user32
    user32.DispatchMessageW(byref(msg))

class KeyListener:
    """Catch and print keyboard events.

    Note: some keys either don't send events or give bad key codes.
    """
    def __init__(self, keyboard):
        self.exit = False
        self.keyboard = keyboard
        self.exitCode = 1

    def cont(self):
        return not self.exit
    
    def KeyDown(self, this, code):
        print 'Keydown: %s, %s' %(code, self.keyboard.GetKeyName(code))
        if code == self.exitCode:
            self.exit = True

    def KeyUp(self, this, code):
        print 'Keyup: %s, %s' %(code, self.keyboard.GetKeyName(code))

class SensorListener:
    """Catch and print sensor events."""
    def __init__(self, sensor):
        self.sensor = sensor
    
    def SensorInput(self, this, inval=None):
        print "Rot: ",
        print self.sensor.Rotation.X,
        print self.sensor.Rotation.Y,
        print self.sensor.Rotation.Z
        print "Trans: ",
        print self.sensor.Translation.X,
        print self.sensor.Translation.Y,
        print self.sensor.Translation.Z

# Get device
device = client.CreateObject("TDxInput.Device")
print types[device.Type],

if not device.Connect(): # Returns failed
	print ": Connected!"

# Setup keyboard listener
keyboard = device.Keyboard
listener = KeyListener(keyboard)
client.GetEvents(keyboard, listener)

# Setup sensor listener
sensor = device.Sensor
client.GetEvents(sensor, SensorListener(sensor))

# Start event loop
while listener.cont():
    msg = GetMessage()
    DispatchMessage(msg)
    #PumpWaitingMessages()
    

Note that there is a error in the comtypes 0.3.2 GetEvents function which causes it to miss all events. I've reported it to the mailing list, but until it is fixed use comtypes 0.2.1.

If you are using pywin32 you should be able to fine the GetMessage, DispatchMessage, and TranslateMessage functions in win32event module.

One continuing problem I've had though is that some key events don't seem to be working correctly. I have the SpaceExplorer - the model with the second most buttons BTW. I'm guessing that the esc, ctrl, etc keys are generating normal keycodes like a keyboard? What are the key codes for 2d and 'fit' though. I think 32 is the keycode for 'fit', but keyboard.GetKeyName(code) raises a undefined COM error?

* This poster neither endorses nor encourages the consumption of alcohol, except in cases involving the Component Object Model or the Window's API*
calli
Posts: 12
Joined: Tue Aug 07, 2007 4:27 am

Post by calli »

My Hero!

Thanks to beer! ;-)
Carsten
kitsu
Posts: 7
Joined: Thu Aug 09, 2007 1:28 pm

Post by kitsu »

I just noticed something interesting this morning - pressing the 2d button toggles sensor.Rotation between outputing all zeros or meaningful values. It seems this behavior is at 'hardware' level (or at least not exposed via COM).

In future releases it might be nice to have a settable 2d attribute in the sensor object. Otherwise there is no way to change the value at run time. It would be fine if I could create arbitrary configuration preference files, but as it is now any software I write will be stuck with the general preferences.

Actually I just peeked and it looks like the configurations are just plain text files? I suppose I can go fake my own then, but I would prefer a nice API to protect me from future format changes. Depending on undocumented file formats sucks :(
etr9j
Posts: 2
Joined: Fri Apr 03, 2009 8:09 pm

Post by etr9j »

I know this post fairly old, but I'm trying to get python working with my navigator and this script seems like it's the best bet. I can get it working to a point. Running the script shows "SpaceNavigator : Connected!" but that's it - I don't get values printing out.

It might have to do with version issues, since I'm using a newer version of comtypes than described. It might also be that some subtle changes in python itself since this post might be to blame (I'm working in python 2.5 at the moment).

But since it works to some degree I hope it might be something less complicated. It looks like the listeners aren't working even though there isn't an error.

Anyone have any ideas?
etr9j
Posts: 2
Joined: Fri Apr 03, 2009 8:09 pm

Post by etr9j »

Okay, looks like it was a version issue. For this to work you really need comtypes 0.2.1. I was using 0.6.0 thinking any bugs in this function was resolved by now, but it seems that the 0.2.1 GetEvents is a bit more involved. With a little searching I found v 0.2.1 here.
Post Reply