I am trying to detect and use a gamepad attached to my Mac in my game. I am using the IOKit for this but without success. The gamepad is recognized as I downloaded a Mac app that views all gamepads attached. It is a Logitech F310 and I have set it to DirectInput. I am calling setupInput inside awakeFromNib but none of the callbacks are ever called. There is no error or exception thrown. I have no idea why the callbacks are not called. What am I doing wrong? I am thinking maybe it's an issue with the run loop. I tried both CFRunLoopGetMain and CFRunLoopGetCurrent.
Not sure what else to do.
Edit: As suggested by someone I tried to put the same GamePad code in a new project and it worked. There is some difference in the structure of the classes but I couldn't make it work in my app even if I tried to replicate the classes. My app use AppDelegate and NSOpenGLView. Strangely enough it doesn't have an NSViewController. The minimal app use NSOpenGLView but also NSResponder and when I put the gamepad code inside the(custom) NSResponder class it "works"(detects the gamepad and responds to input). I tried to add that custom class to my app but it "didn't work". What am I missing?
void gamepadWasAdded(void* inContext, IOReturn inResult, void* inSender, IOHIDDeviceRef device) {
NSLog(@"Gamepad was plugged in");
}
void gamepadWasRemoved(void* inContext, IOReturn inResult, void* inSender, IOHIDDeviceRef device) {
NSLog(@"Gamepad was unplugged");
}
void gamepadAction(void* inContext, IOReturn inResult, void* inSender, IOHIDValueRef value) {
NSLog(@"Gamepad talked!");
IOHIDElementRef element = IOHIDValueGetElement(value);
NSLog(@"Element: %@", element);
int elementValue = IOHIDValueGetIntegerValue(value);
NSLog(@"Element value: %i", elementValue);
}
-(void) setupInput {
//get a HID manager reference
hidManager = IOHIDManagerCreate(kCFAllocatorDefault,
kIOHIDOptionsTypeNone);
//define the device to search for, via usage page and usage key
NSMutableDictionary* criterion = [[NSMutableDictionary alloc] init];
[criterion setObject: [NSNumber numberWithInt: kHIDPage_GenericDesktop]
forKey: (NSString*)CFSTR(kIOHIDDeviceUsagePageKey)];
[criterion setObject: [NSNumber numberWithInt: kHIDUsage_GD_Joystick]
forKey: (NSString*)CFSTR(kIOHIDDeviceUsageKey)];
//search for the device
IOHIDManagerSetDeviceMatching(hidManager,
(__bridge CFDictionaryRef)criterion);
//register our callback functions
IOHIDManagerRegisterDeviceMatchingCallback(hidManager, gamepadWasAdded,
(__bridge void*)self);
IOHIDManagerRegisterDeviceRemovalCallback(hidManager, gamepadWasRemoved,
(__bridge void*)self);
IOHIDManagerRegisterInputValueCallback(hidManager, gamepadAction,
(__bridge void*)self);
//scedule our HIDManager with the current run loop, so that we
//are able to recieve events from the hardware.
IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetMain(),
kCFRunLoopDefaultMode);
//open the HID manager, so that it can start routing events
//to our callbacks.
IOHIDManagerOpen(hidManager, kIOHIDOptionsTypeNone);
}
// Put our timer in -awakeFromNib, so it can start up right from the beginning
-(void)awakeFromNib
{
renderTimer = [NSTimer timerWithTimeInterval:0.001 //a 1ms time interval
target:self
selector:@selector(timerFired:)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:renderTimer
forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] addTimer:renderTimer
forMode:NSEventTrackingRunLoopMode]; //Ensure timer fires during resize
[self setupInput];
}