X-Git-Url: https://git.yukkurigames.com/?p=enjoyable.git;a=blobdiff_plain;f=Joystick.m;h=7870ce0589ec6e6a44f0d54790726eb0bf664d0b;hp=8fa67919789fde788b7c9bd807e787d63f21146a;hb=dd1f684886c2809133356bb9b335a35293e8849e;hpb=530009447c5bbd360ac5023979cffc6d32a28df3 diff --git a/Joystick.m b/Joystick.m index 8fa6791..7870ce0 100644 --- a/Joystick.m +++ b/Joystick.m @@ -5,112 +5,107 @@ // Created by Sam McCall on 4/05/09. // -@implementation Joystick - +#import "Joystick.h" -@synthesize vendorId, productId, productName, name, index, device, children; +#import "JSAction.h" +#import "JSActionAnalog.h" +#import "JSActionButton.h" +#import "JSActionHat.h" --(id)initWithDevice: (IOHIDDeviceRef) newDevice { - if(self=[super init]) { - children = [[NSMutableArray alloc]init]; - - device = newDevice; - productName = (NSString*)IOHIDDeviceGetProperty( device, CFSTR(kIOHIDProductKey) ); - vendorId = [(NSNumber*)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey)) intValue]; - productId = [(NSNumber*)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey)) intValue]; - - name = productName; - } - return self; +static NSArray *ActionsForElement(IOHIDDeviceRef device, id base) { + CFArrayRef elements = IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone); + NSMutableArray *children = [NSMutableArray arrayWithCapacity:CFArrayGetCount(elements)]; + + int buttons = 0; + int axes = 0; + + for (int i = 0; i < CFArrayGetCount(elements); i++) { + IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i); + int type = IOHIDElementGetType(element); + int usage = IOHIDElementGetUsage(element); + int usagePage = IOHIDElementGetUsagePage(element); + int max = IOHIDElementGetPhysicalMax(element); + int min = IOHIDElementGetPhysicalMin(element); + CFStringRef elName = IOHIDElementGetName(element); + + JSAction *action = nil; + + if (!(type == kIOHIDElementTypeInput_Misc + || type == kIOHIDElementTypeInput_Axis + || type == kIOHIDElementTypeInput_Button)) + continue; + + if (max - min == 1 || usagePage == kHIDPage_Button || type == kIOHIDElementTypeInput_Button) { + action = [[JSActionButton alloc] initWithName:(__bridge NSString *)elName + idx:++buttons + max:max]; + } else if (usage == kHIDUsage_GD_Hatswitch) { + action = [[JSActionHat alloc] init]; + } else if (usage >= kHIDUsage_GD_X && usage <= kHIDUsage_GD_Rz) { + // TODO(jfw): Scaling equation doesn't seem right if min != 0. + action = [[JSActionAnalog alloc] initWithIndex:++axes + offset:-1.f + scale:2.f / (max - min)]; + } else { + continue; + } + + // TODO(jfw): Should be moved into better constructors. + action.base = base; + action.cookie = IOHIDElementGetCookie(element); + [children addObject:action]; + } + return children; } --(void) setIndex: (int) newIndex { - index = newIndex; - name = [[NSString alloc] initWithFormat: @"%@ #%d", productName, (index+1)]; -} --(int) index { - return index; -} +@implementation Joystick --(void) invalidate { - IOHIDDeviceClose(device, kIOHIDOptionsTypeNone); - NSLog(@"Removed a device: %@", [self name]); -} +@synthesize vendorId; +@synthesize productId; +@synthesize productName; +@synthesize index; +@synthesize device; +@synthesize children; --(id) base { - return NULL; +- (id)initWithDevice:(IOHIDDeviceRef)dev { + if ((self = [super init])) { + self.device = dev; + self.productName = (__bridge NSString *)IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDProductKey)); + self.vendorId = [(__bridge NSNumber *)IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDVendorIDKey)) intValue]; + self.productId = [(__bridge NSNumber *)IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDProductIDKey)) intValue]; + self.children = ActionsForElement(dev, self); + } + return self; } --(void) populateActions { - NSArray* elements = (NSArray*)IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone); - - int buttons = 0; - int axes = 0; - - for(int i=0; i<[elements count]; i++) { - IOHIDElementRef element = (IOHIDElementRef)[elements objectAtIndex: i]; - int type = IOHIDElementGetType(element); - int usage = IOHIDElementGetUsage(element); - int usagePage = IOHIDElementGetUsagePage(element); - int max = IOHIDElementGetPhysicalMax(element); - int min = IOHIDElementGetPhysicalMin(element); - CFStringRef elName = IOHIDElementGetName(element); - -// if(usagePage != 1 || usagePage == 9) { -// NSLog(@"Skipping usage page %x usage %x", usagePage, usage); -// continue; -// } - - JSAction* action = NULL; - - if(!(type == kIOHIDElementTypeInput_Misc || type == kIOHIDElementTypeInput_Axis || - type == kIOHIDElementTypeInput_Button)) { - - continue; - } - - if((max - min == 1) || usagePage == kHIDPage_Button || type == kIOHIDElementTypeInput_Button) { - action = [[JSActionButton alloc] initWithIndex: buttons++ andName: (NSString *)elName]; - [(JSActionButton*)action setMax: max]; - } else if(usage == 0x39) - action = [[JSActionHat alloc] init]; - else { - if(usage >= 0x30 && usage < 0x36) { - action = [[JSActionAnalog alloc] initWithIndex: axes++]; - [(JSActionAnalog*)action setOffset: (double)-1.0]; - [(JSActionAnalog*)action setScale: (double)2.0/(max - min)]; - } else - continue; - } +- (NSString *)name { + return [NSString stringWithFormat:@"%@ #%d", productName, index]; +} - [action setBase: self]; - [action setUsage: usage]; - [action setCookie: IOHIDElementGetCookie(element)]; - [children addObject:action]; - } +- (id)base { + return nil; } --(NSString*) stringify { - return [[NSString alloc] initWithFormat: @"%d~%d~%d", vendorId, productId, index]; +- (NSString *)uid { + return [NSString stringWithFormat: @"%d:%d:%d", vendorId, productId, index]; } -- (JSAction*) findActionByCookie: (void*) cookie { - for(int i=0; i<[children count]; i++) - if([[children objectAtIndex:i]cookie] == cookie) - return (JSAction*)[children objectAtIndex:i]; - return NULL; +- (JSAction *)findActionByCookie:(void *)cookie { + for (JSAction *child in children) + if (child.cookie == cookie) + return child; + return nil; } --(id) handlerForEvent: (IOHIDValueRef) value { - JSAction* mainAction = [self actionForEvent: value]; - if(!mainAction) - return NULL; - return [mainAction findSubActionForValue: value]; +- (id)handlerForEvent:(IOHIDValueRef) value { + JSAction *mainAction = [self actionForEvent:value]; + return [mainAction findSubActionForValue:value]; } --(JSAction*) actionForEvent: (IOHIDValueRef) value { - IOHIDElementRef elt = IOHIDValueGetElement(value); - void* cookie = IOHIDElementGetCookie(elt); - return [self findActionByCookie: cookie]; + +- (JSAction *)actionForEvent:(IOHIDValueRef)value { + IOHIDElementRef elt = IOHIDValueGetElement(value); + void *cookie = IOHIDElementGetCookie(elt); + return [self findActionByCookie:cookie]; } @end