Reset target settings in UI when switching target types.
[enjoyable.git] / Joystick.m
1 //
2 // Joystick.m
3 // Enjoy
4 //
5 // Created by Sam McCall on 4/05/09.
6 //
7
8 #import "Joystick.h"
9
10 #import "JSAction.h"
11 #import "JSActionAnalog.h"
12 #import "JSActionButton.h"
13 #import "JSActionHat.h"
14
15 static NSArray *ActionsForElement(IOHIDDeviceRef device, id base) {
16 CFArrayRef elements = IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);
17 NSMutableArray *children = [NSMutableArray arrayWithCapacity:CFArrayGetCount(elements)];
18
19 int buttons = 0;
20 int axes = 0;
21
22 for (int i = 0; i < CFArrayGetCount(elements); i++) {
23 IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i);
24 int type = IOHIDElementGetType(element);
25 int usage = IOHIDElementGetUsage(element);
26 int usagePage = IOHIDElementGetUsagePage(element);
27 int max = IOHIDElementGetPhysicalMax(element);
28 int min = IOHIDElementGetPhysicalMin(element);
29 CFStringRef elName = IOHIDElementGetName(element);
30
31 JSAction *action = nil;
32
33 if (!(type == kIOHIDElementTypeInput_Misc
34 || type == kIOHIDElementTypeInput_Axis
35 || type == kIOHIDElementTypeInput_Button))
36 continue;
37
38 if (max - min == 1 || usagePage == kHIDPage_Button || type == kIOHIDElementTypeInput_Button) {
39 action = [[JSActionButton alloc] initWithName:(__bridge NSString *)elName
40 idx:++buttons
41 max:max];
42 } else if (usage == kHIDUsage_GD_Hatswitch) {
43 action = [[JSActionHat alloc] init];
44 } else if (usage >= kHIDUsage_GD_X && usage <= kHIDUsage_GD_Rz) {
45 // TODO(jfw): Scaling equation doesn't seem right if min != 0.
46 action = [[JSActionAnalog alloc] initWithIndex:++axes
47 offset:-1.f
48 scale:2.f / (max - min)];
49 } else {
50 continue;
51 }
52
53 // TODO(jfw): Should be moved into better constructors.
54 action.base = base;
55 action.cookie = IOHIDElementGetCookie(element);
56 [children addObject:action];
57 }
58 return children;
59 }
60
61 @implementation Joystick
62
63 @synthesize vendorId;
64 @synthesize productId;
65 @synthesize productName;
66 @synthesize index;
67 @synthesize device;
68 @synthesize children;
69
70 - (id)initWithDevice:(IOHIDDeviceRef)dev {
71 if ((self = [super init])) {
72 self.device = dev;
73 self.productName = (__bridge NSString *)IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDProductKey));
74 self.vendorId = [(__bridge NSNumber *)IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDVendorIDKey)) intValue];
75 self.productId = [(__bridge NSNumber *)IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDProductIDKey)) intValue];
76 self.children = ActionsForElement(dev, self);
77 }
78 return self;
79 }
80
81 - (NSString *)name {
82 return [NSString stringWithFormat:@"%@ #%d", productName, index];
83 }
84
85 - (id)base {
86 return nil;
87 }
88
89 - (NSString *)uid {
90 return [NSString stringWithFormat: @"%d:%d:%d", vendorId, productId, index];
91 }
92
93 - (JSAction *)findActionByCookie:(void *)cookie {
94 for (JSAction *child in children)
95 if (child.cookie == cookie)
96 return child;
97 return nil;
98 }
99
100 - (id)handlerForEvent:(IOHIDValueRef) value {
101 JSAction *mainAction = [self actionForEvent:value];
102 return [mainAction findSubActionForValue:value];
103 }
104
105 - (JSAction *)actionForEvent:(IOHIDValueRef)value {
106 IOHIDElementRef elt = IOHIDValueGetElement(value);
107 void *cookie = IOHIDElementGetCookie(elt);
108 return [self findActionByCookie:cookie];
109 }
110
111 @end