【问题标题】:How to detect a gamepad button press on OSX 10.5 and higher?如何检测 OSX 10.5 及更高版本上的游戏手柄按钮按下?
【发布时间】:2010-02-10 04:12:36
【问题描述】:

如何在 OSX 10.5 及更高版本上检测 USB 游戏手柄上的按钮按下?

我无法理解复杂得离谱的 HID 管理器(尽管它显然是用 10.5 简化的),Apple 的代码示例有数千行代码,需要几天时间才能理解和隔离我需要的内容,所以如果有人针对这个孤立的问题发布一个简单且完全编码的解决方案,我将不胜感激。


编辑:到目前为止,所有答案都是指向各种 HID 设备的源代码或半晦涩库的链接,这将需要比我想投入更多的研究时间。我开始赏金以获得实际的 sn-p of code 来解决这个简单的问题(使用或不使用外部库)。


EDIT POS BOUNTY:感谢大家的帮助;但不幸的是,系统自动选择的答案对我不起作用,不知道为什么;并且作者还没有回复我的cmets。任何见解都将不胜感激,但在找到修复程序之前,任何寻找有关此主题的资源的人都应该对这个答案持怀疑态度。

【问题讨论】:

  • 值得花一点时间研究这些选项。我花了五分钟时间下载了 DDHidLib 源代码,找到了游戏杆相关的代码并创建了一个实现。
  • 彼得一发布我就做了。 30分钟后无法弄清楚。如果我没有从这个答案中得到有效的代码,我别无选择,但老实说,我很害怕那一刻。对于这样一个简单的问题来说,这太复杂了。

标签: cocoa


【解决方案1】:

首先,导入 IOKit 框架并将其包含在您的头文件和实现文件中:

#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);
}

然后从您的 awakeFromNib 调用 setupGamepad。您也可以修改变量“kHIDUsage_GD_GamePad”来注册其他设备。我通过逐步阅读http://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/HID/hid.pdf 文档示例并将其与http://abstractable.net/enjoy 的“真实”源代码进行比较,对上面的内容进行了编码

祝你好运。

【讨论】:

    【解决方案2】:

    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
    

    【讨论】:

    • 您是否在 OSX 10.5 及更高版本上测试过此代码?它不适合我。 JoySticks 数组被正确填充,但 ddhidJoystick 方法没有被调用。我已将 NSLog 调用添加到实际的 DDHidJoystick ddhidJoystick 方法(以及所有其他输入方法)中,尽管我按下所有按钮并移动所有摇杆,但没有一个方法被调用。我已经用几个游戏手柄试过了。不过,它们确实正确地出现在了 joySticks 数组中。
    • 我指的是 DDHidJoystick ddhidJoystick 方法:DDHidJoystick ddhidJoystick:buttonDown: 和 DDHidJoystick ddhidJoystick:buttonUp:
    【解决方案3】:

    你可以试试Dave DribinDDHidLib

    【讨论】:

    • Dave 做了 Mac MAME 移植,所以这可能是等效的,但比我的建议要好。
    • 谢谢彼得。这个库的文档很少(如果不是不存在的话),你知道如何使用它吗?
    • 不,我不知道。 (您好,评论长度最短。)
    • 这是 Dave 的介绍性博客文章。他指着项目中的样本。我知道你想要一个 sn-p,这很好,但这对我来说并没有那么糟糕。 dribin.org/dave/blog/archives/2007/03/19/ddhidlib_10
    • 但是你们真的尝试过从游戏手柄检测事件吗?
    【解决方案4】:

    我使用 Procontroll,但那是一个 Java 库。不过也不错。

    【讨论】:

      【解决方案5】:

      也许您可以查看MAME OS X 的源代码?它有很好的游戏手柄支持。

      【讨论】:

        【解决方案6】:

        我相信我已经解决了原始发帖人就给出的示例代码提出的问题:

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

        您必须选择一个操纵杆并开始收听它。就那么简单!请注意,您可以将 0 替换为 joySticks 数组中的任何有效索引,以选择您要收听的游戏杆,我猜您可以一次收听多个。

        还要注意,这个(和上面的)初始化必须从一个有运行循环的线程中完成。如果您正在使用本机 mac os x 应用程序,这不是问题,但如果您正在编写可移植代码并希望使用 POSIX 线程,您会发现许多可可对象在 POSIX 中创建时不起作用线。我发现一旦创建,您通常可以从任何线程安全地调用它们,但是创建必须在具有运行循环的线程上进行。几乎所有通过回调样式事件工作的可可对象,都会从创建它们的线程的运行循环中触发这些事件。

        【讨论】:

          【解决方案7】:

          Rob 的示例代码只需要再做一件事情即可。

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

          在调用 startWatchingJoySticks 之后将其放入 awakeFromNib 函数中。

          顺便说一句,mac 不会将所有游戏手柄(至少不是 360 游戏手柄)注册为 HID 设备,因此您需要为其下载驱动程序。我用这个驱动程序测试过,它可以工作。 http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/OsxDriver

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-10-07
            • 1970-01-01
            • 2018-05-10
            • 2020-09-11
            相关资源
            最近更新 更多