// Copyright 2009 University of Otago. All rights reserved.
//
-#import <Cocoa/Cocoa.h>
+#import <Foundation/Foundation.h>
+
@class Target;
+@class JSAction;
-@interface Config : NSObject {
- NSString *name;
- BOOL protect;
- NSMutableDictionary *entries;
-}
+@interface Config : NSObject
-@property(readwrite) BOOL protect;
-@property(readwrite, copy) NSString* name;
-@property(readonly) NSMutableDictionary* entries;
+@property (assign) BOOL protect;
+@property (copy) NSString *name;
+@property (readonly) NSMutableDictionary *entries;
--(void) setTarget:(Target*)target forAction:(id)jsa;
--(Target*) getTargetForAction: (id) jsa;
+- (void)setTarget:(Target *)target forAction:(JSAction *)jsa;
+- (Target *)getTargetForAction:(JSAction *)sa;
@end
// Created by Sam McCall on 4/05/09.
//
-@implementation Config
+#import "Config.h"
--(id) init {
- if(self=[super init]) {
- entries = [[NSMutableDictionary alloc] init];
- }
- return self;
-}
+@implementation Config
@synthesize protect, name, entries;
--(void) setTarget:(Target*)target forAction:(id)jsa {
- [entries setValue:target forKey: [jsa stringify]];
+- (id)init {
+ if ((self = [super init])) {
+ entries = [[NSMutableDictionary alloc] init];
+ }
+ return self;
}
--(Target*) getTargetForAction: (id) jsa {
- return entries[[jsa stringify]];
+
+- (void)setTarget:(Target *)target forAction:(JSAction *)jsa {
+ entries[[jsa stringify]] = target;
+}
+
+- (Target *)getTargetForAction:(JSAction *)jsa {
+ return entries[[jsa stringify]];
}
@end
// Copyright 2009 University of Otago. All rights reserved.
//
-#import <Cocoa/Cocoa.h>
-#import <IOKit/hid/IOHIDLib.h>
+#import <Foundation/Foundation.h>
+#import <IOKit/hid/IOHIDBase.h>
@interface JSAction : NSObject {
- int usage, index;
- void* cookie;
- NSArray *subActions;
id base;
NSString *name;
}
-@property(readwrite) int usage;
-@property(readwrite) void* cookie;
-@property(readonly) int index;
-@property(copy) NSArray* subActions;
-@property(readwrite, strong) id base;
-@property(copy) NSString* name;
-@property(readonly) BOOL active;
+@property (assign) void* cookie;
+@property (assign) int index;
+@property (copy) NSArray *subActions;
+@property (strong) id base;
+@property (copy) NSString *name;
+@property (readonly) BOOL active;
--(void) notifyEvent: (IOHIDValueRef) value;
--(NSString*) stringify;
--(NSArray*) subActions;
--(id) findSubActionForValue: (IOHIDValueRef) value;
+- (void)notifyEvent:(IOHIDValueRef)value;
+- (NSString *)stringify;
+- (id)findSubActionForValue:(IOHIDValueRef)value;
@end
// Created by Sam McCall on 4/05/09.
//
+#import "JSAction.h"
+
@implementation JSAction
-@synthesize usage, cookie, index, subActions, base, name;
+@synthesize cookie;
+@synthesize index;
+@synthesize subActions;
+@synthesize base;
+@synthesize name;
--(id) findSubActionForValue: (IOHIDValueRef) value {
- return NULL;
+- (id)findSubActionForValue:(IOHIDValueRef)value {
+ return NULL;
}
--(NSString*) stringify {
- return [[NSString alloc] initWithFormat: @"%@~%d",[base stringify],(int)cookie];
+- (NSString *)stringify {
+ return [NSString stringWithFormat: @"%@~%p", [base stringify], cookie];
}
--(void) notifyEvent: (IOHIDValueRef) value {
- [self doesNotRecognizeSelector:_cmd];
+
+- (void)notifyEvent:(IOHIDValueRef)value {
+ [self doesNotRecognizeSelector:_cmd];
}
--(BOOL) active {
- [self doesNotRecognizeSelector:_cmd];
- return NO;
+
+- (BOOL)active {
+ [self doesNotRecognizeSelector:_cmd];
+ return NO;
}
@end
//
#import <Cocoa/Cocoa.h>
-@class JSAction;
-@interface JSActionAnalog : JSAction {
- double offset, scale;
-}
+#import "JSAction.h"
-@property(readwrite) double offset;
-@property(readwrite) double scale;
+@interface JSActionAnalog : JSAction
-- (id) initWithIndex: (int)newIndex;
--(double) getRealValue: (int) value;
+@property (assign) float offset;
+@property (assign) float scale;
+
+- (id)initWithIndex:(int)newIndex offset:(float)offset scale:(float)scale;
+- (float)getRealValue:(int)value;
@end
// Created by Sam McCall on 5/05/09.
//
+// TODO: Dead zone should be configurable per-device.
+#define DEAD_ZONE 0.3
+
+#import "JSActionAnalog.h"
+
@implementation JSActionAnalog
-- (id) initWithIndex: (int)newIndex {
- if(self = [super init]) {
- subActions = @[[[SubAction alloc] initWithIndex: 0 name: @"Low" base: self],
- [[SubAction alloc] initWithIndex: 1 name: @"High" base: self],
- [[SubAction alloc] initWithIndex: 2 name: @"Analog" base: self]];
- index = newIndex;
- name = [[NSString alloc] initWithFormat: @"Axis %d", (index+1)];
- }
- return self;
-}
+@synthesize offset, scale;
--(id) findSubActionForValue: (IOHIDValueRef) value {
- if ([subActions[2] active]) {
- return subActions[2]; // TODO?
+- (id)initWithIndex:(int)newIndex offset:(float)offset_ scale:(float)scale_ {
+ if ((self = [super init])) {
+ self.subActions = @[[[SubAction alloc] initWithIndex:0 name:@"Low" base:self],
+ [[SubAction alloc] initWithIndex:1 name:@"High" base:self]];
+ self.index = newIndex;
+ self.offset = offset_;
+ self.scale = scale_;
+ self.name = [[NSString alloc] initWithFormat: @"Axis %d", self.index + 1];
}
-
- //Target* target = [[base->configsController currentConfig] getTargetForAction: [subActions objectAtIndex: 0]];
-
- int raw = IOHIDValueGetIntegerValue(value);
- double parsed = [self getRealValue: raw];
-
- if(parsed < -0.3) // fixed?!
- return subActions[0];
- else if(parsed > 0.3)
- return subActions[1];
- return NULL;
+ return self;
}
--(void) notifyEvent: (IOHIDValueRef) value {
- // Analog action is always active
- [subActions[2] setActive: true];
+- (id)findSubActionForValue:(IOHIDValueRef)value {
+ int raw = IOHIDValueGetIntegerValue(value);
+ float parsed = [self getRealValue:raw];
- int raw = IOHIDValueGetIntegerValue(value);
- double parsed = [self getRealValue: raw];
-
- [subActions[0] setActive: (parsed < -0.3)];
- [subActions[1] setActive: (parsed > 0.3)];
+ if (parsed < -DEAD_ZONE)
+ return self.subActions[0];
+ else if (parsed > DEAD_ZONE)
+ return self.subActions[1];
+ else
+ return nil;
}
--(double) getRealValue: (int)value {
- double parsed = offset + scale * value;
- return parsed;
+- (void)notifyEvent:(IOHIDValueRef)value {
+ int raw = IOHIDValueGetIntegerValue(value);
+ float parsed = [self getRealValue:raw];
+ [self.subActions[0] setActive:parsed < -DEAD_ZONE];
+ [self.subActions[1] setActive:parsed > DEAD_ZONE];
}
-@synthesize offset, scale;
+- (float)getRealValue:(int)value {
+ return offset + scale * value;
+}
@end
//
#import <Cocoa/Cocoa.h>
-@class JSAction;
-@interface JSActionButton : JSAction {
- int max;
- BOOL active;
-}
+#import "JSAction.h"
--(id)initWithIndex: (int)newIndex andName: (NSString*)newName;
-@property(readwrite) int max;
+@interface JSActionButton : JSAction
+
+- (id)initWithName:(NSString *)name idx:(int)idx max:(int)max;
+
+@property (assign) int max;
@end
// Created by Sam McCall on 5/05/09.
//
-@implementation JSActionButton
+@implementation JSActionButton {
+ BOOL active;
+}
-@synthesize max, active;
+@synthesize max;
+@synthesize active;
--(id)initWithIndex: (int)newIndex andName: (NSString *)newName {
- if(self= [ super init]) {
- subActions = NULL;
- index = newIndex;
- name = [[NSString alloc] initWithFormat: @"Button %d %@", (index+1), newName];
- }
- return self;
+- (id)initWithName:(NSString *)name_ idx:(int)idx max:(int)max_ {
+ if ((self = [super init])) {
+ self.index = idx;
+ self.max = max_;
+ if (name_.length)
+ self.name = [NSString stringWithFormat:@"Button %d - %@", self.index + 1, name_];
+ else
+ self.name = [NSString stringWithFormat:@"Button %d", self.index + 1];
+ }
+ return self;
}
--(id) findSubActionForValue: (IOHIDValueRef) val {
- if(IOHIDValueGetIntegerValue(val) == max)
- return self;
- return NULL;
+- (id)findSubActionForValue:(IOHIDValueRef)val {
+ return (IOHIDValueGetIntegerValue(val) == max) ? self : nil;
}
--(void) notifyEvent: (IOHIDValueRef) value {
- active = IOHIDValueGetIntegerValue(value) == max;
+- (void)notifyEvent:(IOHIDValueRef)value {
+ active = IOHIDValueGetIntegerValue(value) == max;
}
@end
//
#import <Cocoa/Cocoa.h>
-@class JSAction;
-@interface JSActionHat : JSAction {
-
-}
+#import "JSAction.h"
+
+@interface JSActionHat : JSAction
@end
//
static BOOL active_eightway[36] = {
-NO, NO, NO, NO , // center
-YES, NO, NO, NO , // N
-YES, NO, NO, YES, // NE
-NO, NO, NO, YES, // E
-NO, YES, NO, YES, // SE
-NO, YES, NO, NO , // S
-NO, YES, YES, NO , // SW
-NO, NO, YES, NO , // W
-YES, NO, YES, NO , // NW
+ NO, NO, NO, NO , // center
+ YES, NO, NO, NO , // N
+ YES, NO, NO, YES, // NE
+ NO, NO, NO, YES, // E
+ NO, YES, NO, YES, // SE
+ NO, YES, NO, NO , // S
+ NO, YES, YES, NO , // SW
+ NO, NO, YES, NO , // W
+ YES, NO, YES, NO , // NW
};
+
static BOOL active_fourway[20] = {
-NO, NO, NO, NO , // center
-YES, NO, NO, NO , // N
-NO, NO, NO, YES, // E
-NO, YES, NO, NO , // S
-NO, NO, YES, NO , // W
+ NO, NO, NO, NO , // center
+ YES, NO, NO, NO , // N
+ NO, NO, NO, YES, // E
+ NO, YES, NO, NO , // S
+ NO, NO, YES, NO , // W
};
@implementation JSActionHat
-- (id) init {
- if(self = [super init]) {
- subActions = @[[[SubAction alloc] initWithIndex: 0 name: @"Up" base: self],
- [[SubAction alloc] initWithIndex: 1 name: @"Down" base: self],
- [[SubAction alloc] initWithIndex: 2 name: @"Left" base: self],
- [[SubAction alloc] initWithIndex: 3 name: @"Right" base: self]];
- name = @"Hat switch";
- }
- return self;
+- (id)init {
+ if ((self = [super init])) {
+ self.subActions = @[[[SubAction alloc] initWithIndex: 0 name: @"Up" base: self],
+ [[SubAction alloc] initWithIndex: 1 name: @"Down" base: self],
+ [[SubAction alloc] initWithIndex: 2 name: @"Left" base: self],
+ [[SubAction alloc] initWithIndex: 3 name: @"Right" base: self]];
+ // TODO(jfw): Should have an indexed name, like everything else.
+ self.name = @"Hat switch";
+ }
+ return self;
}
--(id) findSubActionForValue: (IOHIDValueRef) value {
- int parsed = IOHIDValueGetIntegerValue(value);
- if(IOHIDElementGetLogicalMax(IOHIDValueGetElement(value)) == 7) {
- // 8-way
- switch(parsed) {
- case 0: return subActions[0];
- case 4: return subActions[1];
- case 6: return subActions[2];
- case 2: return subActions[3];
- }
- } else if(IOHIDElementGetLogicalMax(IOHIDValueGetElement(value)) == 8) {
- // 8-way
- switch(parsed) {
- case 1: return subActions[0];
- case 5: return subActions[1];
- case 7: return subActions[2];
- case 3: return subActions[3];
- }
- } else if(IOHIDElementGetLogicalMax(IOHIDValueGetElement(value)) == 3) {
- // 4-way
- switch(parsed) {
- case 0: return subActions[0];
- case 2: return subActions[1];
- case 3: return subActions[2];
- case 1: return subActions[3];
- }
- } else if(IOHIDElementGetLogicalMax(IOHIDValueGetElement(value)) == 4) {
- // 4-way
- switch(parsed) {
- case 1: return subActions[0];
- case 3: return subActions[1];
- case 4: return subActions[2];
- case 2: return subActions[3];
- }
- }
- return NULL;
+- (id)findSubActionForValue:(IOHIDValueRef)value {
+ int parsed = IOHIDValueGetIntegerValue(value);
+ switch (IOHIDElementGetLogicalMax(IOHIDValueGetElement(value))) {
+ case 7: // 8-way switch, 0-7.
+ switch (parsed) {
+ case 0: return self.subActions[0];
+ case 4: return self.subActions[1];
+ case 6: return self.subActions[2];
+ case 2: return self.subActions[3];
+ default: return nil;
+ }
+ case 8: // 8-way switch, 1-8 (neutral 0).
+ switch (parsed) {
+ case 1: return self.subActions[0];
+ case 5: return self.subActions[1];
+ case 7: return self.subActions[2];
+ case 3: return self.subActions[3];
+ default: return nil;
+ }
+ case 3: // 4-way switch, 0-3.
+ switch (parsed) {
+ case 0: return self.subActions[0];
+ case 2: return self.subActions[1];
+ case 3: return self.subActions[2];
+ case 1: return self.subActions[3];
+ default: return nil;
+ }
+ case 4: // 4-way switch, 1-4 (neutral 0).
+ switch (parsed) {
+ case 1: return self.subActions[0];
+ case 3: return self.subActions[1];
+ case 4: return self.subActions[2];
+ case 2: return self.subActions[3];
+ default: return nil;
+ }
+ default:
+ return nil;
+ }
}
--(void) notifyEvent: (IOHIDValueRef) value {
- int parsed = IOHIDValueGetIntegerValue(value);
- int size = IOHIDElementGetLogicalMax(IOHIDValueGetElement(value));
- if(size == 7 || size == 3) {
- parsed++;
- size++;
- }
- BOOL* activeSubactions = (size == 8) ? active_eightway : active_fourway;
- for(int i=0; i<4; i++)
- [subActions[i] setActive: activeSubactions[parsed * 4 + i]];
+- (void)notifyEvent:(IOHIDValueRef)value {
+ int parsed = IOHIDValueGetIntegerValue(value);
+ int size = IOHIDElementGetLogicalMax(IOHIDValueGetElement(value));
+ // Skip first row in table if 0 is not neutral.
+ if (size & 1) {
+ parsed++;
+ size++;
+ }
+ BOOL *activeSubactions = (size == 8) ? active_eightway : active_fourway;
+ for (int i = 0; i < 4; i++)
+ [self.subActions[i] setActive:activeSubactions[parsed * 4 + i]];
}
@end
// Copyright 2009 University of Otago. All rights reserved.
//
-#import <Cocoa/Cocoa.h>
+#import <Foundation/Foundation.h>
+#import <IOKit/hid/IOHIDBase.h>
@class JSAction;
// Created by Sam McCall on 4/05/09.
//
+#import "Joystick.h"
+
static NSArray *ActionsForElement(IOHIDDeviceRef device, id base) {
CFArrayRef elements = IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);
NSMutableArray *children = [NSMutableArray arrayWithCapacity:CFArrayGetCount(elements)];
int min = IOHIDElementGetPhysicalMin(element);
CFStringRef elName = IOHIDElementGetName(element);
- JSAction *action = NULL;
+ JSAction *action = nil;
- if(!(type == kIOHIDElementTypeInput_Misc
- || type == kIOHIDElementTypeInput_Axis
- || type == kIOHIDElementTypeInput_Button))
- continue;
+ 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:(__bridge NSString *)elName];
- [(JSActionButton*)action setMax:max];
+ 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 {
- if (usage >= kHIDUsage_GD_X && usage <= kHIDUsage_GD_Rz) {
- action = [[JSActionAnalog alloc] initWithIndex: axes++];
- [(JSActionAnalog*)action setOffset:(double)-1.0];
- [(JSActionAnalog*)action setScale:(double)2.0/(max - min)];
- } else
- continue;
+ continue;
}
- [action setBase:base];
- [action setUsage:usage];
- [action setCookie:IOHIDElementGetCookie(element)];
+ // TODO(jfw): Should be moved into better constructors.
+ action.base = base;
+ action.cookie = IOHIDElementGetCookie(element);
[children addObject:action];
}
return children;
#import <Cocoa/Cocoa.h>
#import <IOKit/hid/IOHIDLib.h>
+
@class Joystick;
+@class JSAction;
@class ConfigsController;
-
@class TargetController;
@interface JoystickController : NSObject {
-(void) setup;
-(Joystick*) findJoystickByRef: (IOHIDDeviceRef) device;
-@property(strong, readonly) id selectedAction;
-@property(readonly) NSMutableArray *joysticks;
-@property(readonly) NSMutableArray *runningTargets;
-@property(readwrite) BOOL frontWindowOnly;
+@property (readonly) JSAction *selectedAction;
+@property (readonly) NSMutableArray *joysticks;
+@property (readonly) NSMutableArray *runningTargets;
+@property (readwrite) BOOL frontWindowOnly;
@end
// Created by Sam McCall on 4/05/09.
//
-#import "CoreFoundation/CoreFoundation.h"
+#import "JoystickController.h"
@implementation JoystickController
CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode);
}
--(id) determineSelectedAction {
- id item = [outlineView itemAtRow: [outlineView selectedRow]];
- if(!item)
- return NULL;
- if([item isKindOfClass: [JSAction class]] && [item subActions] != NULL)
- return NULL;
- if([item isKindOfClass: [Joystick class]])
- return NULL;
- return item;
+- (JSAction *)selectedAction {
+ id item = [outlineView itemAtRow:outlineView.selectedRow];
+ if ([item isKindOfClass: [JSAction class]] && ![item subActions])
+ return item;
+ else
+ return nil;
}
/* outline view */
- (void)outlineViewSelectionDidChange: (NSNotification*) notification {
[targetController reset];
- selectedAction = [self determineSelectedAction];
[targetController load];
- if(programmaticallySelecting)
+ if (programmaticallySelecting)
[targetController focusKey];
programmaticallySelecting = NO;
}
//
#import <Cocoa/Cocoa.h>
-@class JSAction;
-@interface SubAction : NSObject {
- JSAction *base;
- NSString *name;
- int index;
- BOOL active;
-}
+#import "JSAction.h"
--(id) initWithIndex:(int)newIndex name: (NSString*)newName base: (JSAction*)newBase;
+@interface SubAction : JSAction
-@property(readwrite, strong) JSAction* base;
-@property(readwrite, copy) NSString* name;
-@property(readwrite) int index;
-@property(readwrite) BOOL active;
+- (id)initWithIndex:(int)newIndex name:(NSString *)newName base:(JSAction *)newBase;
+
+@property (assign) BOOL active;
@end
// Created by Sam McCall on 5/05/09.
//
-@implementation SubAction
+// TODO(jfw): This class is useless and can just be replaced w/ JSAction probably.
-@synthesize base, name, index, active;
+#import "SubAction.h"
--(id) initWithIndex:(int)newIndex name: (NSString*)newName base: (JSAction*)newBase {
- if(self = [super init]) {
- [self setName: newName];
- [self setBase: newBase];
- [self setIndex: newIndex];
+@implementation SubAction {
+ BOOL active;
+}
+
+@synthesize active;
+
+- (id)initWithIndex:(int)newIndex name:(NSString *)newName base:(JSAction *)newBase {
+ if ((self = [super init])) {
+ self.name = newName;
+ self.base = newBase;
+ self.index = newIndex;
}
return self;
}
-(NSString*) stringify {
- return [[NSString alloc] initWithFormat: @"%@~%d", [base stringify], index];
+ return [[NSString alloc] initWithFormat: @"%@~%d", [base stringify], self.index];
}
@end