From e68c19b5923618b763543c74bf8dd6f85d4d323e Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Wed, 27 Feb 2013 00:31:03 +0100 Subject: [PATCH] Refactor Actions. SubAction is a (mostly) proper JSAction. JSActions have (more) proper constructors. --- Config.h | 20 +++--- Config.m | 25 ++++---- JSAction.h | 27 ++++---- JSAction.m | 28 ++++++--- JSActionAnalog.h | 15 +++-- JSActionAnalog.m | 68 ++++++++++---------- JSActionButton.h | 13 ++-- JSActionButton.m | 34 +++++----- JSActionHat.h | 7 +-- JSActionHat.m | 143 ++++++++++++++++++++++--------------------- Joystick.h | 3 +- Joystick.m | 35 ++++++----- JoystickController.h | 11 ++-- JoystickController.m | 20 +++--- SubAction.h | 17 ++--- SubAction.m | 22 ++++--- 16 files changed, 247 insertions(+), 241 deletions(-) diff --git a/Config.h b/Config.h index 1120ede..d118262 100644 --- a/Config.h +++ b/Config.h @@ -6,20 +6,18 @@ // Copyright 2009 University of Otago. All rights reserved. // -#import +#import + @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 diff --git a/Config.m b/Config.m index 27ca4f0..f62c40f 100644 --- a/Config.m +++ b/Config.m @@ -5,22 +5,25 @@ // 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 diff --git a/JSAction.h b/JSAction.h index 1e60cf2..9de4696 100644 --- a/JSAction.h +++ b/JSAction.h @@ -6,28 +6,23 @@ // Copyright 2009 University of Otago. All rights reserved. // -#import -#import +#import +#import @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 diff --git a/JSAction.m b/JSAction.m index a0fab80..6bc1529 100644 --- a/JSAction.m +++ b/JSAction.m @@ -5,23 +5,31 @@ // 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 diff --git a/JSActionAnalog.h b/JSActionAnalog.h index f1276d5..f351a4a 100644 --- a/JSActionAnalog.h +++ b/JSActionAnalog.h @@ -7,16 +7,15 @@ // #import -@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 diff --git a/JSActionAnalog.m b/JSActionAnalog.m index 027bd5d..e7d6eba 100644 --- a/JSActionAnalog.m +++ b/JSActionAnalog.m @@ -5,53 +5,49 @@ // 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 diff --git a/JSActionButton.h b/JSActionButton.h index 4720b73..5a9a4c0 100644 --- a/JSActionButton.h +++ b/JSActionButton.h @@ -7,14 +7,13 @@ // #import -@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 diff --git a/JSActionButton.m b/JSActionButton.m index 98a186a..c358c8d 100644 --- a/JSActionButton.m +++ b/JSActionButton.m @@ -5,27 +5,31 @@ // 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 diff --git a/JSActionHat.h b/JSActionHat.h index bab893f..5a1fa22 100644 --- a/JSActionHat.h +++ b/JSActionHat.h @@ -7,10 +7,9 @@ // #import -@class JSAction; -@interface JSActionHat : JSAction { - -} +#import "JSAction.h" + +@interface JSActionHat : JSAction @end diff --git a/JSActionHat.m b/JSActionHat.m index 13abcda..4e11b49 100644 --- a/JSActionHat.m +++ b/JSActionHat.m @@ -6,85 +6,90 @@ // 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 diff --git a/Joystick.h b/Joystick.h index 6d38ce1..04c5686 100644 --- a/Joystick.h +++ b/Joystick.h @@ -6,7 +6,8 @@ // Copyright 2009 University of Otago. All rights reserved. // -#import +#import +#import @class JSAction; diff --git a/Joystick.m b/Joystick.m index 9f3c826..a65304e 100644 --- a/Joystick.m +++ b/Joystick.m @@ -5,6 +5,8 @@ // 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)]; @@ -21,30 +23,31 @@ static NSArray *ActionsForElement(IOHIDDeviceRef device, id base) { 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; diff --git a/JoystickController.h b/JoystickController.h index f0530dc..c698c17 100644 --- a/JoystickController.h +++ b/JoystickController.h @@ -8,9 +8,10 @@ #import #import + @class Joystick; +@class JSAction; @class ConfigsController; - @class TargetController; @interface JoystickController : NSObject { @@ -31,9 +32,9 @@ -(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 diff --git a/JoystickController.m b/JoystickController.m index 3895328..54734a8 100644 --- a/JoystickController.m +++ b/JoystickController.m @@ -5,7 +5,7 @@ // Created by Sam McCall on 4/05/09. // -#import "CoreFoundation/CoreFoundation.h" +#import "JoystickController.h" @implementation JoystickController @@ -174,15 +174,12 @@ static void remove_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDD 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 */ @@ -227,9 +224,8 @@ static void remove_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDD - (void)outlineViewSelectionDidChange: (NSNotification*) notification { [targetController reset]; - selectedAction = [self determineSelectedAction]; [targetController load]; - if(programmaticallySelecting) + if (programmaticallySelecting) [targetController focusKey]; programmaticallySelecting = NO; } diff --git a/SubAction.h b/SubAction.h index d09fa3a..51a8509 100644 --- a/SubAction.h +++ b/SubAction.h @@ -7,20 +7,13 @@ // #import -@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 diff --git a/SubAction.m b/SubAction.m index cfca78b..07011ca 100644 --- a/SubAction.m +++ b/SubAction.m @@ -5,21 +5,27 @@ // 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 -- 2.30.2