2010-02-10 10 views
10

¿Cómo puedo detectar la pulsación de un botón en un gamepad USB en OSX 10.5 y superior?Cómo detectar un botón del gamepad presione en OSX 10.5 y superior?

No puedo entender el ridículo complejo HID Manager (aunque aparentemente se simplificó con 10.5), y las muestras de código en Apple tienen miles de líneas de código que tomarían días para comprender y aislar lo que Necesito, por lo que agradecería que alguien publique una solución simple y completamente codificada para este problema aislado.


EDITAR: hasta ahora todas las respuestas son enlaces a bibliotecas de código fuente o semi oscuros para todo tipo de dispositivos HID, lo que requerirá más tiempo de investigación de lo que me gustaría invertir en esto. Estoy empezando una recompensa para obtener un fragmento real del código que resuelve este problema simple (usando una biblioteca externa o no).


EDITAR POS BOUNTY: gracias a todos por su ayuda; pero desafortunadamente la respuesta que ha sido seleccionada automáticamente por el sistema no me funciona, no puedo entender por qué; y el autor aún no ha respondido a mis comentarios. Cualquier idea sería apreciada, pero hasta que se encuentre una solución, cualquiera que busque recursos sobre este tema debería tomar esta respuesta con un poco de sal.

+0

Vale la pena invertir un poco de tiempo para investigar las opciones. Me llevó los cinco minutos descargar la fuente DDHidLib, encontrar el código relacionado con el joystick y crear una implementación. –

+0

Lo hice tan pronto como Peter lo publicó. No pude resolverlo después de 30 min. Si no obtengo un fragmento de código funcional de esta respuesta, no tendré otra opción, pero sinceramente estoy temiendo ese momento. Esto es demasiado complejo para un problema tan simple. –

Respuesta

7

La sugerencia de Peter del marco DDHidLib es exactamente lo que estás buscando. La biblioteca está bien diseñada y el código de muestra que viene con la biblioteca es bastante autoexplicativo.

Una implementación de un objeto que se lleva todos los joysticks/consolas de juego conectados al sistema y los relojes de las pulsaciones de botón usando DDHidLib sería algo como esto:

#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 
+0

¿Ha probado este código en OSX 10.5 y versiones posteriores? No está funcionando para mi. La matriz joySticks se llena correctamente, pero los métodos ddhidJoystick no se llaman. He agregado llamadas NSLog a los métodos reales DDHidJoystick ddhidJoystick (y todos los otros métodos de entrada), y tanto como presiono todos los botones y muevo todos los palos, ninguno de los métodos se llama. Lo he intentado con un par de gamepads. Sin embargo, aparecen correctamente en la matriz joySticks. –

+0

y DDHidJoystick ddhidJoystick métodos quise decir: DDHidJoystick ddhidJoystick: buttonDown: y DDHidJoystick ddhidJoystick: buttonUp: –

1

Utilizo Procontroll, pero esa es una biblioteca de Java. Es bueno sin embargo.

1

¿Quizás podría consultar el código fuente de MAME OS X? Tiene buen soporte para gamepad.

4

Puede probar Dave Dribin 's DDHidLib.

+0

Dave hizo el puerto Mac MAME, por lo que esto es probablemente equivalente, pero mejor que mi sugerencia. – Ken

+0

Gracias Peter. La documentación es escasa (si no inexistente) para esta biblioteca, ¿sabe cómo usarla? –

+1

No, yo no. (Hola, mínimo de longitud de comentarios.) –

1

creo haber resuelto el problema planteado por la póster original con respecto al código de ejemplo proporcionado:

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

Debe seleccionar un joystick y empezar a escucharlo. ¡Simple como eso! Tenga en cuenta que puede reemplazar el 0 con cualquier índice válido en la matriz joySticks, para seleccionar qué joystick escuchará, y supongo que puede escuchar más de uno a la vez si lo desea.

También tenga en cuenta que esta (y la anterior) inicialización se debe hacer desde una secuencia que tiene un ciclo de ejecución. Si está trabajando en aplicaciones mac OS x nativas, esto no es un problema, pero si está escribiendo código portátil y espera usar los hilos POSIX, encontrará que muchos objetos de cacao no funcionan cuando se crean dentro de un POSIX hilo. He descubierto que, en general, puede llamarlos de forma segura desde cualquier hilo una vez creado, pero la creación debe ocurrir en un hilo con un ciclo de ejecución. Casi todos los objetos de cacao que funcionan a través de eventos de estilo de devolución de llamada, activan esos eventos desde el ciclo de ejecución del subproceso que los crea.

10

En primer lugar, importe el marco IOKit e incluirlo como este en su encabezado e implementación archivos:

#import <IOKit/hid/IOHIDLib.h> 

En el archivo de cabecera es posible que desee tener esta variable:

IOHIDManagerRef hidManager; 

A continuación, añadir esto a su implementación:

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

Y llame a setupGamepad desde su awakeFrom Punta. Puede modificar la variable "kHIDUsage_GD_GamePad" para registrar también otros dispositivos. Codifiqué las cosas de arriba leyendo los ejemplos del documento http://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/HID/hid.pdf paso a paso y comparándolo con el código fuente "real" en http://abstractable.net/enjoy

Buena suerte.

0

El código de ejemplo de Rob solo necesita una cosa más para que funcione.

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

Pon esto en tu función awakeFromNib, después de llamar a startWatchingJoySticks.

BTW, mac no registra todo el gamepad (al menos no 360 Gamepad) como un dispositivo HID, por lo tanto, tendrá que descargar un controlador para ello. Probé con este controlador y funciona. http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/OsxDriver

Cuestiones relacionadas