Как обнаружить кнопку геймпада нажмите на OSX 10.5 и выше?

Как определить нажатие кнопки на геймпаде USB на OSX 10.5 и выше?

Я не могу обернуть голову вокруг смехотворно сложного HID Manager (хотя, по-видимому, это было упрощено с 10.5), а в образцах кода у Apple есть тысячи строк кода, которые занимают дни, чтобы понять и изолировать то, что мне нужно, поэтому я был бы признателен, если бы кто-то опубликовал простое и полностью закодированное решение для этой изолированной проблемы.


РЕДАКТИРОВАТЬ: пока все ответы - это ссылки на исходный код или неполные библиотеки для всех видов HID-устройств, для чего потребуется больше времени на исследования, чем то, что я хотел бы инвестировать в это. Я начинаю щедро получать фактический фрагмент кода, который решает эту простую задачу (используя внешнюю библиотеку или нет).


EDIT POS BOUNTY: спасибо всем за помощь; но, к сожалению, ответ, который был автоматически выбран системой, не работает для меня, не может понять, почему; и автор еще не ответил на мои комментарии. Любое понимание было бы оценено, но до тех пор, пока не будет найдено исправление, любой, кто ищет ресурсы по этой теме, должен принять этот ответ с большим количеством соли.

Ответ 1

Предложение Peter DDHidLib - именно то, что вы ищете. Библиотека хорошо разработана, и пример кода, который поставляется с библиотекой, довольно понятен.

Реализация объекта, который получает все джойстики/геймпады, прикрепленные к системе, и наблюдает за нажатиями кнопок с использованием DDHidLib, будет выглядеть примерно так:

#import <Cocoa/Cocoa.h>
#import <DDHidLib/DDHidLib.h>

@interface JoyStickWatcher : NSObject
{
    NSArray* joySticks;
}
- (void)startWatchingJoysticks;
@end


@implementation JoyStickWatcher
- (void)startWatchingJoysticks
{
    //get an array of all joystick objects
    joySticks = [[DDHidJoystick allJoysticks] retain];

    //become the delegate of all available joystick objects
    [joySticks makeObjectsPerformSelector:@selector(setDelegate:) withObject:self];
}

- (void)dealloc
{
    [joySticks release];
    [super dealloc];
}

//these are the DDHidLib joystick delegate methods related to buttons

- (void)ddhidJoystick:(DDHidJoystick *)joystick buttonDown:(unsigned)buttonNumber
{
    NSLog(@"button number %ld of joystick %p went down",joystick,buttonNumber);
}

- (void)ddhidJoystick:(DDHidJoystick *)joystick buttonUp:(unsigned)buttonNumber
{
    NSLog(@"button number %ld of joystick %p went up",joystick,buttonNumber);
}

@end

Ответ 2

Сначала импортируйте IOKit Framework и включите его в свой заголовок и файлы реализации:

#import <IOKit/hid/IOHIDLib.h>

В вашем файле заголовка вы можете иметь эту переменную:

IOHIDManagerRef hidManager;

Затем добавьте это в свою реализацию:

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) setupGamepad {
  hidManager = IOHIDManagerCreate( kCFAllocatorDefault, kIOHIDOptionsTypeNone);
  NSMutableDictionary* criterion = [[NSMutableDictionary alloc] init];
  [criterion setObject: [NSNumber numberWithInt: kHIDPage_GenericDesktop] forKey: (NSString*)CFSTR(kIOHIDDeviceUsagePageKey)];
  [criterion setObject: [NSNumber numberWithInt: kHIDUsage_GD_GamePad] forKey: (NSString*)CFSTR(kIOHIDDeviceUsageKey)];
  IOHIDManagerSetDeviceMatching(hidManager, criterion);
  IOHIDManagerRegisterDeviceMatchingCallback(hidManager, gamepadWasAdded, (void*)self);
  IOHIDManagerRegisterDeviceRemovalCallback(hidManager, gamepadWasRemoved, (void*)self);
  IOHIDManagerScheduleWithRunLoop(hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
  IOReturn tIOReturn = IOHIDManagerOpen(hidManager, kIOHIDOptionsTypeNone);
  IOHIDManagerRegisterInputValueCallback(hidManager, gamepadAction, (void*)self);
}

И вызовите setupGamepad с вашего awakeFromNib. Вы можете изменить переменную "kHIDUsage_GD_GamePad" для регистрации других устройств. Я закодировал материал выше, прочитав http://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/HID/hid.pdf примеры документов и сравнивая их с "реальным" исходным кодом в http://abstractable.net/enjoy

Удачи.

Ответ 4

Я использую Procontroll, но это библиотека Java. Это хорошо, хотя.

Ответ 5

Возможно, вы могли бы посмотреть исходный код MAME OS X? Он имеет хорошую поддержку геймпада.

Ответ 6

Я считаю, что я решил проблему, изложенную в оригинальном плакате, в отношении приведенного примера кода:

DDHidJoystick * currentJoystick = [joySticks objectAtIndex: 0]; [currentJoystick startListening];

Вы должны выбрать джойстик и начать слушать его. Просто как тот! Обратите внимание, что вы можете заменить 0 на любой допустимый индекс в массив joySticks, чтобы выбрать, какой джойстик вы слушаете, и я предполагаю, что вы можете слушать более одного раза за раз, если хотите.

Также обратите внимание, что эта инициализация (и выше) должна выполняться из потока, который имеет цикл выполнения. Если вы работаете с родными приложениями mac os x, это не проблема, но если вы пишете переносимый код и надеетесь использовать потоки POSIX, вы обнаружите, что многие объекты cocoa не работают при создании внутри поток POSIX. Я обнаружил, что вы можете обычно безопасно их вызывать из любого потока после создания, но создание должно происходить в потоке с циклом запуска. Почти все объекты cocoa, которые работают через события стиля обратного вызова, запускают эти события из цикла запуска потока, который их создает.

Ответ 7

Пример кода Rob нужен только для того, чтобы заставить его работать.

if([joySticks count] > 0)
{
    DDHidJoyStick *myJoyStick = [joySticks objectAtIdex:0];
    [myJoyStick startListening];
}

Поместите это в свою функцию awakeFromNib, после вызова startWatchingJoySticks.

BTW, mac не регистрирует весь геймпад (по крайней мере, не 360 геймпад) как HID-устройство, поэтому вам нужно будет скачать драйвер для него. Я тестировал этот драйвер, и он работает. http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/OsxDriver