@class NJInput;
-@interface NJDevice : NSObject <NJInputPathElement>
+@interface NJDevice : NJInputPathElement
+
+- (id)initWithDevice:(IOHIDDeviceRef)device;
@property (nonatomic, assign) int index;
@property (nonatomic, copy) NSString *productName;
@property (nonatomic, assign) IOHIDDeviceRef device;
-@property (nonatomic, copy) NSArray *children;
-@property (nonatomic, readonly) NSString *name;
-@property (readonly) NSString *uid;
-- (id)initWithDevice:(IOHIDDeviceRef)device;
- (NJInput *)handlerForEvent:(IOHIDValueRef)value;
- (NJInput *)inputForEvent:(IOHIDValueRef)value;
}
- (id)initWithDevice:(IOHIDDeviceRef)dev {
- if ((self = [super init])) {
+ if ((self = [super initWithName:nil did:nil base:nil])) {
self.device = dev;
self.productName = (__bridge NSString *)IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDProductKey));
vendorId = [(__bridge NSNumber *)IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDVendorIDKey)) intValue];
}
- (NJInput *)findInputByCookie:(IOHIDElementCookie)cookie {
- for (NJInput *child in _children)
+ for (NJInput *child in self.children)
if (child.cookie == cookie)
return child;
return nil;
return [self findInputByCookie:cookie];
}
-- (BOOL)isEqual:(id)object {
- return [object isKindOfClass:NJDevice.class]
- && [[object uid] isEqualToString:self.uid];
-}
-
-- (NSUInteger)hash {
- return self.uid.hash;
-}
-
-- (id <NJInputPathElement>)elementForUID:(NSString *)uid {
- if ([uid isEqualToString:self.uid])
- return self;
- else if (![uid hasPrefix:self.uid])
- return nil;
- else {
- for (id <NJInputPathElement> elem in self.children) {
- id <NJInputPathElement> ret = [elem elementForUID:uid];
- if (ret)
- return ret;
- }
- }
- return nil;
-}
-
@end
[_continuousOutputsTick invalidate];
}
-- (void)expandRecursive:(id <NJInputPathElement>)pathElement {
+- (void)expandRecursive:(NJInputPathElement *)pathElement {
if (pathElement) {
[self expandRecursive:pathElement.base];
[outlineView expandItem:pathElement];
}
- (NJInput *)selectedInput {
- id <NJInputPathElement> item = [outlineView itemAtRow:outlineView.selectedRow];
- return (!item.children && item.base) ? item : nil;
+ NJInputPathElement *item = [outlineView itemAtRow:outlineView.selectedRow];
+ return (NJInput *)((!item.children && item.base) ? item : nil);
}
- (NSInteger)outlineView:(NSOutlineView *)outlineView
- numberOfChildrenOfItem:(id <NJInputPathElement>)item {
+ numberOfChildrenOfItem:(NJInputPathElement *)item {
return item ? item.children.count : _devices.count;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView
- isItemExpandable:(id <NJInputPathElement>)item {
+ isItemExpandable:(NJInputPathElement *)item {
return item ? [[item children] count] > 0: YES;
}
- (id)outlineView:(NSOutlineView *)outlineView
child:(NSInteger)index
- ofItem:(id <NJInputPathElement>)item {
+ ofItem:(NJInputPathElement *)item {
return item ? item.children[index] : _devices[index];
}
- (id)outlineView:(NSOutlineView *)outlineView
objectValueForTableColumn:(NSTableColumn *)tableColumn
- byItem:(id <NJInputPathElement>)item {
+ byItem:(NJInputPathElement *)item {
return item ? item.name : @"root";
}
- (void)outlineViewSelectionDidChange:(NSNotification *)notification {
- id <NJInputPathElement> item = [outlineView itemAtRow:outlineView.selectedRow];
+ NJInputPathElement *item = [outlineView itemAtRow:outlineView.selectedRow];
if (item)
[NSUserDefaults.standardUserDefaults setObject:item.uid
forKey:@"selected input"];
}
- (BOOL)outlineView:(NSOutlineView *)outlineView
- isGroupItem:(id <NJInputPathElement>)item {
+ isGroupItem:(NJInputPathElement *)item {
return [item isKindOfClass:NJDevice.class];
}
- (BOOL)outlineView:(NSOutlineView *)outlineView_
- shouldSelectItem:(id <NJInputPathElement>)item {
+ shouldSelectItem:(NJInputPathElement *)item {
return ![self outlineView:outlineView_ isGroupItem:item];
}
- (void)outlineViewItemDidExpand:(NSNotification *)notification {
- id <NJInputPathElement> item = notification.userInfo[@"NSObject"];
+ NJInputPathElement *item = notification.userInfo[@"NSObject"];
NSString *uid = item.uid;
if (![_expanded containsObject:uid])
[_expanded addObject:uid];
}
- (void)outlineViewItemDidCollapse:(NSNotification *)notification {
- id <NJInputPathElement> item = notification.userInfo[@"NSObject"];
+ NJInputPathElement *item = notification.userInfo[@"NSObject"];
[_expanded removeObject:item.uid];
[NSUserDefaults.standardUserDefaults setObject:_expanded
forKey:@"expanded rows"];
#import "NJInputPathElement.h"
-@interface NJInput : NSObject <NJInputPathElement>
+@interface NJInput : NJInputPathElement
+
+- (id)initWithName:(NSString *)name
+ did:(NSString *)did
+ cookie:(IOHIDElementCookie)cookie
+ base:(NJInputPathElement *)base;
@property (nonatomic, assign) IOHIDElementCookie cookie;
-@property (nonatomic, copy) NSArray *children;
-@property (nonatomic, weak) id <NJInputPathElement> base;
-@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) BOOL active;
@property (nonatomic, assign) float magnitude;
-@property (readonly) NSString *uid;
-
-- (id)initWithName:(NSString *)newName base:(id <NJInputPathElement>)newBase;
- (void)notifyEvent:(IOHIDValueRef)value;
- (id)findSubInputForValue:(IOHIDValueRef)value;
@implementation NJInput
-- (id)initWithName:(NSString *)newName base:(id <NJInputPathElement>)newBase {
- if ((self = [super init])) {
- self.name = newName;
- self.base = newBase;
+- (id)initWithName:(NSString *)name
+ did:(NSString *)did
+ cookie:(IOHIDElementCookie)cookie
+ base:(NJInputPathElement *)base {
+ if ((self = [super initWithName:name did:did base:base])) {
+ self.cookie = cookie;
}
return self;
}
return nil;
}
-- (NSString *)uid {
- return [NSString stringWithFormat:@"%@~%@", _base.uid, _name];
-}
-
- (void)notifyEvent:(IOHIDValueRef)value {
[self doesNotRecognizeSelector:_cmd];
}
-- (BOOL)isEqual:(id)object {
- return [object isKindOfClass:NJInput.class]
- && [[object uid] isEqualToString:self.uid];
-}
-
-- (NSUInteger)hash {
- return self.uid.hash;
-}
-
-- (id <NJInputPathElement>)elementForUID:(NSString *)uid {
- if ([uid isEqualToString:self.uid])
- return self;
- else {
- for (id <NJInputPathElement> elem in self.children) {
- id <NJInputPathElement> ret = [elem elementForUID:uid];
- if (ret)
- return ret;
- }
- }
- return nil;
-}
-
@end
}
@implementation NJInputAnalog {
- float magnitude;
long rawMin;
long rawMax;
}
- (id)initWithIndex:(int)index rawMin:(long)rawMin_ rawMax:(long)rawMax_ {
- if ((self = [super init])) {
- self.name = [[NSString alloc] initWithFormat:NSLocalizedString(@"axis %d", @"axis name"), index];
- self.children = @[[[NJInput alloc] initWithName:NSLocalizedString(@"axis low", @"axis low trigger") base:self],
- [[NJInput alloc] initWithName:NSLocalizedString(@"axis high", @"axis high trigger") base:self]];
+ NSString *name = [[NSString alloc] initWithFormat:NSLocalizedString(@"axis %d", @"axis name"), index];
+ NSString *did = [[NSString alloc] initWithFormat:@"Axis %d", index];
+ if ((self = [super initWithName:name did:did base:nil])) {
+ self.children = @[[[NJInput alloc] initWithName:NSLocalizedString(@"axis low", @"axis low trigger")
+ did:@"Low"
+ base:self],
+ [[NJInput alloc] initWithName:NSLocalizedString(@"axis high", @"axis high trigger")
+ did:@"High"
+ base:self]];
rawMax = rawMax_;
rawMin = rawMin_;
}
}
- (void)notifyEvent:(IOHIDValueRef)value {
- magnitude = normalize(IOHIDValueGetIntegerValue(value), rawMin, rawMax);
+ float magnitude = self.magnitude = normalize(IOHIDValueGetIntegerValue(value), rawMin, rawMax);
[self.children[0] setMagnitude:fabsf(MIN(magnitude, 0))];
[self.children[1] setMagnitude:fabsf(MAX(magnitude, 0))];
[self.children[0] setActive:magnitude < -DEAD_ZONE];
[self.children[1] setActive:magnitude > DEAD_ZONE];
}
-- (float)magnitude {
- return magnitude;
-}
-
@end
}
- (id)initWithName:(NSString *)name idx:(int)idx max:(long)max {
- if ((self = [super init])) {
+ NSString *fullname = [NSString stringWithFormat:NSLocalizedString(@"button %d", @"button name"), idx];
+ if (name.length)
+ fullname = [fullname stringByAppendingFormat:@"- %@", name];
+ NSString *did = [[NSString alloc] initWithFormat:@"Button %d", idx];
+ if ((self = [super initWithName:fullname did:did base:nil])) {
_max = max;
- self.name = [NSString stringWithFormat:NSLocalizedString(@"button %d", @"button name"), idx];
-
- if (name.length)
- self.name = [self.name stringByAppendingFormat:@"- %@", name];
}
return self;
}
@implementation NJInputHat
- (id)initWithIndex:(int)index {
- if ((self = [super init])) {
- self.children = @[[[NJInput alloc] initWithName:NSLocalizedString(@"hat up", @"hat switch up state") base:self],
- [[NJInput alloc] initWithName:NSLocalizedString(@"hat down", @"hat switch down state") base:self],
- [[NJInput alloc] initWithName:NSLocalizedString(@"hat left", @"hat switch left state") base:self],
- [[NJInput alloc] initWithName:NSLocalizedString(@"hat right", @"hat switch right state") base:self]];
- self.name = [NSString stringWithFormat:NSLocalizedString(@"hat switch %d", @"hat switch name"), index];
+ NSString *name = [NSString stringWithFormat:NSLocalizedString(@"hat switch %d", @"hat switch name"), index];
+ NSString *did = [NSString stringWithFormat:@"Hat Switch %d", index];
+ if ((self = [super initWithName:name did:did base:nil])) {
+ self.children = @[[[NJInput alloc] initWithName:NSLocalizedString(@"hat up", @"hat switch up state")
+ did:@"Up"
+ base:self],
+ [[NJInput alloc] initWithName:NSLocalizedString(@"hat down", @"hat switch down state")
+ did:@"Down"
+ base:self],
+ [[NJInput alloc] initWithName:NSLocalizedString(@"hat left", @"hat switch left state")
+ did:@"Left"
+ base:self],
+ [[NJInput alloc] initWithName:NSLocalizedString(@"hat right", @"hat switch right state")
+ did:@"Right"
+ base:self]];
}
return self;
}
-#import <Foundation/Foundation.h>
+//
+// NJInputPathElement.h
+// Enjoyable
+//
+// Created by Joe Wreschnig on 3/13/13.
+//
+//
+@interface NJInputPathElement : NSObject
-@protocol NJInputPathElement <NSObject>
+- (id)initWithName:(NSString *)name
+ did:(NSString *)did
+ base:(NJInputPathElement *)base;
-// TODO: It's time this became a real base class rather than a protocol.
+@property (nonatomic, weak) NJInputPathElement *base;
+@property (nonatomic, copy) NSString *name;
+@property (nonatomic, readonly) NSString *uid;
+@property (nonatomic, strong) NSArray *children;
-- (NSArray *)children;
-- (id <NJInputPathElement>) base;
-- (NSString *)name;
-- (NSString *)uid;
-
-- (id <NJInputPathElement>)elementForUID:(NSString *)uid;
+- (NJInputPathElement *)elementForUID:(NSString *)uid;
@end
--- /dev/null
+//
+// NJInputPathElement.m
+// Enjoyable
+//
+// Created by Joe Wreschnig on 3/13/13.
+//
+//
+
+#include "NJInputPathElement.h"
+
+@implementation NJInputPathElement {
+ NSString *_did;
+}
+
+- (id)initWithName:(NSString *)name
+ did:(NSString *)did
+ base:(NJInputPathElement *)base {
+ if ((self = [super init])) {
+ self.name = name;
+ self.base = base;
+ _did = did;
+ }
+ return self;
+}
+
+- (BOOL)isEqual:(id)object {
+ return [object isKindOfClass:NJInputPathElement.class]
+ && [[object uid] isEqualToString:self.uid];
+}
+
+- (NSUInteger)hash {
+ return self.uid.hash;
+}
+
+- (NSString *)uid {
+ return [NSString stringWithFormat:@"%@~%@", _base.uid, _did];
+}
+
+- (NJInputPathElement *)elementForUID:(NSString *)uid {
+ if ([uid isEqualToString:self.uid])
+ return self;
+ else if (![uid hasPrefix:self.uid])
+ return nil;
+ else {
+ for (NJInputPathElement *elem in self.children) {
+ NJInputPathElement *ret = [elem elementForUID:uid];
+ if (ret)
+ return ret;
+ }
+ }
+ return nil;
+}
+
+@end
} else {
self.enabled = YES;
NSString *inpFullName = input.name;
- for (id <NJInputPathElement> cur = input.base; cur; cur = cur.base) {
+ for (NJInputPathElement *cur = input.base; cur; cur = cur.base) {
inpFullName = [[NSString alloc] initWithFormat:@"%@ ▸ %@", cur.name, inpFullName];
}
title.stringValue = inpFullName;
EED4CE7716EE195100C65AA8 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EED4CE7616EE195100C65AA8 /* Sparkle.framework */; };
EED4CE7816EE195B00C65AA8 /* Sparkle.framework in Copy Sparkle Framework */ = {isa = PBXBuildFile; fileRef = EED4CE7616EE195100C65AA8 /* Sparkle.framework */; };
EEE703DC16F089FE002FDD69 /* NJHIDManager.m in Sources */ = {isa = PBXBuildFile; fileRef = EEE703DB16F089FE002FDD69 /* NJHIDManager.m */; };
+ EEE703DE16F0B3F6002FDD69 /* NJInputPathElement.m in Sources */ = {isa = PBXBuildFile; fileRef = EEE703DD16F0B3F6002FDD69 /* NJInputPathElement.m */; };
EEE73B1616EA42E5009D9D99 /* NSRunningApplication+NJPossibleNames.m in Sources */ = {isa = PBXBuildFile; fileRef = EEE73B1516EA42E5009D9D99 /* NSRunningApplication+NJPossibleNames.m */; };
EEF17D1916E8E21A00D7DC4D /* com.yukkurigames.Enjoyable.mapping.icns in Resources */ = {isa = PBXBuildFile; fileRef = EEF17D1716E8E21A00D7DC4D /* com.yukkurigames.Enjoyable.mapping.icns */; };
EEF17D1F16E8E23A00D7DC4D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = EEF17D1B16E8E23A00D7DC4D /* InfoPlist.strings */; };
EED4CE7616EE195100C65AA8 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Sparkle.framework; sourceTree = "<group>"; };
EEE703DA16F089FE002FDD69 /* NJHIDManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NJHIDManager.h; path = Classes/NJHIDManager.h; sourceTree = "<group>"; };
EEE703DB16F089FE002FDD69 /* NJHIDManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NJHIDManager.m; path = Classes/NJHIDManager.m; sourceTree = "<group>"; };
+ EEE703DD16F0B3F6002FDD69 /* NJInputPathElement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NJInputPathElement.m; path = Classes/NJInputPathElement.m; sourceTree = "<group>"; };
EEE73B1416EA42E5009D9D99 /* NSRunningApplication+NJPossibleNames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSRunningApplication+NJPossibleNames.h"; path = "Categories/NSRunningApplication+NJPossibleNames.h"; sourceTree = "<group>"; };
EEE73B1516EA42E5009D9D99 /* NSRunningApplication+NJPossibleNames.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSRunningApplication+NJPossibleNames.m"; path = "Categories/NSRunningApplication+NJPossibleNames.m"; sourceTree = "<group>"; };
EEF17D1716E8E21A00D7DC4D /* com.yukkurigames.Enjoyable.mapping.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = com.yukkurigames.Enjoyable.mapping.icns; path = Resources/com.yukkurigames.Enjoyable.mapping.icns; sourceTree = "<group>"; };
EEF17D4A16E8E2EF00D7DC4D /* NJMapping.h */,
EEF17D4B16E8E2EF00D7DC4D /* NJMapping.m */,
EEF17D4716E8E2EF00D7DC4D /* NJInputPathElement.h */,
+ EEE703DD16F0B3F6002FDD69 /* NJInputPathElement.m */,
EEF17D3B16E8E2EF00D7DC4D /* NJDevice.h */,
EEF17D3C16E8E2EF00D7DC4D /* NJDevice.m */,
EEF17D3F16E8E2EF00D7DC4D /* NJInput.h */,
EEE73B1616EA42E5009D9D99 /* NSRunningApplication+NJPossibleNames.m in Sources */,
EED4CE6E16ED692400C65AA8 /* NJMappingMenuController.m in Sources */,
EEE703DC16F089FE002FDD69 /* NJHIDManager.m in Sources */,
+ EEE703DE16F0B3F6002FDD69 /* NJInputPathElement.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>244</string>
+ <string>248</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>NSHumanReadableCopyright</key>