From: Joe Wreschnig Date: Wed, 20 Mar 2013 19:51:30 +0000 (+0100) Subject: Merge device and mapping controllers into NJInputController. X-Git-Tag: version-1.1~8 X-Git-Url: https://git.yukkurigames.com/?p=enjoyable.git;a=commitdiff_plain;h=93d9951d6bd16b37e88b8fb6c38bc4afd6c9401e Merge device and mapping controllers into NJInputController. --- diff --git a/Classes/EnjoyableApplicationDelegate.h b/Classes/EnjoyableApplicationDelegate.h index 3b1f2f4..ddc6acf 100644 --- a/Classes/EnjoyableApplicationDelegate.h +++ b/Classes/EnjoyableApplicationDelegate.h @@ -12,17 +12,16 @@ #import "NJMappingsViewController.h" #import "NJDeviceViewController.h" #import "NJOutputController.h" -#import "NJDeviceController.h" +#import "NJInputController.h" @interface EnjoyableApplicationDelegate : NSObject -@property (nonatomic, strong) IBOutlet NJMappingsController *mappingsController; -@property (nonatomic, strong) IBOutlet NJDeviceController *deviceController; +@property (nonatomic, strong) IBOutlet NJInputController *inputController; @property (nonatomic, strong) IBOutlet NJOutputController *outputController; @property (nonatomic, strong) IBOutlet NJMappingsViewController *mvc; @property (nonatomic, strong) IBOutlet NJDeviceViewController *dvc; diff --git a/Classes/EnjoyableApplicationDelegate.m b/Classes/EnjoyableApplicationDelegate.m index 7646363..96aa8dd 100644 --- a/Classes/EnjoyableApplicationDelegate.m +++ b/Classes/EnjoyableApplicationDelegate.m @@ -10,7 +10,7 @@ #import "EnjoyableApplicationDelegate.h" #import "NJMapping.h" -#import "NJMappingsController.h" +#import "NJInput.h" #import "NJEvents.h" @implementation EnjoyableApplicationDelegate { @@ -20,7 +20,7 @@ - (void)didSwitchApplication:(NSNotification *)note { NSRunningApplication *activeApp = note.userInfo[NSWorkspaceApplicationKey]; if (activeApp) - [self.mappingsController activateMappingForProcess:activeApp]; + [self.inputController activateMappingForProcess:activeApp]; } - (void)applicationWillFinishLaunching:(NSNotification *)notification { @@ -40,11 +40,11 @@ name:NJEventSimulationStopped object:nil]; - [self.mappingsController load]; + [self.inputController load]; [self.mvc.mappingList reloadData]; [self.mvc changedActiveMappingToIndex: - [self.mappingsController indexOfMapping: - self.mappingsController.currentMapping]]; + [self.inputController indexOfMapping: + self.inputController.currentMapping]]; statusItem = [NSStatusBar.systemStatusBar statusItemWithLength:36]; statusItem.image = [NSImage imageNamed:@"Status Menu Icon Disabled"]; @@ -148,16 +148,16 @@ NSURL *URL = [NSURL fileURLWithPath:filename]; NJMapping *mapping = [NJMapping mappingWithContentsOfURL:URL error:&error]; - if ([[self.mappingsController mappingForKey:mapping.name] hasConflictWith:mapping]) { - [self promptForMapping:mapping atIndex:self.mappingsController.mappings.count]; - } else if ([self.mappingsController mappingForKey:mapping.name]) { - [[self.mappingsController mappingForKey:mapping.name] mergeEntriesFrom:mapping]; + if ([[self.inputController mappingForKey:mapping.name] hasConflictWith:mapping]) { + [self promptForMapping:mapping atIndex:self.inputController.mappings.count]; + } else if ([self.inputController mappingForKey:mapping.name]) { + [[self.inputController mappingForKey:mapping.name] mergeEntriesFrom:mapping]; } else if (mapping) { [self.mvc beginUpdates]; - [self.mappingsController addMapping:mapping]; - [self.mvc addedMappingAtIndex:self.mappingsController.mappings.count - 1 startEditing:NO]; + [self.inputController addMapping:mapping]; + [self.mvc addedMappingAtIndex:self.inputController.mappings.count - 1 startEditing:NO]; [self.mvc endUpdates]; - [self.mappingsController activateMapping:mapping]; + [self.inputController activateMapping:mapping]; } else { [self.window presentError:error modalForWindow:self.window @@ -169,7 +169,7 @@ } - (void)mappingWasChosen:(NJMapping *)mapping { - [self.mappingsController activateMapping:mapping]; + [self.inputController activateMapping:mapping]; } - (void)mappingListShouldOpen { @@ -229,12 +229,12 @@ NSError *error; NJMapping *mapping = [NJMapping mappingWithContentsOfURL:panel.URL error:&error]; - if ([[self.mappingsController mappingForKey:mapping.name] hasConflictWith:mapping]) { - [self promptForMapping:mapping atIndex:self.mappingsController.mappings.count]; - } else if ([self.mappingsController mappingForKey:mapping.name]) { - [[self.mappingsController mappingForKey:mapping.name] mergeEntriesFrom:mapping]; + if ([[self.inputController mappingForKey:mapping.name] hasConflictWith:mapping]) { + [self promptForMapping:mapping atIndex:self.inputController.mappings.count]; + } else if ([self.inputController mappingForKey:mapping.name]) { + [[self.inputController mappingForKey:mapping.name] mergeEntriesFrom:mapping]; } else if (mapping) { - [self.mappingsController addMapping:mapping]; + [self.inputController addMapping:mapping]; } else { [self.window presentError:error modalForWindow:self.window @@ -249,7 +249,7 @@ - (void)exportMappingClicked:(id)sender { NSSavePanel *panel = [NSSavePanel savePanel]; panel.allowedFileTypes = @[ @"enjoyable" ]; - NJMapping *mapping = self.mappingsController.currentMapping; + NJMapping *mapping = self.inputController.currentMapping; panel.nameFieldStringValue = [mapping.name stringByFixingPathComponent]; [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) { @@ -277,15 +277,15 @@ [alert.window orderOut:nil]; switch (returnCode) { case NSAlertFirstButtonReturn: // Merge - [self.mappingsController mergeMapping:newMapping intoMapping:oldMapping]; - [self.mappingsController activateMapping:oldMapping]; + [self.inputController mergeMapping:newMapping intoMapping:oldMapping]; + [self.inputController activateMapping:oldMapping]; break; case NSAlertThirdButtonReturn: // New Mapping [self.mvc beginUpdates]; - [self.mappingsController addMapping:newMapping]; + [self.inputController addMapping:newMapping]; [self.mvc addedMappingAtIndex:idx startEditing:YES]; [self.mvc endUpdates]; - [self.mappingsController activateMapping:newMapping]; + [self.inputController activateMapping:newMapping]; break; default: // Cancel, other. break; @@ -293,7 +293,7 @@ } - (void)promptForMapping:(NJMapping *)mapping atIndex:(NSInteger)idx { - NJMapping *mergeInto = [self.mappingsController mappingForKey:mapping.name]; + NJMapping *mergeInto = [self.inputController mappingForKey:mapping.name]; NSAlert *conflictAlert = [[NSAlert alloc] init]; conflictAlert.messageText = NSLocalizedString(@"import conflict prompt", @"Title of import conflict alert"); conflictAlert.informativeText = @@ -311,18 +311,18 @@ } - (NSInteger)numberOfMappings:(NJMappingsViewController *)mvc { - return self.mappingsController.mappings.count; + return self.inputController.mappings.count; } - (NJMapping *)mappingsViewController:(NJMappingsViewController *)mvc mappingForIndex:(NSUInteger)idx { - return self.mappingsController.mappings[idx]; + return self.inputController.mappings[idx]; } - (void)mappingsViewController:(NJMappingsViewController *)mvc renameMappingAtIndex:(NSInteger)index toName:(NSString *)name { - [self.mappingsController renameMapping:self.mappingsController.mappings[index] + [self.inputController renameMapping:self.inputController.mappings[index] to:name]; } @@ -330,7 +330,7 @@ canMoveMappingFromIndex:(NSInteger)fromIdx toIndex:(NSInteger)toIdx { return fromIdx != toIdx && fromIdx != 0 && toIdx != 0 - && toIdx < (NSInteger)self.mappingsController.mappings.count; + && toIdx < (NSInteger)self.inputController.mappings.count; } - (void)mappingsViewController:(NJMappingsViewController *)mvc @@ -338,7 +338,7 @@ toIndex:(NSInteger)toIdx { [mvc beginUpdates]; [mvc.mappingList moveRowAtIndex:fromIdx toIndex:toIdx]; - [self.mappingsController moveMoveMappingFromIndex:fromIdx toIndex:toIdx]; + [self.inputController moveMoveMappingFromIndex:fromIdx toIndex:toIdx]; [mvc endUpdates]; } @@ -351,7 +351,7 @@ removeMappingAtIndex:(NSInteger)idx { [mvc beginUpdates]; [mvc removedMappingAtIndex:idx]; - [self.mappingsController removeMappingAtIndex:idx]; + [self.inputController removeMappingAtIndex:idx]; [mvc endUpdates]; } @@ -361,14 +361,14 @@ error:(NSError **)error { NJMapping *mapping = [NJMapping mappingWithContentsOfURL:url error:error]; - if ([[self.mappingsController mappingForKey:mapping.name] hasConflictWith:mapping]) { + if ([[self.inputController mappingForKey:mapping.name] hasConflictWith:mapping]) { [self promptForMapping:mapping atIndex:index]; - } else if ([self.mappingsController mappingForKey:mapping.name]) { - [[self.mappingsController mappingForKey:mapping.name] mergeEntriesFrom:mapping]; + } else if ([self.inputController mappingForKey:mapping.name]) { + [[self.inputController mappingForKey:mapping.name] mergeEntriesFrom:mapping]; } else if (mapping) { [self.mvc beginUpdates]; [self.mvc addedMappingAtIndex:index startEditing:NO]; - [self.mappingsController insertMapping:mapping atIndex:index]; + [self.inputController insertMapping:mapping atIndex:index]; [self.mvc endUpdates]; } return !!mapping; @@ -377,20 +377,20 @@ - (void)mappingsViewController:(NJMappingsViewController *)mvc addMapping:(NJMapping *)mapping { [mvc beginUpdates]; - [mvc addedMappingAtIndex:self.mappingsController.mappings.count startEditing:YES]; - [self.mappingsController addMapping:mapping]; + [mvc addedMappingAtIndex:self.inputController.mappings.count startEditing:YES]; + [self.inputController addMapping:mapping]; [mvc endUpdates]; - [self.mappingsController activateMapping:mapping]; + [self.inputController activateMapping:mapping]; } - (void)mappingsViewController:(NJMappingsViewController *)mvc choseMappingAtIndex:(NSInteger)idx { - [self.mappingsController activateMapping:self.mappingsController.mappings[idx]]; + [self.inputController activateMapping:self.inputController.mappings[idx]]; } - (id)deviceViewController:(NJDeviceViewController *)dvc elementForUID:(NSString *)uid { - return [self.deviceController elementForUID:uid]; + return [self.inputController elementForUID:uid]; } - (void)deviceViewControllerDidSelectNothing:(NJDeviceViewController *)dvc { @@ -412,30 +412,31 @@ [self.outputController loadInput:dvc.selectedHandler]; } -- (void)deviceController:(NJDeviceController *)dc +- (void)deviceController:(NJInputController *)dc didAddDevice:(NJDevice *)device { [self.dvc addedDevice:device atIndex:dc.devices.count - 1]; } -- (void)deviceController:(NJDeviceController *)dc +- (void)deviceController:(NJInputController *)dc didRemoveDeviceAtIndex:(NSInteger)idx { [self.dvc removedDeviceAtIndex:idx]; } -- (void)deviceControllerDidStartHID:(NJDeviceController *)dc { +- (void)deviceControllerDidStartHID:(NJInputController *)dc { [self.dvc hidStarted]; } -- (void)deviceControllerDidStopHID:(NJDeviceController *)dc { +- (void)deviceControllerDidStopHID:(NJInputController *)dc { [self.dvc hidStopped]; } -- (void)deviceController:(NJDeviceController *)dc didInput:(NJInput *)input { +- (void)deviceController:(NJInputController *)dc didInput:(NJInput *)input { + [self.dvc expandAndSelectItem:input]; [self.outputController loadInput:input]; [self.outputController focusKey]; } -- (void)deviceController:(NJDeviceController *)dc didError:(NSError *)error { +- (void)deviceController:(NJInputController *)dc didError:(NSError *)error { // Since the error shows the window, it can trigger another attempt // to re-open the HID manager, which will also probably fail and error, // so don't bother repeating ourselves. @@ -451,16 +452,16 @@ } - (NSInteger)numberOfDevicesInDeviceList:(NJDeviceViewController *)dvc { - return self.deviceController.devices.count; + return self.inputController.devices.count; } - (NJDevice *)deviceViewController:(NJDeviceViewController *)dvc deviceForIndex:(NSUInteger)idx { - return self.deviceController.devices[idx]; + return self.inputController.devices[idx]; } - (IBAction)simulatingEventsChanged:(NSButton *)sender { - self.deviceController.simulatingEvents = sender.state == NSOnState; + self.inputController.simulatingEvents = sender.state == NSOnState; } @end diff --git a/Classes/NJDeviceController.h b/Classes/NJDeviceController.h deleted file mode 100644 index 41017db..0000000 --- a/Classes/NJDeviceController.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// NJDeviceController.h -// Enjoy -// -// Created by Sam McCall on 4/05/09. -// Copyright 2009 University of Otago. All rights reserved. -// - -#import "NJHIDManager.h" - -@class NJDevice; -@class NJInput; -@class NJInputPathElement; -@class NJMappingsController; - -@protocol NJDeviceControllerDelegate; - -@interface NJDeviceController : NSObject { - IBOutlet NJMappingsController *mappingsController; -} - -@property (nonatomic, weak) IBOutlet id delegate; - -@property (nonatomic, assign) NSPoint mouseLoc; -@property (nonatomic, assign) BOOL simulatingEvents; -@property (nonatomic, readonly) NSArray *devices; - -- (NJInputPathElement *)elementForUID:(NSString *)uid; - -@end - -@protocol NJDeviceControllerDelegate - -- (void)deviceController:(NJDeviceController *)dc didAddDevice:(NJDevice *)device; -- (void)deviceController:(NJDeviceController *)dc didRemoveDeviceAtIndex:(NSInteger)idx; -- (void)deviceController:(NJDeviceController *)dc didInput:(NJInput *)input; -- (void)deviceControllerDidStartHID:(NJDeviceController *)dc; -- (void)deviceControllerDidStopHID:(NJDeviceController *)dc; -- (void)deviceController:(NJDeviceController *)dc didError:(NSError *)error; - -@end diff --git a/Classes/NJDeviceController.m b/Classes/NJDeviceController.m deleted file mode 100644 index 5df317b..0000000 --- a/Classes/NJDeviceController.m +++ /dev/null @@ -1,219 +0,0 @@ -// -// NJDeviceController.m -// Enjoy -// -// Created by Sam McCall on 4/05/09. -// - -#import "NJDeviceController.h" - -#import "NJMapping.h" -#import "NJMappingsController.h" -#import "NJDevice.h" -#import "NJInput.h" -#import "NJOutput.h" -#import "NJEvents.h" - -@implementation NJDeviceController { - NJHIDManager *_hidManager; - NSTimer *_continuousOutputsTick; - NSMutableArray *_continousOutputs; - NSMutableArray *_devices; -} - -#define NSSTR(e) ((NSString *)CFSTR(e)) - -- (id)init { - if ((self = [super init])) { - _devices = [[NSMutableArray alloc] initWithCapacity:16]; - _continousOutputs = [[NSMutableArray alloc] initWithCapacity:32]; - - _hidManager = [[NJHIDManager alloc] initWithCriteria:@[ - @{ NSSTR(kIOHIDDeviceUsagePageKey) : @(kHIDPage_GenericDesktop), - NSSTR(kIOHIDDeviceUsageKey) : @(kHIDUsage_GD_Joystick) }, - @{ NSSTR(kIOHIDDeviceUsagePageKey) : @(kHIDPage_GenericDesktop), - NSSTR(kIOHIDDeviceUsageKey) : @(kHIDUsage_GD_GamePad) }, - @{ NSSTR(kIOHIDDeviceUsagePageKey) : @(kHIDPage_GenericDesktop), - NSSTR(kIOHIDDeviceUsageKey) : @(kHIDUsage_GD_MultiAxisController) } - ] - delegate:self]; - - // The HID manager uses 5-10ms per second doing basically - // nothing if a noisy device is plugged in (the % of that - // spent in input_callback is negligible, so it's not - // something we can make faster). I don't really think that's - // acceptable, CPU/power wise. So if simulation is disabled - // and the window is closed, just switch off the HID manager - // entirely. This probably also has some marginal benefits for - // compatibility with other applications that want exclusive - // grabs. - [NSNotificationCenter.defaultCenter - addObserver:self - selector:@selector(stopHidIfDisabled:) - name:NSApplicationDidResignActiveNotification - object:nil]; - [NSNotificationCenter.defaultCenter - addObserver:self - selector:@selector(startHid) - name:NSApplicationDidBecomeActiveNotification - object:nil]; - } - return self; -} - -- (void)dealloc { - [NSNotificationCenter.defaultCenter removeObserver:self]; - [_continuousOutputsTick invalidate]; -} - -- (void)addRunningOutput:(NJOutput *)output { - // Axis events will trigger every small movement, don't keep - // re-adding them or they trigger multiple times each time. - if (![_continousOutputs containsObject:output]) - [_continousOutputs addObject:output]; - if (!_continuousOutputsTick) { - _continuousOutputsTick = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 - target:self - selector:@selector(updateContinuousOutputs:) - userInfo:nil - repeats:YES]; - } -} - -- (void)runOutputForDevice:(IOHIDDeviceRef)device value:(IOHIDValueRef)value { - NJDevice *dev = [self findDeviceByRef:device]; - NJInput *mainInput = [dev inputForEvent:value]; - [mainInput notifyEvent:value]; - NSArray *children = mainInput.children ? mainInput.children : mainInput ? @[mainInput] : @[]; - for (NJInput *subInput in children) { - NJOutput *output = mappingsController.currentMapping[subInput]; - output.magnitude = subInput.magnitude; - output.running = subInput.active; - if ((output.running || output.magnitude) && output.isContinuous) - [self addRunningOutput:output]; - } -} - -- (void)showOutputForDevice:(IOHIDDeviceRef)device value:(IOHIDValueRef)value { - NJDevice *dev = [self findDeviceByRef:device]; - NJInput *handler = [dev handlerForEvent:value]; - if (!handler) - return; - - [self.delegate deviceController:self didInput:handler]; -} - -- (void)hidManager:(NJHIDManager *)manager - valueChanged:(IOHIDValueRef)value - fromDevice:(IOHIDDeviceRef)device { - if (self.simulatingEvents - && !NSApplication.sharedApplication.isActive) { - [self runOutputForDevice:device value:value]; - } else { - [self showOutputForDevice:device value:value]; - } -} - -- (void)addDevice:(NJDevice *)device { - BOOL available; - do { - available = YES; - for (NJDevice *used in _devices) { - if ([used isEqual:device]) { - device.index += 1; - available = NO; - } - } - } while (!available); - - [_devices addObject:device]; -} - -- (void)hidManager:(NJHIDManager *)manager deviceAdded:(IOHIDDeviceRef)device { - NJDevice *match = [[NJDevice alloc] initWithDevice:device]; - [self addDevice:match]; - [self.delegate deviceController:self didAddDevice:match]; -} - -- (NJDevice *)findDeviceByRef:(IOHIDDeviceRef)device { - for (NJDevice *dev in _devices) - if (dev.device == device) - return dev; - return nil; -} - -- (void)hidManager:(NJHIDManager *)manager deviceRemoved:(IOHIDDeviceRef)device { - NJDevice *match = [self findDeviceByRef:device]; - if (match) { - NSInteger idx = [_devices indexOfObjectIdenticalTo:match]; - [_devices removeObjectAtIndex:idx]; - [self.delegate deviceController:self didRemoveDeviceAtIndex:idx]; - } -} - -- (void)updateContinuousOutputs:(NSTimer *)timer { - self.mouseLoc = [NSEvent mouseLocation]; - for (NJOutput *output in [_continousOutputs copy]) { - if (![output update:self]) { - [_continousOutputs removeObject:output]; - } - } - if (!_continousOutputs.count) { - [_continuousOutputsTick invalidate]; - _continuousOutputsTick = nil; - } -} - -- (void)hidManager:(NJHIDManager *)manager didError:(NSError *)error { - [self.delegate deviceController:self didError:error]; - self.simulatingEvents = NO; -} - -- (void)hidManagerDidStart:(NJHIDManager *)manager { - [self.delegate deviceControllerDidStartHID:self]; -} - -- (void)hidManagerDidStop:(NJHIDManager *)manager { - [_devices removeAllObjects]; - [self.delegate deviceControllerDidStopHID:self]; -} - -- (void)startHid { - [_hidManager start]; -} - -- (void)stopHid { - [_hidManager stop]; -} - -- (void)setSimulatingEvents:(BOOL)simulatingEvents { - if (simulatingEvents != _simulatingEvents) { - _simulatingEvents = simulatingEvents; - NSString *name = simulatingEvents - ? NJEventSimulationStarted - : NJEventSimulationStopped; - [NSNotificationCenter.defaultCenter postNotificationName:name - object:self]; - - if (!simulatingEvents && !NSApplication.sharedApplication.isActive) - [self stopHid]; - else - [self startHid]; - } -} - -- (void)stopHidIfDisabled:(NSNotification *)application { - if (!self.simulatingEvents && !NSProcessInfo.processInfo.isBeingDebugged) - [self stopHid]; -} - -- (NJInputPathElement *)elementForUID:(NSString *)uid { - for (NJDevice *dev in _devices) { - id item = [dev elementForUID:uid]; - if (item) - return item; - } - return nil; -} - -@end diff --git a/Classes/NJInputController.h b/Classes/NJInputController.h new file mode 100644 index 0000000..06852f2 --- /dev/null +++ b/Classes/NJInputController.h @@ -0,0 +1,58 @@ +// +// NJDeviceController.h +// Enjoy +// +// Created by Sam McCall on 4/05/09. +// Copyright 2009 University of Otago. All rights reserved. +// + +#import "NJHIDManager.h" + +@class NJDevice; +@class NJInput; +@class NJInputPathElement; +@class NJMapping; + +@protocol NJInputControllerDelegate; + +@interface NJInputController : NSObject + +@property (nonatomic, weak) IBOutlet id delegate; + +@property (nonatomic, assign) NSPoint mouseLoc; +@property (nonatomic, assign) BOOL simulatingEvents; +@property (nonatomic, readonly) NSArray *devices; + +@property (nonatomic, readonly) NJMapping *currentMapping; +@property (nonatomic, readonly) NSArray *mappings; + +- (NJMapping *)mappingForKey:(NSString *)name; +- (NSInteger)indexOfMapping:(NJMapping *)mapping; + +- (void)addMapping:(NJMapping *)mapping; +- (void)insertMapping:(NJMapping *)mapping atIndex:(NSInteger)idx; +- (void)removeMappingAtIndex:(NSInteger)idx; +- (void)mergeMapping:(NJMapping *)mapping intoMapping:(NJMapping *)existing; +- (void)moveMoveMappingFromIndex:(NSInteger)fromIdx toIndex:(NSInteger)toIdx; +- (void)renameMapping:(NJMapping *)mapping to:(NSString *)name; + +- (void)activateMapping:(NJMapping *)mapping; +- (void)activateMappingForProcess:(NSRunningApplication *)app; + +- (void)save; +- (void)load; + +- (NJInputPathElement *)elementForUID:(NSString *)uid; + +@end + +@protocol NJInputControllerDelegate + +- (void)deviceController:(NJInputController *)dc didAddDevice:(NJDevice *)device; +- (void)deviceController:(NJInputController *)dc didRemoveDeviceAtIndex:(NSInteger)idx; +- (void)deviceController:(NJInputController *)dc didInput:(NJInput *)input; +- (void)deviceControllerDidStartHID:(NJInputController *)dc; +- (void)deviceControllerDidStopHID:(NJInputController *)dc; +- (void)deviceController:(NJInputController *)dc didError:(NSError *)error; + +@end diff --git a/Classes/NJInputController.m b/Classes/NJInputController.m new file mode 100644 index 0000000..4ca33e1 --- /dev/null +++ b/Classes/NJInputController.m @@ -0,0 +1,363 @@ +// +// NJDeviceController.m +// Enjoy +// +// Created by Sam McCall on 4/05/09. +// + +#import "NJInputController.h" + +#import "NJMapping.h" +#import "NJDevice.h" +#import "NJInput.h" +#import "NJOutput.h" +#import "NJEvents.h" + +@implementation NJInputController { + NJHIDManager *_hidManager; + NSTimer *_continuousOutputsTick; + NSMutableArray *_continousOutputs; + NSMutableArray *_devices; + NSMutableArray *_mappings; + NJMapping *_manualMapping; + +} + +#define NSSTR(e) ((NSString *)CFSTR(e)) + +- (id)init { + if ((self = [super init])) { + _devices = [[NSMutableArray alloc] initWithCapacity:16]; + _continousOutputs = [[NSMutableArray alloc] initWithCapacity:32]; + + _hidManager = [[NJHIDManager alloc] initWithCriteria:@[ + @{ NSSTR(kIOHIDDeviceUsagePageKey) : @(kHIDPage_GenericDesktop), + NSSTR(kIOHIDDeviceUsageKey) : @(kHIDUsage_GD_Joystick) }, + @{ NSSTR(kIOHIDDeviceUsagePageKey) : @(kHIDPage_GenericDesktop), + NSSTR(kIOHIDDeviceUsageKey) : @(kHIDUsage_GD_GamePad) }, + @{ NSSTR(kIOHIDDeviceUsagePageKey) : @(kHIDPage_GenericDesktop), + NSSTR(kIOHIDDeviceUsageKey) : @(kHIDUsage_GD_MultiAxisController) } + ] + delegate:self]; + + _mappings = [[NSMutableArray alloc] init]; + _currentMapping = [[NJMapping alloc] initWithName: + NSLocalizedString(@"(default)", @"default name for first the mapping")]; + _manualMapping = _currentMapping; + [_mappings addObject:_currentMapping]; + + // The HID manager uses 5-10ms per second doing basically + // nothing if a noisy device is plugged in (the % of that + // spent in input_callback is negligible, so it's not + // something we can make faster). I don't really think that's + // acceptable, CPU/power wise. So if simulation is disabled + // and the window is closed, just switch off the HID manager + // entirely. This probably also has some marginal benefits for + // compatibility with other applications that want exclusive + // grabs. + [NSNotificationCenter.defaultCenter + addObserver:self + selector:@selector(stopHidIfDisabled:) + name:NSApplicationDidResignActiveNotification + object:nil]; + [NSNotificationCenter.defaultCenter + addObserver:self + selector:@selector(startHid) + name:NSApplicationDidBecomeActiveNotification + object:nil]; + } + return self; +} + +- (void)dealloc { + [NSNotificationCenter.defaultCenter removeObserver:self]; + [_continuousOutputsTick invalidate]; +} + +- (void)addRunningOutput:(NJOutput *)output { + // Axis events will trigger every small movement, don't keep + // re-adding them or they trigger multiple times each time. + if (![_continousOutputs containsObject:output]) + [_continousOutputs addObject:output]; + if (!_continuousOutputsTick) { + _continuousOutputsTick = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 + target:self + selector:@selector(updateContinuousOutputs:) + userInfo:nil + repeats:YES]; + } +} + +- (void)runOutputForDevice:(IOHIDDeviceRef)device value:(IOHIDValueRef)value { + NJDevice *dev = [self findDeviceByRef:device]; + NJInput *mainInput = [dev inputForEvent:value]; + [mainInput notifyEvent:value]; + NSArray *children = mainInput.children ? mainInput.children : mainInput ? @[mainInput] : @[]; + for (NJInput *subInput in children) { + NJOutput *output = self.currentMapping[subInput]; + output.magnitude = subInput.magnitude; + output.running = subInput.active; + if ((output.running || output.magnitude) && output.isContinuous) + [self addRunningOutput:output]; + } +} + +- (void)showOutputForDevice:(IOHIDDeviceRef)device value:(IOHIDValueRef)value { + NJDevice *dev = [self findDeviceByRef:device]; + NJInput *handler = [dev handlerForEvent:value]; + if (!handler) + return; + + [self.delegate deviceController:self didInput:handler]; +} + +- (void)hidManager:(NJHIDManager *)manager + valueChanged:(IOHIDValueRef)value + fromDevice:(IOHIDDeviceRef)device { + if (self.simulatingEvents + && !NSApplication.sharedApplication.isActive) { + [self runOutputForDevice:device value:value]; + } else { + [self showOutputForDevice:device value:value]; + } +} + +- (void)addDevice:(NJDevice *)device { + BOOL available; + do { + available = YES; + for (NJDevice *used in _devices) { + if ([used isEqual:device]) { + device.index += 1; + available = NO; + } + } + } while (!available); + + [_devices addObject:device]; +} + +- (void)hidManager:(NJHIDManager *)manager deviceAdded:(IOHIDDeviceRef)device { + NJDevice *match = [[NJDevice alloc] initWithDevice:device]; + [self addDevice:match]; + [self.delegate deviceController:self didAddDevice:match]; +} + +- (NJDevice *)findDeviceByRef:(IOHIDDeviceRef)device { + for (NJDevice *dev in _devices) + if (dev.device == device) + return dev; + return nil; +} + +- (void)hidManager:(NJHIDManager *)manager deviceRemoved:(IOHIDDeviceRef)device { + NJDevice *match = [self findDeviceByRef:device]; + if (match) { + NSInteger idx = [_devices indexOfObjectIdenticalTo:match]; + [_devices removeObjectAtIndex:idx]; + [self.delegate deviceController:self didRemoveDeviceAtIndex:idx]; + } +} + +- (void)updateContinuousOutputs:(NSTimer *)timer { + self.mouseLoc = [NSEvent mouseLocation]; + for (NJOutput *output in [_continousOutputs copy]) { + if (![output update:self]) { + [_continousOutputs removeObject:output]; + } + } + if (!_continousOutputs.count) { + [_continuousOutputsTick invalidate]; + _continuousOutputsTick = nil; + } +} + +- (void)hidManager:(NJHIDManager *)manager didError:(NSError *)error { + [self.delegate deviceController:self didError:error]; + self.simulatingEvents = NO; +} + +- (void)hidManagerDidStart:(NJHIDManager *)manager { + [self.delegate deviceControllerDidStartHID:self]; +} + +- (void)hidManagerDidStop:(NJHIDManager *)manager { + [_devices removeAllObjects]; + [self.delegate deviceControllerDidStopHID:self]; +} + +- (void)startHid { + [_hidManager start]; +} + +- (void)stopHid { + [_hidManager stop]; +} + +- (void)setSimulatingEvents:(BOOL)simulatingEvents { + if (simulatingEvents != _simulatingEvents) { + _simulatingEvents = simulatingEvents; + NSString *name = simulatingEvents + ? NJEventSimulationStarted + : NJEventSimulationStopped; + [NSNotificationCenter.defaultCenter postNotificationName:name + object:self]; + + if (!simulatingEvents && !NSApplication.sharedApplication.isActive) + [self stopHid]; + else + [self startHid]; + } +} + +- (void)stopHidIfDisabled:(NSNotification *)application { + if (!self.simulatingEvents && !NSProcessInfo.processInfo.isBeingDebugged) + [self stopHid]; +} + +- (NJInputPathElement *)elementForUID:(NSString *)uid { + for (NJDevice *dev in _devices) { + id item = [dev elementForUID:uid]; + if (item) + return item; + } + return nil; +} + +- (NJMapping *)mappingForKey:(NSString *)name { + for (NJMapping *mapping in _mappings) + if ([name isEqualToString:mapping.name]) + return mapping; + return nil; +} + +- (void)mappingsSet { + [self postLoadProcess]; + [NSNotificationCenter.defaultCenter + postNotificationName:NJEventMappingListChanged + object:self + userInfo:@{ NJMappingListKey: _mappings, + NJMappingKey: _currentMapping }]; +} + +- (void)mappingsChanged { + [self save]; + [self mappingsSet]; +} + +- (void)activateMappingForProcess:(NSRunningApplication *)app { + NJMapping *oldMapping = _manualMapping; + NSArray *names = app.possibleMappingNames; + BOOL found = NO; + for (NSString *name in names) { + NJMapping *mapping = [self mappingForKey:name]; + if (mapping) { + [self activateMapping:mapping]; + found = YES; + break; + } + } + + if (!found) { + [self activateMapping:oldMapping]; + if ([oldMapping.name.lowercaseString isEqualToString:@"@application"] + || [oldMapping.name.lowercaseString isEqualToString: + NSLocalizedString(@"@Application", nil).lowercaseString]) { + oldMapping.name = app.bestMappingName; + [self mappingsChanged]; + } + } + _manualMapping = oldMapping; +} + +- (void)activateMappingForcibly:(NJMapping *)mapping { + NSLog(@"Switching to mapping %@.", mapping.name); + _currentMapping = mapping; + NSUInteger idx = [self indexOfMapping:_currentMapping]; + [NSNotificationCenter.defaultCenter + postNotificationName:NJEventMappingChanged + object:self + userInfo:@{ NJMappingKey : _currentMapping, + NJMappingIndexKey: @(idx) }]; +} + +- (void)activateMapping:(NJMapping *)mapping { + if (!mapping) + mapping = _manualMapping; + if (mapping == _currentMapping) + return; + _manualMapping = mapping; + [self activateMappingForcibly:mapping]; +} + +- (void)save { + NSLog(@"Saving mappings to defaults."); + NSMutableArray *ary = [[NSMutableArray alloc] initWithCapacity:_mappings.count]; + for (NJMapping *mapping in _mappings) + [ary addObject:[mapping serialize]]; + [NSUserDefaults.standardUserDefaults setObject:ary forKey:@"mappings"]; +} + +- (void)postLoadProcess { + for (NJMapping *mapping in self.mappings) + [mapping postLoadProcess:self.mappings]; +} + +- (void)load { + NSUInteger selected = [NSUserDefaults.standardUserDefaults integerForKey:@"selected"]; + NSArray *storedMappings = [NSUserDefaults.standardUserDefaults arrayForKey:@"mappings"]; + NSMutableArray* newMappings = [[NSMutableArray alloc] initWithCapacity:storedMappings.count]; + + for (NSDictionary *serialization in storedMappings) + [newMappings addObject: + [[NJMapping alloc] initWithSerialization:serialization]]; + + if (newMappings.count) { + _mappings = newMappings; + if (selected >= newMappings.count) + selected = 0; + [self activateMapping:_mappings[selected]]; + [self mappingsSet]; + } +} + +- (NSInteger)indexOfMapping:(NJMapping *)mapping { + return [_mappings indexOfObjectIdenticalTo:mapping]; +} + +- (void)mergeMapping:(NJMapping *)mapping intoMapping:(NJMapping *)existing { + [existing mergeEntriesFrom:mapping]; + [self mappingsChanged]; + if (existing == _currentMapping) + [self activateMappingForcibly:mapping]; +} + +- (void)renameMapping:(NJMapping *)mapping to:(NSString *)name { + mapping.name = name; + [self mappingsChanged]; + if (mapping == _currentMapping) + [self activateMappingForcibly:mapping]; +} + +- (void)addMapping:(NJMapping *)mapping { + [self insertMapping:mapping atIndex:_mappings.count]; +} + +- (void)insertMapping:(NJMapping *)mapping atIndex:(NSInteger)idx { + [_mappings insertObject:mapping atIndex:idx]; + [self mappingsChanged]; +} + +- (void)removeMappingAtIndex:(NSInteger)idx { + NSInteger currentIdx = [self indexOfMapping:_currentMapping]; + [_mappings removeObjectAtIndex:idx]; + [self activateMapping:self.mappings[MIN(currentIdx, _mappings.count - 1)]]; + [self mappingsChanged]; +} + +- (void)moveMoveMappingFromIndex:(NSInteger)fromIdx toIndex:(NSInteger)toIdx { + [_mappings moveObjectAtIndex:fromIdx toIndex:toIdx]; + [self mappingsChanged]; +} + +@end diff --git a/Classes/NJMappingsController.h b/Classes/NJMappingsController.h deleted file mode 100644 index b9d3e67..0000000 --- a/Classes/NJMappingsController.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// NJMappingsController.h -// Enjoy -// -// Created by Sam McCall on 4/05/09. -// Copyright 2009 University of Otago. All rights reserved. -// - -@class NJMapping; - -@interface NJMappingsController : NSObject - -@property (nonatomic, readonly) NJMapping *currentMapping; -@property (nonatomic, readonly) NSArray *mappings; - -- (NJMapping *)mappingForKey:(NSString *)name; -- (NSInteger)indexOfMapping:(NJMapping *)mapping; - -- (void)addMapping:(NJMapping *)mapping; -- (void)insertMapping:(NJMapping *)mapping atIndex:(NSInteger)idx; -- (void)removeMappingAtIndex:(NSInteger)idx; -- (void)mergeMapping:(NJMapping *)mapping intoMapping:(NJMapping *)existing; -- (void)moveMoveMappingFromIndex:(NSInteger)fromIdx toIndex:(NSInteger)toIdx; -- (void)renameMapping:(NJMapping *)mapping to:(NSString *)name; - -- (void)activateMapping:(NJMapping *)mapping; -- (void)activateMappingForProcess:(NSRunningApplication *)app; - -- (void)save; -- (void)load; - -@end diff --git a/Classes/NJMappingsController.m b/Classes/NJMappingsController.m deleted file mode 100644 index 6902504..0000000 --- a/Classes/NJMappingsController.m +++ /dev/null @@ -1,166 +0,0 @@ -// -// NJMappingsController.m -// Enjoy -// -// Created by Sam McCall on 4/05/09. -// - -#import "NJMappingsController.h" - -#import "NJMapping.h" -#import "NJOutput.h" -#import "NJEvents.h" - -@implementation NJMappingsController { - NSMutableArray *_mappings; - NJMapping *_manualMapping; -} - -- (id)init { - if ((self = [super init])) { - _mappings = [[NSMutableArray alloc] init]; - _currentMapping = [[NJMapping alloc] initWithName: - NSLocalizedString(@"(default)", @"default name for first the mapping")]; - _manualMapping = _currentMapping; - [_mappings addObject:_currentMapping]; - } - return self; -} - -- (NJMapping *)mappingForKey:(NSString *)name { - for (NJMapping *mapping in _mappings) - if ([name isEqualToString:mapping.name]) - return mapping; - return nil; -} - -- (void)mappingsSet { - [self postLoadProcess]; - [NSNotificationCenter.defaultCenter - postNotificationName:NJEventMappingListChanged - object:self - userInfo:@{ NJMappingListKey: _mappings, - NJMappingKey: _currentMapping }]; -} - -- (void)mappingsChanged { - [self save]; - [self mappingsSet]; -} - -- (void)activateMappingForProcess:(NSRunningApplication *)app { - NJMapping *oldMapping = _manualMapping; - NSArray *names = app.possibleMappingNames; - BOOL found = NO; - for (NSString *name in names) { - NJMapping *mapping = [self mappingForKey:name]; - if (mapping) { - [self activateMapping:mapping]; - found = YES; - break; - } - } - - if (!found) { - [self activateMapping:oldMapping]; - if ([oldMapping.name.lowercaseString isEqualToString:@"@application"] - || [oldMapping.name.lowercaseString isEqualToString: - NSLocalizedString(@"@Application", nil).lowercaseString]) { - oldMapping.name = app.bestMappingName; - [self mappingsChanged]; - } - } - _manualMapping = oldMapping; -} - -- (void)activateMappingForcibly:(NJMapping *)mapping { - NSLog(@"Switching to mapping %@.", mapping.name); - _currentMapping = mapping; - NSUInteger idx = [self indexOfMapping:_currentMapping]; - [NSNotificationCenter.defaultCenter - postNotificationName:NJEventMappingChanged - object:self - userInfo:@{ NJMappingKey : _currentMapping, - NJMappingIndexKey: @(idx) }]; -} - -- (void)activateMapping:(NJMapping *)mapping { - if (!mapping) - mapping = _manualMapping; - if (mapping == _currentMapping) - return; - _manualMapping = mapping; - [self activateMappingForcibly:mapping]; -} - -- (void)save { - NSLog(@"Saving mappings to defaults."); - NSMutableArray *ary = [[NSMutableArray alloc] initWithCapacity:_mappings.count]; - for (NJMapping *mapping in _mappings) - [ary addObject:[mapping serialize]]; - [NSUserDefaults.standardUserDefaults setObject:ary forKey:@"mappings"]; -} - -- (void)postLoadProcess { - for (NJMapping *mapping in self.mappings) - [mapping postLoadProcess:self.mappings]; -} - -- (void)load { - NSUInteger selected = [NSUserDefaults.standardUserDefaults integerForKey:@"selected"]; - NSArray *storedMappings = [NSUserDefaults.standardUserDefaults arrayForKey:@"mappings"]; - NSMutableArray* newMappings = [[NSMutableArray alloc] initWithCapacity:storedMappings.count]; - - for (NSDictionary *serialization in storedMappings) - [newMappings addObject: - [[NJMapping alloc] initWithSerialization:serialization]]; - - if (newMappings.count) { - _mappings = newMappings; - if (selected >= newMappings.count) - selected = 0; - [self activateMapping:_mappings[selected]]; - [self mappingsSet]; - } -} - -- (NSInteger)indexOfMapping:(NJMapping *)mapping { - return [_mappings indexOfObjectIdenticalTo:mapping]; -} - -- (void)mergeMapping:(NJMapping *)mapping intoMapping:(NJMapping *)existing { - [existing mergeEntriesFrom:mapping]; - [self mappingsChanged]; - if (existing == _currentMapping) - [self activateMappingForcibly:mapping]; -} - -- (void)renameMapping:(NJMapping *)mapping to:(NSString *)name { - mapping.name = name; - [self mappingsChanged]; - if (mapping == _currentMapping) - [self activateMappingForcibly:mapping]; -} - -- (void)addMapping:(NJMapping *)mapping { - [self insertMapping:mapping atIndex:_mappings.count]; -} - -- (void)insertMapping:(NJMapping *)mapping atIndex:(NSInteger)idx { - [_mappings insertObject:mapping atIndex:idx]; - [self mappingsChanged]; -} - -- (void)removeMappingAtIndex:(NSInteger)idx { - NSInteger currentIdx = [self indexOfMapping:_currentMapping]; - [_mappings removeObjectAtIndex:idx]; - [self activateMapping:self.mappings[MIN(currentIdx, _mappings.count - 1)]]; - [self mappingsChanged]; -} - -- (void)moveMoveMappingFromIndex:(NSInteger)fromIdx toIndex:(NSInteger)toIdx { - [_mappings moveObjectAtIndex:fromIdx toIndex:toIdx]; - [self mappingsChanged]; -} - -@end diff --git a/Classes/NJOutput.h b/Classes/NJOutput.h index aeb8e46..52c0320 100644 --- a/Classes/NJOutput.h +++ b/Classes/NJOutput.h @@ -6,7 +6,7 @@ // Copyright 2009 University of Otago. All rights reserved. // -@class NJDeviceController; +@class NJInputController; @interface NJOutput : NSObject @@ -16,7 +16,7 @@ - (void)trigger; - (void)untrigger; -- (BOOL)update:(NJDeviceController *)jc; +- (BOOL)update:(NJInputController *)jc; - (NSDictionary *)serialize; + (NJOutput *)outputDeserialize:(NSDictionary *)serialization; diff --git a/Classes/NJOutput.m b/Classes/NJOutput.m index 54809ce..8b21164 100644 --- a/Classes/NJOutput.m +++ b/Classes/NJOutput.m @@ -60,7 +60,7 @@ - (void)untrigger { } -- (BOOL)update:(NJDeviceController *)jc { +- (BOOL)update:(NJInputController *)jc { return NO; } diff --git a/Classes/NJOutputController.h b/Classes/NJOutputController.h index c18275f..b22afdb 100644 --- a/Classes/NJOutputController.h +++ b/Classes/NJOutputController.h @@ -8,8 +8,7 @@ #import "NJKeyInputField.h" -@class NJMappingsController; -@class NJDeviceController; +@class NJInputController; @class NJOutput; @class NJInput; @@ -23,7 +22,7 @@ IBOutlet NSSlider *scrollSpeedSlider; IBOutlet NSTextField *title; IBOutlet NSPopUpButton *mappingPopup; - IBOutlet NJMappingsController *mappingsController; + IBOutlet NJInputController *inputController; IBOutlet NSButton *smoothCheck; IBOutlet NSButton *unknownMapping; } diff --git a/Classes/NJOutputController.m b/Classes/NJOutputController.m index 22c387f..f8ed2ea 100644 --- a/Classes/NJOutputController.m +++ b/Classes/NJOutputController.m @@ -7,11 +7,10 @@ #import "NJOutputController.h" -#import "NJMappingsController.h" #import "NJMapping.h" #import "NJInput.h" #import "NJEvents.h" -#import "NJDeviceController.h" +#import "NJInputController.h" #import "NJKeyInputField.h" #import "NJOutputMapping.h" #import "NJOutputController.h" @@ -159,7 +158,7 @@ } - (NJOutput *)currentOutput { - return mappingsController.currentMapping[_input]; + return inputController.currentMapping[_input]; } - (NJOutput *)makeOutput { @@ -177,7 +176,7 @@ break; case 2: { NJOutputMapping *c = [[NJOutputMapping alloc] init]; - c.mapping = mappingsController.mappings[mappingPopup.indexOfSelectedItem]; + c.mapping = inputController.mappings[mappingPopup.indexOfSelectedItem]; return c; } case 3: { @@ -205,8 +204,8 @@ - (void)commit { [self cleanUpInterface]; - mappingsController.currentMapping[_input] = [self makeOutput]; - [mappingsController save]; + inputController.currentMapping[_input] = [self makeOutput]; + [inputController save]; } - (BOOL)enabled { diff --git a/Classes/NJOutputMapping.m b/Classes/NJOutputMapping.m index efb7c00..cfcc34f 100644 --- a/Classes/NJOutputMapping.m +++ b/Classes/NJOutputMapping.m @@ -9,7 +9,6 @@ #import "EnjoyableApplicationDelegate.h" #import "NJMapping.h" -#import "NJMappingsController.h" @implementation NJOutputMapping @@ -34,7 +33,7 @@ - (void)trigger { EnjoyableApplicationDelegate *ctrl = (EnjoyableApplicationDelegate *)NSApplication.sharedApplication.delegate; if (_mapping) { - [ctrl.mappingsController activateMapping:_mapping]; + [ctrl.inputController activateMapping:_mapping]; self.mappingName = _mapping.name; } else { // TODO: Show an error message? Unobtrusively since something diff --git a/Classes/NJOutputMouseMove.m b/Classes/NJOutputMouseMove.m index 84c0ea3..f943546 100644 --- a/Classes/NJOutputMouseMove.m +++ b/Classes/NJOutputMouseMove.m @@ -7,7 +7,7 @@ #import "NJOutputMouseMove.h" -#import "NJDeviceController.h" +#import "NJInputController.h" @implementation NJOutputMouseMove @@ -37,7 +37,7 @@ #define CLAMP(a, l, h) MIN(h, MAX(a, l)) -- (BOOL)update:(NJDeviceController *)jc { +- (BOOL)update:(NJInputController *)jc { if (self.magnitude < 0.05) return NO; // dead zone diff --git a/Classes/NJOutputMouseScroll.m b/Classes/NJOutputMouseScroll.m index 06913d6..b2775a8 100644 --- a/Classes/NJOutputMouseScroll.m +++ b/Classes/NJOutputMouseScroll.m @@ -52,7 +52,7 @@ } } -- (BOOL)update:(NJDeviceController *)jc { +- (BOOL)update:(NJInputController *)jc { if (self.magnitude < 0.05f) return NO; // dead zone diff --git a/Enjoyable.xcodeproj/project.pbxproj b/Enjoyable.xcodeproj/project.pbxproj index 74db726..c19007b 100644 --- a/Enjoyable.xcodeproj/project.pbxproj +++ b/Enjoyable.xcodeproj/project.pbxproj @@ -39,14 +39,13 @@ EEF17D3816E8E2E100D7DC4D /* NSView+FirstResponder.m in Sources */ = {isa = PBXBuildFile; fileRef = EEF17D3216E8E2E100D7DC4D /* NSView+FirstResponder.m */; }; EEF17D5C16E8E2EF00D7DC4D /* EnjoyableApplicationDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EEF17D3A16E8E2EF00D7DC4D /* EnjoyableApplicationDelegate.m */; }; EEF17D5D16E8E2EF00D7DC4D /* NJDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = EEF17D3C16E8E2EF00D7DC4D /* NJDevice.m */; }; - EEF17D5E16E8E2EF00D7DC4D /* NJDeviceController.m in Sources */ = {isa = PBXBuildFile; fileRef = EEF17D3E16E8E2EF00D7DC4D /* NJDeviceController.m */; }; + EEF17D5E16E8E2EF00D7DC4D /* NJInputController.m in Sources */ = {isa = PBXBuildFile; fileRef = EEF17D3E16E8E2EF00D7DC4D /* NJInputController.m */; }; EEF17D5F16E8E2EF00D7DC4D /* NJInput.m in Sources */ = {isa = PBXBuildFile; fileRef = EEF17D4016E8E2EF00D7DC4D /* NJInput.m */; }; EEF17D6016E8E2EF00D7DC4D /* NJInputAnalog.m in Sources */ = {isa = PBXBuildFile; fileRef = EEF17D4216E8E2EF00D7DC4D /* NJInputAnalog.m */; }; EEF17D6116E8E2EF00D7DC4D /* NJInputButton.m in Sources */ = {isa = PBXBuildFile; fileRef = EEF17D4416E8E2EF00D7DC4D /* NJInputButton.m */; }; EEF17D6216E8E2EF00D7DC4D /* NJInputHat.m in Sources */ = {isa = PBXBuildFile; fileRef = EEF17D4616E8E2EF00D7DC4D /* NJInputHat.m */; }; EEF17D6316E8E2EF00D7DC4D /* NJKeyInputField.m in Sources */ = {isa = PBXBuildFile; fileRef = EEF17D4916E8E2EF00D7DC4D /* NJKeyInputField.m */; }; EEF17D6416E8E2EF00D7DC4D /* NJMapping.m in Sources */ = {isa = PBXBuildFile; fileRef = EEF17D4B16E8E2EF00D7DC4D /* NJMapping.m */; }; - EEF17D6516E8E2EF00D7DC4D /* NJMappingsController.m in Sources */ = {isa = PBXBuildFile; fileRef = EEF17D4D16E8E2EF00D7DC4D /* NJMappingsController.m */; }; EEF17D6616E8E2EF00D7DC4D /* NJOutput.m in Sources */ = {isa = PBXBuildFile; fileRef = EEF17D4F16E8E2EF00D7DC4D /* NJOutput.m */; }; EEF17D6716E8E2EF00D7DC4D /* NJOutputController.m in Sources */ = {isa = PBXBuildFile; fileRef = EEF17D5116E8E2EF00D7DC4D /* NJOutputController.m */; }; EEF17D6816E8E2EF00D7DC4D /* NJOutputKeyPress.m in Sources */ = {isa = PBXBuildFile; fileRef = EEF17D5316E8E2EF00D7DC4D /* NJOutputKeyPress.m */; }; @@ -124,8 +123,8 @@ EEF17D3A16E8E2EF00D7DC4D /* EnjoyableApplicationDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = EnjoyableApplicationDelegate.m; path = Classes/EnjoyableApplicationDelegate.m; sourceTree = ""; }; EEF17D3B16E8E2EF00D7DC4D /* NJDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NJDevice.h; path = Classes/NJDevice.h; sourceTree = ""; }; EEF17D3C16E8E2EF00D7DC4D /* NJDevice.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NJDevice.m; path = Classes/NJDevice.m; sourceTree = ""; }; - EEF17D3D16E8E2EF00D7DC4D /* NJDeviceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NJDeviceController.h; path = Classes/NJDeviceController.h; sourceTree = ""; }; - EEF17D3E16E8E2EF00D7DC4D /* NJDeviceController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NJDeviceController.m; path = Classes/NJDeviceController.m; sourceTree = ""; }; + EEF17D3D16E8E2EF00D7DC4D /* NJInputController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NJInputController.h; path = Classes/NJInputController.h; sourceTree = ""; }; + EEF17D3E16E8E2EF00D7DC4D /* NJInputController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NJInputController.m; path = Classes/NJInputController.m; sourceTree = ""; }; EEF17D3F16E8E2EF00D7DC4D /* NJInput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NJInput.h; path = Classes/NJInput.h; sourceTree = ""; }; EEF17D4016E8E2EF00D7DC4D /* NJInput.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NJInput.m; path = Classes/NJInput.m; sourceTree = ""; }; EEF17D4116E8E2EF00D7DC4D /* NJInputAnalog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NJInputAnalog.h; path = Classes/NJInputAnalog.h; sourceTree = ""; }; @@ -139,8 +138,6 @@ EEF17D4916E8E2EF00D7DC4D /* NJKeyInputField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NJKeyInputField.m; path = Classes/NJKeyInputField.m; sourceTree = ""; }; EEF17D4A16E8E2EF00D7DC4D /* NJMapping.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NJMapping.h; path = Classes/NJMapping.h; sourceTree = ""; }; EEF17D4B16E8E2EF00D7DC4D /* NJMapping.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NJMapping.m; path = Classes/NJMapping.m; sourceTree = ""; }; - EEF17D4C16E8E2EF00D7DC4D /* NJMappingsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NJMappingsController.h; path = Classes/NJMappingsController.h; sourceTree = ""; }; - EEF17D4D16E8E2EF00D7DC4D /* NJMappingsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NJMappingsController.m; path = Classes/NJMappingsController.m; sourceTree = ""; }; EEF17D4E16E8E2EF00D7DC4D /* NJOutput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NJOutput.h; path = Classes/NJOutput.h; sourceTree = ""; }; EEF17D4F16E8E2EF00D7DC4D /* NJOutput.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NJOutput.m; path = Classes/NJOutput.m; sourceTree = ""; }; EEF17D5016E8E2EF00D7DC4D /* NJOutputController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NJOutputController.h; path = Classes/NJOutputController.h; sourceTree = ""; }; @@ -176,10 +173,8 @@ children = ( EEF17D3916E8E2EF00D7DC4D /* EnjoyableApplicationDelegate.h */, EEF17D3A16E8E2EF00D7DC4D /* EnjoyableApplicationDelegate.m */, - EEF17D3D16E8E2EF00D7DC4D /* NJDeviceController.h */, - EEF17D3E16E8E2EF00D7DC4D /* NJDeviceController.m */, - EEF17D4C16E8E2EF00D7DC4D /* NJMappingsController.h */, - EEF17D4D16E8E2EF00D7DC4D /* NJMappingsController.m */, + EEF17D3D16E8E2EF00D7DC4D /* NJInputController.h */, + EEF17D3E16E8E2EF00D7DC4D /* NJInputController.m */, EEF17D5016E8E2EF00D7DC4D /* NJOutputController.h */, EEF17D5116E8E2EF00D7DC4D /* NJOutputController.m */, EEF17D4816E8E2EF00D7DC4D /* NJKeyInputField.h */, @@ -442,14 +437,13 @@ EEF17D3816E8E2E100D7DC4D /* NSView+FirstResponder.m in Sources */, EEF17D5C16E8E2EF00D7DC4D /* EnjoyableApplicationDelegate.m in Sources */, EEF17D5D16E8E2EF00D7DC4D /* NJDevice.m in Sources */, - EEF17D5E16E8E2EF00D7DC4D /* NJDeviceController.m in Sources */, + EEF17D5E16E8E2EF00D7DC4D /* NJInputController.m in Sources */, EEF17D5F16E8E2EF00D7DC4D /* NJInput.m in Sources */, EEF17D6016E8E2EF00D7DC4D /* NJInputAnalog.m in Sources */, EEF17D6116E8E2EF00D7DC4D /* NJInputButton.m in Sources */, EEF17D6216E8E2EF00D7DC4D /* NJInputHat.m in Sources */, EEF17D6316E8E2EF00D7DC4D /* NJKeyInputField.m in Sources */, EEF17D6416E8E2EF00D7DC4D /* NJMapping.m in Sources */, - EEF17D6516E8E2EF00D7DC4D /* NJMappingsController.m in Sources */, EEF17D6616E8E2EF00D7DC4D /* NJOutput.m in Sources */, EEF17D6716E8E2EF00D7DC4D /* NJOutputController.m in Sources */, EEF17D6816E8E2EF00D7DC4D /* NJOutputKeyPress.m in Sources */, diff --git a/Info.plist b/Info.plist index 78a6a1a..3114a8b 100644 --- a/Info.plist +++ b/Info.plist @@ -46,7 +46,7 @@ CFBundleSignature ???? CFBundleVersion - 548 + 559 LSApplicationCategoryType public.app-category.utilities NSHumanReadableCopyright diff --git a/Resources/English.lproj/MainMenu.xib b/Resources/English.lproj/MainMenu.xib index b3d81ba..0c068fc 100644 --- a/Resources/English.lproj/MainMenu.xib +++ b/Resources/English.lproj/MainMenu.xib @@ -365,7 +365,6 @@ 268 {{7, 14}, {36, 25}} - _NS:9 YES @@ -415,7 +414,6 @@ 268 {{0, 14}, {140, 25}} - _NS:9 YES @@ -570,7 +568,7 @@ aW5nLg {232, 321} - + YES NO YES @@ -700,7 +698,7 @@ aW5nLg {234, 323} - + 150034 @@ -1218,6 +1216,101 @@ aW5nLg Enjoyable YES + + + + + + Enable + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Show Enjoyable + + 2147483647 + + + + + + Quit Enjoyable + + 2147483647 + + + + + + + + + + + Enable + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + + EnjoyableApplicationDelegate + + + NJInputController + + + NJOutputController + + + NJDeviceViewController + + + NJMappingsViewController + + + + 0 + 1 + 0.0 + 0.0 + YES + 256 @@ -1236,7 +1329,7 @@ aW5nLg {198, 198} - + YES NO YES @@ -1328,7 +1421,7 @@ aW5nLg {{0, 20}, {200, 200}} - + 150034 @@ -1473,104 +1566,6 @@ aW5nLg NSView - - - - - - Enable - - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - Show Enjoyable - - 2147483647 - - - - - - Quit Enjoyable - - 2147483647 - - - - - - - - - - - Enable - - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - - EnjoyableApplicationDelegate - - - - 0 - 1 - 0.0 - 0.0 - YES - - - NJMappingsController - - - NJDeviceController - - - NJOutputController - - - NJDeviceViewController - - - NJMappingsViewController - NJMappingMenuController @@ -1698,14 +1693,6 @@ aW5nLg 1002 - - - mappingsController - - - - 822 - delegate @@ -1714,14 +1701,6 @@ aW5nLg 1029 - - - mappingsController - - - - 820 - window @@ -1786,14 +1765,6 @@ aW5nLg 1025 - - - deviceController - - - - 1026 - outputController @@ -1818,6 +1789,14 @@ aW5nLg 1031 + + + inputController + + + + 1032 + performClick: @@ -1842,14 +1821,6 @@ aW5nLg 991 - - - mappingsController - - - - 821 - mouseDirSelect @@ -1994,6 +1965,14 @@ aW5nLg 1022 + + + inputController + + + + 1034 + delegate @@ -2537,11 +2516,6 @@ aW5nLg - - 514 - - - 479 @@ -3171,7 +3145,6 @@ aW5nLg com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -3373,7 +3346,7 @@ aW5nLg - 1031 + 1034 @@ -3405,10 +3378,9 @@ aW5nLg - NJDeviceController NSMenu NJDeviceViewController - NJMappingsController + NJInputController NJMappingsViewController NJOutputController NSButton @@ -3416,10 +3388,6 @@ aW5nLg NSWindow - - deviceController - NJDeviceController - dockMenu NSMenu @@ -3428,9 +3396,9 @@ aW5nLg dvc NJDeviceViewController - - mappingsController - NJMappingsController + + inputController + NJInputController mvc @@ -3458,28 +3426,6 @@ aW5nLg ./Classes/EnjoyableApplicationDelegate.h - - NJDeviceController - NSObject - - id - NJMappingsController - - - - delegate - id - - - mappingsController - NJMappingsController - - - - IBProjectSource - ./Classes/NJDeviceController.h - - NJDeviceViewController NSObject @@ -3512,6 +3458,25 @@ aW5nLg ./Classes/NJDeviceViewController.h + + NJInputController + NSObject + + delegate + id + + + delegate + + delegate + id + + + + IBProjectSource + ./Classes/NJInputController.h + + NJKeyInputField NSControl @@ -3558,14 +3523,6 @@ aW5nLg ./Classes/NJMappingMenuController.h - - NJMappingsController - NSObject - - IBProjectSource - ./Classes/NJMappingsController.h - - NJMappingsViewController NSViewController @@ -3685,9 +3642,9 @@ aW5nLg + NJInputController NJKeyInputField NSPopUpButton - NJMappingsController NSSegmentedControl NSSegmentedControl NSSlider @@ -3699,6 +3656,10 @@ aW5nLg NSButton + + inputController + NJInputController + keyInput NJKeyInputField @@ -3707,10 +3668,6 @@ aW5nLg mappingPopup NSPopUpButton - - mappingsController - NJMappingsController - mouseBtnSelect NSSegmentedControl