Closed PWBENNETT closed 7 years ago
joystick
isn't really a collection or array, it's just an object that happens to have an indexer (which allows you to use [] to get an item from it). When you use it to get an object by name or by index, it simply calls a function that gets the i'th item from an internal list, or searches that list for the given name. The names and/or collection length are not publicly exposed, even if you get a joystick object (there's no joystick[i].name() or equivalent). The error is actually a general python error, telling you that "keys" does not exist on the object (neither as function or other type).
For implementation details, the joystick object is a globalindexer, which is backed by these 2 functions to read from the list.
In other words, retrieving the names is not possible unless you add such a function and recompile FreePIE, or through reflection.
Thanks. I'll start RTFMing on IronPython, then. In the meantime, I suppose I can loop over the integers from 0 thru number_of_joysticks_plugged_in - 1 and at least learn which one has which number.
Do you have an alternative method for finding out which name FreePIE uses for which device? Windows 10 64-bit. Thanks.
At first glance, it looks like the joystick object includes my vJoy devices (joystick[0].x matches what I'm (elsewhere) setting vJoy[0].x to). Is this a bug or a feature?
Never mind. It looks like the USB HID device I want to reprogram (the thumbstick on my Logitech G13) does not show up in the joystick[] object. I think I'm going to have to learn how to write FreePIE plugins, and then write one for the G13.
How do I do "joystick[n].update += update"? That's another case of "... object has no attribute 'update'"
Basically, I want update() to execute every time a given joystick moves, in just the same way I can midi[1].update += update. Well, it doesn't have to be "in exactly the same way". Any way that works is fine by me.
I feel like I'm tantalizingly close with ...
import clr
from pprint import pformat
def update():
clr_type = clr.GetClrType(type(joystick))
all_fields = clr_type.GetMembers()
field_names = [ m.ToString() for m in all_fields if m.Name == 'Item' ]
watchme = pformat(field_names)
diagnostics.watch(watchme)
... but I don't quite know enough IronPython or .NET to (quickly) get over the next hump. I'll keep plugging away at it. It's a great learning experience.
At first glance, it looks like the joystick object includes my vJoy devices (joystick[0].x matches what I'm (elsewhere) setting vJoy[0].x to). Is this a bug or a feature?
This is part of how vJoy and DirectInput work - vJoy simulates a DirectInput device with a driver that's installed, hence why it shows up when enumerating DirectInput devices (otherwise it won't work in games either). There's no feature built into FreePIE to remove all vJoy devices from the list, but that's a nice feature to add since it's quite hard to get the device name.
Never mind. It looks like the USB HID device I want to reprogram (the thumbstick on my Logitech G13) does not show up in the joystick[] object. I think I'm going to have to learn how to write FreePIE plugins, and then write one for the G13.
I don't have a G13 so I can't comment with authority - it seems you should be able to set the thumbstick
to act like a joystick from the Logitech Gaming Software, perhaps that works. You can access it through joystick[]
as soon as it shows up in the "Set up USB game controllers" panel.
It's a good idea to pull the FreePIE source code and run your own build, makes it a lot easier to see the internals and make your own changes. It's not necessary for plugin development though.
I feel like I'm tantalizingly close with ...
Not so fast :wink:, it's a little more complicated to get the device name. Like I said, joystick
is just an object with a function to iterate over a collection, it doesn't contain this collection directly (JoystickPlugin
has it). As such, I find it easier to extract the private device
field from a JoystickGlobal
object (which is returned by calling joystick[i]). Then, get the private SlimDX.DirectInput.Joystick
field joystick
, from where the device name can be accessed (it's both in the Properties
as in the Information
field).
import clr
import System
from System.Reflection import *
if starting:
num_devices = 1
devs = [joystick[i] for i in range(num_devices)]
joystick_global = clr.GetClrType(type(devs[0]))
device = joystick_global.GetField("device", BindingFlags.NonPublic | BindingFlags.Instance)
di_joystick = device.FieldType.GetField("joystick", BindingFlags.NonPublic | BindingFlags.Instance)
for dev in devs:
device_val = device.GetValue(dev)
joystick_val = di_joystick.GetValue(device_val)
diagnostics.debug("dev: {0}", joystick_val.Properties.InstanceName)
Aha... I think I kinda sorta understand what you're doing there. Enough of it for now. Thank you so very much.
Aha... I think I kinda sorta understand what you're doing there. Enough of it for now. Thank you so very much.
You're welcome. It's a little complicated so I recommend you to look at the source code, which is where I got the class/field/type structure from.
I couldn't work out where diagnostics.debug() writes to (it doesn't seem to be the Console tab). I ended up using diagnostics.watch() and some hard-coded numbers to extract the joystick names, and it worked a treat. Thanks again!
https://gist.github.com/PWBENNETT/0c178601cf6e614e14b7593ef78ff230 is the whole shebang, as it stands right now.
I'm trying to find out what FreePIE calls my joysticks, with something like
However, the error message "... object has no attribute 'keys'" is utterly opaque (to me). Any hints or tips on how I can proceed? The API documentation seems to be a bit slim on this subject.