// Created by Sam McCall on 4/05/09.
//
+#import "CoreFoundation/CoreFoundation.h"
+
@implementation JoystickController
-@synthesize joysticks, selectedAction;
+@synthesize joysticks, runningTargets, selectedAction, frontWindowOnly;
-(id) init {
if(self=[super init]) {
joysticks = [[NSMutableArray alloc]init];
+ runningTargets = [[NSMutableArray alloc]init];
programmaticallySelecting = NO;
+ mouseLoc.x = mouseLoc.y = 0;
}
return self;
}
--(void) finalize {
+-(void) dealloc {
for(int i=0; i<[joysticks count]; i++) {
- [[joysticks objectAtIndex:i] invalidate];
+ [joysticks[i] invalidate];
}
IOHIDManagerClose(hidManager, kIOHIDOptionsTypeNone);
CFRelease(hidManager);
- [super finalize];
}
static NSMutableDictionary* create_criterion( UInt32 inUsagePage, UInt32 inUsage )
{
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
- [dict setObject: [NSNumber numberWithInt: inUsagePage] forKey: (NSString*)CFSTR(kIOHIDDeviceUsagePageKey)];
- [dict setObject: [NSNumber numberWithInt: inUsage] forKey: (NSString*)CFSTR(kIOHIDDeviceUsageKey)];
+ dict[(NSString*)CFSTR(kIOHIDDeviceUsagePageKey)] = @(inUsagePage);
+ dict[(NSString*)CFSTR(kIOHIDDeviceUsageKey)] = @(inUsage);
return dict;
}
[outlineView expandItem: handler];
}
+BOOL objInArray(NSMutableArray *array, id object) {
+ for (id o in array) {
+ if (o == object)
+ return true;
+ }
+ return false;
+}
+
+void timer_callback(CFRunLoopTimerRef timer, void *ctx) {
+ JoystickController *jc = (__bridge JoystickController *)ctx;
+ jc->mouseLoc = [NSEvent mouseLocation];
+ for (Target *target in [jc runningTargets]) {
+ [target update: jc];
+ }
+}
+
void input_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDValueRef value) {
- JoystickController* self = (JoystickController*)inContext;
+ JoystickController* self = (__bridge JoystickController*)inContext;
IOHIDDeviceRef device = IOHIDQueueGetDevice((IOHIDQueueRef) inSender);
Joystick* js = [self findJoystickByRef: device];
- if([[[NSApplication sharedApplication] delegate] active]) {
+ if([(ApplicationController *)[[NSApplication sharedApplication] delegate] active]) {
// for reals
JSAction* mainAction = [js actionForEvent: value];
if(!mainAction)
[mainAction notifyEvent: value];
NSArray* subactions = [mainAction subActions];
if(!subactions)
- subactions = [NSArray arrayWithObject:mainAction];
+ subactions = @[mainAction];
for(id subaction in subactions) {
Target* target = [[self->configsController currentConfig] getTargetForAction:subaction];
if(!target)
continue;
/* target application? doesn't seem to be any need since we are only active when it's in front */
/* might be required for some strange actions */
- [target setRunning: [subaction active]];
- [target setInputValue: IOHIDValueGetIntegerValue(value)];
+ if ([target running] != [subaction active]) {
+ if ([subaction active]) {
+ [target trigger: self];
+ }
+ else {
+ [target untrigger: self];
+ }
+ [target setRunning: [subaction active]];
+ }
+
+ if ([mainAction isKindOfClass: [JSActionAnalog class]]) {
+ double realValue = [(JSActionAnalog*)mainAction getRealValue: IOHIDValueGetIntegerValue(value)];
+ [target setInputValue: realValue];
+
+ // Add to list of running targets
+ if ([target isContinuous] && [target running]) {
+ if (!objInArray([self runningTargets], target)) {
+ [[self runningTargets] addObject: target];
+ }
+ }
+ }
}
} else if([[NSApplication sharedApplication] isActive] && [[[NSApplication sharedApplication]mainWindow]isVisible]) {
// joysticks not active, use it to select stuff
for(int index=0;;index++) {
available = YES;
for(int i=0; i<[list count]; i++) {
- js2 = [list objectAtIndex: i];
+ js2 = list[i];
if([js2 vendorId] == [js vendorId] && [js2 productId] == [js productId] && [js index] == index) {
available = NO;
break;
}
void add_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDDeviceRef device) {
- JoystickController* self = (JoystickController*)inContext;
+ JoystickController* self = (__bridge JoystickController*)inContext;
IOHIDDeviceOpen(device, kIOHIDOptionsTypeNone);
- IOHIDDeviceRegisterInputValueCallback(device, input_callback, (void*) self);
+ IOHIDDeviceRegisterInputValueCallback(device, input_callback, (void*) CFBridgingRetain(self));
Joystick *js = [[Joystick alloc] initWithDevice: device];
[js setIndex: findAvailableIndex([self joysticks], js)];
}
-(Joystick*) findJoystickByRef: (IOHIDDeviceRef) device {
- for(int i=0; i<[joysticks count]; i++)
- if([[joysticks objectAtIndex:i] device] == device)
- return [joysticks objectAtIndex:i];
- return NULL;
+ for (Joystick *js in joysticks)
+ if (js.device == device)
+ return js;
+ return nil;
}
void remove_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDDeviceRef device) {
- JoystickController* self = (JoystickController*)inContext;
+ JoystickController* self = CFBridgingRelease(inContext);
Joystick* match = [self findJoystickByRef: device];
if(!match)
-(void) setup {
hidManager = IOHIDManagerCreate( kCFAllocatorDefault, kIOHIDOptionsTypeNone);
- NSArray *criteria = [NSArray arrayWithObjects:
- create_criterion(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick),
+ NSArray *criteria = @[create_criterion(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick),
create_criterion(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad),
- create_criterion(kHIDPage_GenericDesktop, kHIDUsage_GD_MultiAxisController),
- create_criterion(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard),
- nil];
-
- IOHIDManagerSetDeviceMatchingMultiple(hidManager, (CFArrayRef)criteria);
+ create_criterion(kHIDPage_GenericDesktop, kHIDUsage_GD_MultiAxisController)];
+ IOHIDManagerSetDeviceMatchingMultiple(hidManager, (CFArrayRef)CFBridgingRetain(criteria));
+
IOHIDManagerScheduleWithRunLoop( hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode );
IOReturn tIOReturn = IOHIDManagerOpen( hidManager, kIOHIDOptionsTypeNone );
(void)tIOReturn;
- IOHIDManagerRegisterDeviceMatchingCallback( hidManager, add_callback, (void*)self );
- IOHIDManagerRegisterDeviceRemovalCallback(hidManager, remove_callback, (void*) self);
+ IOHIDManagerRegisterDeviceMatchingCallback( hidManager, add_callback, (__bridge void*)self );
+ IOHIDManagerRegisterDeviceRemovalCallback(hidManager, remove_callback, (__bridge void*) self);
// IOHIDManagerRegisterInputValueCallback(hidManager, input_callback, (void*)self);
// register individually so we can find the device more easily
+
+
+
+ // Setup timer for continuous targets
+ CFRunLoopTimerContext ctx = {
+ 0, (__bridge void*)self, NULL, NULL, NULL
+ };
+ CFRunLoopTimerRef timer = CFRunLoopTimerCreate(kCFAllocatorDefault,
+ CFAbsoluteTimeGetCurrent(), 1.0/80.0,
+ 0, 0, timer_callback, &ctx);
+ CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode);
}
-(id) determineSelectedAction {
- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item {
if(item == nil)
- return [joysticks objectAtIndex: index];
+ return joysticks[index];
if([item isKindOfClass: [Joystick class]])
- return [[item children] objectAtIndex: index];
+ return [item children][index];
if([item isKindOfClass: [JSAction class]])
- return [[item subActions] objectAtIndex:index];
+ return [item subActions][index];
return NULL;
}