'Convert to Modern Objective-C Syntax'...
[enjoyable.git] / JoystickController.m
index b510848..6b748df 100644 (file)
@@ -5,21 +5,25 @@
 //  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 {
        for(int i=0; i<[joysticks count]; i++) {
-               [[joysticks objectAtIndex:i] invalidate];
+               [joysticks[i] invalidate];
        }
        IOHIDManagerClose(hidManager, kIOHIDOptionsTypeNone);
        CFRelease(hidManager);
@@ -29,8 +33,8 @@
 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)] = [NSNumber numberWithInt: inUsagePage];
+       dict[(NSString*)CFSTR(kIOHIDDeviceUsageKey)] = [NSNumber numberWithInt: inUsage];
        return dict;
 } 
 
@@ -40,12 +44,28 @@ static NSMutableDictionary* create_criterion( UInt32 inUsagePage, UInt32 inUsage
        [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 = (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;
        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)
@@ -54,15 +74,34 @@ void input_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDVal
                [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
@@ -82,7 +121,7 @@ int findAvailableIndex(id list, Joystick* js) {
        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;
@@ -109,10 +148,10 @@ void add_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDDevic
 }
        
 -(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) {
@@ -130,15 +169,12 @@ void remove_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDDe
 
 -(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];
+         create_criterion(kHIDPage_GenericDesktop, kHIDUsage_GD_MultiAxisController)];
        
        IOHIDManagerSetDeviceMatchingMultiple(hidManager, (CFArrayRef)criteria);
-       
+    
        IOHIDManagerScheduleWithRunLoop( hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode );
        IOReturn tIOReturn = IOHIDManagerOpen( hidManager, kIOHIDOptionsTypeNone );
        (void)tIOReturn;
@@ -147,6 +183,17 @@ void remove_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDDe
        IOHIDManagerRegisterDeviceRemovalCallback(hidManager, remove_callback, (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, (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 {
@@ -184,13 +231,13 @@ void remove_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDDe
 
 - (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;
 }