diff --git a/stepmania/src/arch/InputHandler/InputHandler_Carbon.cpp b/stepmania/src/arch/InputHandler/InputHandler_Carbon.cpp index c937cc3d74..814cdb07de 100644 --- a/stepmania/src/arch/InputHandler/InputHandler_Carbon.cpp +++ b/stepmania/src/arch/InputHandler/InputHandler_Carbon.cpp @@ -1,15 +1,6 @@ #include "global.h" #include "RageLog.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include "InputHandler_Carbon.h" @@ -17,604 +8,8 @@ #include "RageUtil.h" #include "PrefsManager.h" #include "archutils/Darwin/DarwinThreadHelpers.h" - -using namespace std; -using __gnu_cxx::hash_map; - -// Simple helper, still need to release it -static inline CFNumberRef CFInt( int n ) -{ - return CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &n ); -} - -static inline void PrintIOErr( IOReturn err, const char *s ) -{ - LOG->Warn( "%s - %s(%x,%d)", s, mach_error_string(err), err, err & 0xFFFFFF ); -} - -static inline Boolean IntValue( const void *o, int *n ) -{ - return CFNumberGetValue( CFNumberRef(o), kCFNumberIntType, n ); -} - -/* - * This is just awful, these aren't objects, treating them as such leads - * to: (*object)->function(object [, argument]...) - * Instead, do: CALL(object, function [, argument]...) - */ -#define CALL(o,f,...) (*(o))->f((o), ## __VA_ARGS__) - -struct Joystick -{ - InputDevice id; - // map cookie to button - hash_map mapping; - int x_axis, y_axis, z_axis; - int x_min, y_min, z_min; - int x_max, y_max, z_max; - - Joystick(); -}; - -Joystick::Joystick() : id( DEVICE_NONE ), - x_axis( DeviceButton_Invalid ), - y_axis( DeviceButton_Invalid ), - z_axis( DeviceButton_Invalid ), - x_min( 0 ), y_min( 0 ), z_min( 0 ), - x_max( 0 ), y_max( 0 ), z_max( 0 ) -{ -} - -class HIDDevice -{ -private: - IOHIDDeviceInterface **mInterface; - IOHIDQueueInterface **mQueue; - bool mRunning; - RString mDescription; - - static void AddLogicalDevice( const void *value, void *context ); - static void AddElement( const void *value, void *context ); - -protected: - virtual bool AddLogicalDevice( int usagePage, int usage ) = 0; - virtual void AddElement( int usagePage, int usage, int cookie, const CFDictionaryRef dict ) = 0; - virtual void Open() = 0; - - inline void AddElementToQueue( int cookie ) - { - CALL( mQueue, addElement, IOHIDElementCookie(cookie), 0 ); - } -public: - HIDDevice(); - virtual ~HIDDevice(); - - bool Open( io_object_t device ); - void StartQueue( CFRunLoopRef loopRef, IOHIDCallbackFunction callback, void *target, int refCon ); - inline const RString& GetDescription() const { return mDescription; } -}; - -HIDDevice::HIDDevice() : mInterface( NULL ), mQueue( NULL ), mRunning( false ) -{ -} - -HIDDevice::~HIDDevice() -{ - if( mQueue ) - { - CFRunLoopSourceRef runLoopSource; - - if( mRunning ) - CALL( mQueue, stop ); - if( (runLoopSource = CALL(mQueue, getAsyncEventSource)) ) - { - mach_port_deallocate( mach_task_self(), CALL(mQueue, getAsyncPort) ); - CFRunLoopSourceInvalidate( runLoopSource ); - CFRelease( runLoopSource ); - } - - CALL( mQueue, dispose ); - CALL( mQueue, Release ); - } - if( mInterface ) - { - CALL( mInterface, close ); - CALL( mInterface, Release ); - } -} - -bool HIDDevice::Open( io_object_t device ) -{ - IOReturn ret; - CFMutableDictionaryRef properties; - kern_return_t result; - - result = IORegistryEntryCreateCFProperties( device, &properties, kCFAllocatorDefault, kNilOptions ); - if ( result != KERN_SUCCESS || !properties ) - { - LOG->Warn( "Couldn't get properties." ); - return false; - } - - CFStringRef productRef = (CFStringRef)CFDictionaryGetValue( properties, CFSTR(kIOHIDProductKey) ); - - if( productRef ) - { - mDescription = CFStringGetCStringPtr( productRef, CFStringGetSystemEncoding() ); - } - else - { - CFTypeRef vidRef = (CFTypeRef)CFDictionaryGetValue( properties, CFSTR(kIOHIDVendorIDKey) ); - CFTypeRef pidRef = (CFTypeRef)CFDictionaryGetValue( properties, CFSTR(kIOHIDProductIDKey) ); - int vid, pid; - - if( vidRef && !IntValue(vidRef, &vid) ) - vid = 0; - if( pidRef && !IntValue(pidRef, &pid) ) - pid = 0; - mDescription = ssprintf( "%04x:%04x", vid, pid ); - } - - CFArrayRef logicalDevices; - - if ( !(logicalDevices = (CFArrayRef)CFDictionaryGetValue(properties, CFSTR(kIOHIDElementKey))) ) - { - CFRelease( properties ); - return false; - } - CFRange r = { 0, CFArrayGetCount(logicalDevices) }; - - CFArrayApplyFunction( logicalDevices, r, HIDDevice::AddLogicalDevice, this ); - - CFRelease( properties ); - - // Create the interface - IOCFPlugInInterface **plugInInterface; - HRESULT hresult; - SInt32 score; - - ret = IOCreatePlugInInterfaceForService( device, kIOHIDDeviceUserClientTypeID, - kIOCFPlugInInterfaceID, &plugInInterface, &score ); - if( ret != kIOReturnSuccess ) - { - PrintIOErr( ret, "Failed to create plugin interface." ); - return false; - } - - // Call a method of the plugin to create the device interface - CFUUIDBytes bytes = CFUUIDGetUUIDBytes( kIOHIDDeviceInterfaceID ); - - hresult = CALL( plugInInterface, QueryInterface, bytes, (void **)&mInterface ); - - CALL( plugInInterface, Release ); - - if( hresult != S_OK ) - { - LOG->Warn( "Couldn't get device interface from plugin interface." ); - mInterface = NULL; - return false; - } - - // open the interface - if( (ret = CALL(mInterface, open, 0)) != kIOReturnSuccess ) - { - PrintIOErr( ret, "Failed to open the interface." ); - CALL( mInterface, Release ); - mInterface = NULL; - return false; - } - - // alloc/create queue - mQueue = CALL( mInterface, allocQueue ); - if( !mQueue ) - { - LOG->Warn( "Couldn't allocate a queue." ); - return false; - } - - if( (ret = CALL(mQueue, create, 0, 32)) != kIOReturnSuccess ) - { - PrintIOErr( ret, "Failed to create the queue." ); - CALL( mQueue, Release ); - mQueue = NULL; - return false; - } - - Open(); - return true; -} - -void HIDDevice::StartQueue( CFRunLoopRef loopRef, IOHIDCallbackFunction callback, void *target, int refCon ) -{ - CFRunLoopSourceRef runLoopSource; - // This creates a run loop source and a mach port. They are released in the dtor. - IOReturn ret = CALL( mQueue, createAsyncEventSource, &runLoopSource ); - - if( ret != kIOReturnSuccess ) - { - PrintIOErr( ret, "Failed to create async event source." ); - return; - } - - if( !CFRunLoopContainsSource(loopRef, runLoopSource, kCFRunLoopDefaultMode) ) - CFRunLoopAddSource( loopRef, runLoopSource, kCFRunLoopDefaultMode ); - - CALL( mQueue, setEventCallout, callback, target, (void *)refCon ); - - if( ret != kIOReturnSuccess ) - { - PrintIOErr( ret, "Failed to set the call back." ); - return; - } - - // start the queue - ret = CALL( mQueue, start ); - - if( ret != kIOReturnSuccess ) - { - PrintIOErr( ret, "Failed to start the queue." ); - return; - } - mRunning = true; -} - -void HIDDevice::AddLogicalDevice( const void *value, void *context ) -{ - if( CFGetTypeID(CFTypeRef(value)) != CFDictionaryGetTypeID() ) - return; - - CFDictionaryRef dict = CFDictionaryRef( value ); - HIDDevice *This = (HIDDevice *)context; - CFArrayRef elements; - CFTypeRef object; - int usage, usagePage; - CFTypeID numID = CFNumberGetTypeID(); - - // Get usage page - object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementUsagePageKey) ); - if( !object || CFGetTypeID(object) != numID || !IntValue(object, &usagePage) ) - return; - - // Get usage - object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementUsageKey) ); - if( !object || CFGetTypeID(object) != numID || !IntValue(object, &usage) ) - return; - - if( !(elements = (CFArrayRef)CFDictionaryGetValue( dict, CFSTR(kIOHIDElementKey))) ) - return; - - if( !This->AddLogicalDevice(usagePage, usage) ) - return; - - CFRange r = { 0, CFArrayGetCount(elements) }; - - CFArrayApplyFunction( elements, r, HIDDevice::AddElement, This ); -} - -void HIDDevice::AddElement( const void *value, void *context ) -{ - if( CFGetTypeID(CFTypeRef(value)) != CFDictionaryGetTypeID() ) - return; - - CFDictionaryRef dict = CFDictionaryRef( value ); - HIDDevice *This = (HIDDevice *)context; - CFTypeRef object; - CFTypeID numID = CFNumberGetTypeID(); - int cookie, usage, usagePage; - CFArrayRef elements; - - // Recursively add elements - if( (elements = (CFArrayRef)CFDictionaryGetValue(dict, CFSTR(kIOHIDElementKey))) ) - { - CFRange r = { 0, CFArrayGetCount(elements) }; - - CFArrayApplyFunction( elements, r, AddElement, context ); - } - - // Get usage page - object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementUsagePageKey) ); - if( !object || CFGetTypeID(object) != numID || !IntValue(object, &usagePage) ) - return; - - // Get usage - object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementUsageKey) ); - if( !object || CFGetTypeID(object) != numID || !IntValue(object, &usage) ) - return; - - - // Get cookie - object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementCookieKey) ); - if( !object || CFGetTypeID(object) != numID || !IntValue(object, &cookie) ) - return; - This->AddElement( usagePage, usage, cookie, dict ); -} - -class JoystickDevice : public HIDDevice -{ -private: - vector m_vSticks; - -protected: - bool AddLogicalDevice( int usagePage, int usage ); - void AddElement( int usagePage, int usage, int cookie, const CFDictionaryRef dict ); - void Open(); - -public: - // returns the number of IDs assigned starting from startID - int AssignJoystickIDs( int startID ); - inline int NumberOfSticks() const { return m_vSticks.size(); } - inline const Joystick& GetStick( int index ) const { return m_vSticks[index]; } -}; - -bool JoystickDevice::AddLogicalDevice( int usagePage, int usage ) -{ - if( usagePage != kHIDPage_GenericDesktop || usage != kHIDUsage_GD_Joystick ) - return false; - m_vSticks.push_back( Joystick() ); - return true; -} - -void JoystickDevice::AddElement( int usagePage, int usage, int cookie, const CFDictionaryRef dict ) -{ - CFTypeRef object; - CFTypeID numID = CFNumberGetTypeID(); - - Joystick& js = m_vSticks.back(); - - switch( usagePage ) - { - case kHIDPage_GenericDesktop: - { - int min = 0; - int max = 0; - - object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementMinKey) ); - if( object && CFGetTypeID(object) == numID ) - IntValue( object, &min ); - - object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementMaxKey) ); - if( object && CFGetTypeID(object) == numID ) - IntValue( object, &max ); - - switch( usage ) - { - case kHIDUsage_GD_X: - js.x_axis = cookie; - js.x_min = min; - js.x_max = max; - break; - case kHIDUsage_GD_Y: - js.y_axis = cookie; - js.y_min = min; - js.y_max = max; - break; - case kHIDUsage_GD_Z: - js.z_axis = cookie; - js.z_min = min; - js.z_max = max; - break; - case kHIDUsage_GD_DPadUp: - js.mapping[cookie] = JOY_UP; - break; - case kHIDUsage_GD_DPadDown: - js.mapping[cookie] = JOY_DOWN; - break; - case kHIDUsage_GD_DPadRight: - js.mapping[cookie] = JOY_RIGHT; - break; - case kHIDUsage_GD_DPadLeft: - js.mapping[cookie] = JOY_LEFT; - break; - default: - return; - } - break; - } - case kHIDPage_Button: - { - // button n has usage = n, subtract 1 to ensure - // button 1 = JOY_BUTTON_1 - const DeviceButton buttonID = enum_add2( JOY_BUTTON_1, usage - 1 ); - - if( buttonID <= JOY_BUTTON_32 ) - js.mapping[cookie] = buttonID; - break; - } - default: - return; - } // end switch (usagePage) -} - -void JoystickDevice::Open() -{ - // Add elements to the queue for each Joystick - FOREACH_CONST( Joystick, m_vSticks, i ) - { - const Joystick& js = *i; - - if( js.x_axis ) - AddElementToQueue( js.x_axis ); - if( js.y_axis ) - AddElementToQueue( js.y_axis ); - if( js.z_axis ) - AddElementToQueue( js.z_axis ); - - for( hash_map::const_iterator j = js.mapping.begin(); j != js.mapping.end(); ++j ) - AddElementToQueue( j->first ); - } -} - -int JoystickDevice::AssignJoystickIDs( int startID ) -{ - for( vector::iterator i = m_vSticks.begin(); i != m_vSticks.end(); ++i ) - i->id = InputDevice( startID++ ); - return m_vSticks.size(); -} - -class KeyboardDevice : public HIDDevice -{ -private: - hash_map m_Mapping; - -protected: - bool AddLogicalDevice( int usagePage, int usage ); - void AddElement( int usagePage, int usage, int cookie, const CFDictionaryRef dict ); - void Open(); - - friend void InputHandler_Carbon::QueueCallBack( void *, int, void *, void * ); -}; - -bool KeyboardDevice::AddLogicalDevice( int usagePage, int usage ) -{ - return usagePage == kHIDPage_GenericDesktop && usage == kHIDUsage_GD_Keyboard; -} - -void KeyboardDevice::AddElement( int usagePage, int usage, int cookie, const CFDictionaryRef dict ) -{ - if( usagePage != kHIDPage_KeyboardOrKeypad ) - return; - - if( usage < kHIDUsage_KeyboardA ) - return; - - if( usage <= kHIDUsage_KeyboardZ ) - { - m_Mapping[cookie] = enum_add2( KEY_Ca, usage - kHIDUsage_KeyboardA ); - return; - } - - // KEY_C0 = KEY_C1 - 1, kHIDUsage_Keyboard0 = kHIDUsage_Keyboard9 + 1 - if( usage <= kHIDUsage_Keyboard9 ) - { - m_Mapping[cookie] = enum_add2( KEY_C1, usage - kHIDUsage_Keyboard1 ); - return; - } - - if( usage >= kHIDUsage_KeyboardF1 && usage <= kHIDUsage_KeyboardF12 ) - { - m_Mapping[cookie] = enum_add2( KEY_F1, usage - kHIDUsage_KeyboardF1 ); - return; - } - - if( usage >= kHIDUsage_KeyboardF13 && usage <= kHIDUsage_KeyboardF16 ) - { - m_Mapping[cookie] = enum_add2( KEY_F13, usage - kHIDUsage_KeyboardF13 ); - return; - } - - // keypad 0 is again backward - if( usage >= kHIDUsage_Keypad1 && usage <= kHIDUsage_Keypad9 ) - { - m_Mapping[cookie] = enum_add2( KEY_KP_C1, usage - kHIDUsage_Keypad1 ); - return; - } - -#define OTHER(n) (enum_add2(KEY_OTHER_0, (n))) - - // [0, 8] - if( usage >= kHIDUsage_KeyboardF17 && usage <= kHIDUsage_KeyboardExecute ) - { - m_Mapping[cookie] = OTHER( 0 + usage - kHIDUsage_KeyboardF17 ); - return; - } - - // [9, 19] - if( usage >= kHIDUsage_KeyboardSelect && usage <= kHIDUsage_KeyboardVolumeDown ) - { - m_Mapping[cookie] = OTHER( 9 + usage - kHIDUsage_KeyboardSelect ); - return; - } - - // [20, 31] - if( usage >= kHIDUsage_KeypadEqualSignAS400 && usage <= kHIDUsage_KeyboardCancel ) - { - m_Mapping[cookie] = OTHER( 20 + usage - kHIDUsage_KeypadEqualSignAS400 ); - return; - } - - // [32, 37] - // XXX kHIDUsage_KeyboardClearOrAgain - if( usage >= kHIDUsage_KeyboardSeparator && usage <= kHIDUsage_KeyboardExSel ) - { - m_Mapping[cookie] = OTHER( 32 + usage - kHIDUsage_KeyboardSeparator ); - return; - } - -#define X(x,y) case x: m_Mapping[cookie] = y; return - - // Time for the special cases - switch( usage ) - { - X( kHIDUsage_Keyboard0, KEY_C0 ); - X( kHIDUsage_Keypad0, KEY_KP_C0 ); - X( kHIDUsage_KeyboardReturnOrEnter, KEY_ENTER ); - X( kHIDUsage_KeyboardEscape, KEY_ESC ); - X( kHIDUsage_KeyboardDeleteOrBackspace, KEY_BACK ); - X( kHIDUsage_KeyboardTab, KEY_TAB ); - X( kHIDUsage_KeyboardSpacebar, KEY_SPACE ); - X( kHIDUsage_KeyboardHyphen, KEY_HYPHEN ); - X( kHIDUsage_KeyboardEqualSign, KEY_EQUAL ); - X( kHIDUsage_KeyboardOpenBracket, KEY_LBRACKET ); - X( kHIDUsage_KeyboardCloseBracket, KEY_RBRACKET ); - X( kHIDUsage_KeyboardBackslash, KEY_BACKSLASH ); - X( kHIDUsage_KeyboardNonUSPound, KEY_HASH ); - X( kHIDUsage_KeyboardSemicolon, KEY_SEMICOLON ); - X( kHIDUsage_KeyboardQuote, KEY_SQUOTE ); - X( kHIDUsage_KeyboardGraveAccentAndTilde, KEY_ACCENT ); - X( kHIDUsage_KeyboardComma, KEY_COMMA ); - X( kHIDUsage_KeyboardPeriod, KEY_PERIOD ); - X( kHIDUsage_KeyboardSlash, KEY_SLASH ); - X( kHIDUsage_KeyboardCapsLock, KEY_CAPSLOCK ); - X( kHIDUsage_KeyboardPrintScreen, KEY_PRTSC ); - X( kHIDUsage_KeyboardScrollLock, KEY_SCRLLOCK ); - X( kHIDUsage_KeyboardPause, OTHER(38) ); - X( kHIDUsage_KeyboardInsert, KEY_INSERT ); - X( kHIDUsage_KeyboardHome, KEY_HOME ); - X( kHIDUsage_KeyboardPageUp, KEY_PGUP ); - X( kHIDUsage_KeyboardDeleteForward, KEY_DEL ); - X( kHIDUsage_KeyboardEnd, KEY_END ); - X( kHIDUsage_KeyboardPageDown, KEY_PGDN ); - X( kHIDUsage_KeyboardRightArrow, KEY_RIGHT ); - X( kHIDUsage_KeyboardLeftArrow, KEY_LEFT ); - X( kHIDUsage_KeyboardDownArrow, KEY_DOWN ); - X( kHIDUsage_KeyboardUpArrow, KEY_UP ); - X( kHIDUsage_KeypadNumLock, KEY_NUMLOCK ); - X( kHIDUsage_KeypadSlash, KEY_KP_SLASH ); - X( kHIDUsage_KeypadEqualSign, KEY_KP_EQUAL ); - X( kHIDUsage_KeypadAsterisk, KEY_KP_ASTERISK ); - X( kHIDUsage_KeypadHyphen, KEY_KP_HYPHEN ); - X( kHIDUsage_KeypadPlus, KEY_KP_PLUS ); - X( kHIDUsage_KeypadEnter, KEY_KP_ENTER ); - X( kHIDUsage_KeypadPeriod, KEY_KP_PERIOD ); - X( kHIDUsage_KeyboardNonUSBackslash, OTHER(39) ); - X( kHIDUsage_KeyboardApplication, OTHER(40) ); - X( kHIDUsage_KeyboardClear, KEY_NUMLOCK ); // XXX - X( kHIDUsage_KeyboardHelp, KEY_INSERT ); - X( kHIDUsage_KeyboardMenu, KEY_MENU ); - // XXX kHIDUsage_KeyboardLockingCapsLock - // XXX kHIDUsage_KeyboardLockingNumLock - // XXX kHIDUsage_KeyboardLockingScrollLock - X( kHIDUsage_KeypadComma, KEY_KP_PERIOD ); // XXX - X( kHIDUsage_KeyboardReturn, KEY_ENTER ); - X( kHIDUsage_KeyboardPrior, OTHER(41) ); - X( kHIDUsage_KeyboardLeftControl, KEY_LCTRL ); - X( kHIDUsage_KeyboardLeftShift, KEY_LSHIFT ); - X( kHIDUsage_KeyboardLeftAlt, KEY_LALT ); - X( kHIDUsage_KeyboardLeftGUI, KEY_LMETA ); - X( kHIDUsage_KeyboardRightControl, KEY_RCTRL ); - X( kHIDUsage_KeyboardRightShift, KEY_RSHIFT ); - X( kHIDUsage_KeyboardRightAlt, KEY_RALT ); - X( kHIDUsage_KeyboardRightGUI, KEY_RMETA ); - } -#undef X -#undef OTHER -} - -void KeyboardDevice::Open() -{ - for (hash_map::const_iterator i = m_Mapping.begin(); i != m_Mapping.end(); ++i) - AddElementToQueue( i->first ); -} +#include "archutils/Darwin/KeyboardDevice.h" +#include "archutils/Darwin/JoystickDevice.h" void InputHandler_Carbon::QueueCallBack( void *target, int result, void *refcon, void *sender ) { @@ -627,67 +22,12 @@ void InputHandler_Carbon::QueueCallBack( void *target, int result, void *refcon, IOHIDEventStruct event; AbsoluteTime zeroTime = { 0, 0 }; HIDDevice *dev = This->m_vDevices[int( refcon )]; - KeyboardDevice *kd = dynamic_cast(dev); - JoystickDevice *jd = dynamic_cast(dev); - - ASSERT( kd || jd ); + vector > vPresses; while( (result = CALL(queue, getNextEvent, &event, zeroTime, 0)) == kIOReturnSuccess ) - { - int cookie = int( event.elementCookie ); - int value = event.value; - - if( kd ) - { - hash_map::const_iterator iter = kd->m_Mapping.find( cookie ); - - if( iter != kd->m_Mapping.end() ) - This->ButtonPressed( DeviceInput(DEVICE_KEYBOARD, iter->second, value, now), value ); - continue; - } - - for( int i = 0; i < jd->NumberOfSticks(); ++i ) - { - const Joystick& js = jd->GetStick( i ); - - if( js.x_axis == cookie ) - { - float level = SCALE( value, js.x_min, js.x_max, -1.0f, 1.0f ); - - This->ButtonPressed( DeviceInput(js.id, JOY_LEFT, max(-level, 0.0f), now), level < -0.5f ); - This->ButtonPressed( DeviceInput(js.id, JOY_RIGHT, max(level, 0.0f), now), level > 0.5f ); - break; - } - else if( js.y_axis == cookie ) - { - float level = SCALE( value, js.y_min, js.y_max, -1.0f, 1.0f ); - - This->ButtonPressed( DeviceInput(js.id, JOY_UP, max(-level, 0.0f), now), level < -0.5f ); - This->ButtonPressed( DeviceInput(js.id, JOY_DOWN, max(level, 0.0f), now), level > 0.5f ); - break; - } - else if( js.z_axis == cookie ) - { - float level = SCALE( value, js.z_min, js.z_max, -1.0f, 1.0f ); - - This->ButtonPressed( DeviceInput(js.id, JOY_Z_UP, max(-level, 0.0f), now), level < -0.5f ); - This->ButtonPressed( DeviceInput(js.id, JOY_Z_DOWN, max(level, 0.0f), now), level > 0.5f ); - break; - } - else - { - // hash_map::operator[] is not const - hash_map::const_iterator iter; - - iter = js.mapping.find( cookie ); - if( iter != js.mapping.end() ) - { - This->ButtonPressed( DeviceInput(js.id, iter->second, value, now), value ); - break; - } - } - } - } + dev->GetButtonPresses( vPresses, int(event.elementCookie), int(event.value), now ); + for( vector >::const_iterator i = vPresses.begin(); i != vPresses.end(); ++i ) + This->ButtonPressed( i->first, i->second ); } static void RunLoopStarted( CFRunLoopObserverRef o, CFRunLoopActivity a, void *sem ) @@ -777,36 +117,8 @@ static io_iterator_t GetDeviceIterator( int usagePage, int usage ) InputHandler_Carbon::InputHandler_Carbon() : m_Sem( "Input thread started" ) { - // Find the joysticks - io_iterator_t iter = GetDeviceIterator( kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick ); - - if( iter ) - { - // Iterate over the devices and add them - io_object_t device; - int id = DEVICE_JOY1; - - while( (device = IOIteratorNext(iter)) ) - { - JoystickDevice *jd = new JoystickDevice; - - if( static_cast(jd)->Open(device) ) - { - id += jd->AssignJoystickIDs( id ); - m_vDevices.push_back( jd ); - } - else - { - delete jd; - } - - IOObjectRelease( device ); - - } - IOObjectRelease( iter ); - } - // Now find the keyboards - iter = GetDeviceIterator( kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard ); + // Find the keyboards. + io_iterator_t iter = GetDeviceIterator( kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard ); if( iter ) { @@ -825,6 +137,37 @@ InputHandler_Carbon::InputHandler_Carbon() : m_Sem( "Input thread started" ) } IOObjectRelease( iter ); } + + // Find the joysticks. + iter = GetDeviceIterator( kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick ); + + if( iter ) + { + // Iterate over the devices and add them + io_object_t device; + InputDevice id = DEVICE_JOY1; + + while( (device = IOIteratorNext(iter)) ) + { + HIDDevice *jd = new JoystickDevice; + + if( jd->Open(device) ) + { + int num = jd->AssignIDs( id ); + + enum_add( id, num ); + m_vDevices.push_back( jd ); + } + else + { + delete jd; + } + + IOObjectRelease( device ); + + } + IOObjectRelease( iter ); + } if( PREFSMAN->m_bThreadedInput ) { @@ -842,24 +185,8 @@ InputHandler_Carbon::InputHandler_Carbon() : m_Sem( "Input thread started" ) void InputHandler_Carbon::GetDevicesAndDescriptions( vector& dev, vector& desc ) { - dev.push_back( DEVICE_KEYBOARD ); - desc.push_back( "Keyboard" ); - FOREACH_CONST( HIDDevice *, m_vDevices, i ) - { - const JoystickDevice *jd = dynamic_cast(*i); - - /* This could be break since right now KeyboardDevices follow - * the JoystickDevices, but that is brittle. */ - if( !jd ) - continue; - - for( int j = 0; j < jd->NumberOfSticks(); ++j ) - { - dev.push_back( jd->GetStick(j).id ); - desc.push_back( jd->GetDescription() ); - } - } + (*i)->GetDevicesAndDescriptions( dev, desc ); } /* diff --git a/stepmania/src/archutils/Darwin/HIDDevice.cpp b/stepmania/src/archutils/Darwin/HIDDevice.cpp new file mode 100644 index 0000000000..5a3097dae8 --- /dev/null +++ b/stepmania/src/archutils/Darwin/HIDDevice.cpp @@ -0,0 +1,239 @@ +#include "global.h" +#include "HIDDevice.h" +#include "RageUtil.h" + +HIDDevice::HIDDevice() : m_Interface( NULL ), m_Queue( NULL ), m_bRunning( false ) +{ +} + +HIDDevice::~HIDDevice() +{ + if( m_Queue ) + { + CFRunLoopSourceRef runLoopSource; + + if( m_bRunning ) + CALL( m_Queue, stop ); + if( (runLoopSource = CALL(m_Queue, getAsyncEventSource)) ) + { + mach_port_deallocate( mach_task_self(), CALL(m_Queue, getAsyncPort) ); + CFRunLoopSourceInvalidate( runLoopSource ); + CFRelease( runLoopSource ); + } + + CALL( m_Queue, dispose ); + CALL( m_Queue, Release ); + } + if( m_Interface ) + { + CALL( m_Interface, close ); + CALL( m_Interface, Release ); + } +} + +bool HIDDevice::Open( io_object_t device ) +{ + IOReturn ret; + CFMutableDictionaryRef properties; + kern_return_t result; + + result = IORegistryEntryCreateCFProperties( device, &properties, kCFAllocatorDefault, kNilOptions ); + if ( result != KERN_SUCCESS || !properties ) + { + LOG->Warn( "Couldn't get properties." ); + return false; + } + + CFStringRef productRef = (CFStringRef)CFDictionaryGetValue( properties, CFSTR(kIOHIDProductKey) ); + + if( productRef ) + { + m_sDescription = CFStringGetCStringPtr( productRef, CFStringGetSystemEncoding() ); + } + else + { + CFTypeRef vidRef = (CFTypeRef)CFDictionaryGetValue( properties, CFSTR(kIOHIDVendorIDKey) ); + CFTypeRef pidRef = (CFTypeRef)CFDictionaryGetValue( properties, CFSTR(kIOHIDProductIDKey) ); + int vid, pid; + + if( vidRef && !IntValue(vidRef, &vid) ) + vid = 0; + if( pidRef && !IntValue(pidRef, &pid) ) + pid = 0; + m_sDescription = ssprintf( "%04x:%04x", vid, pid ); + } + + CFArrayRef logicalDevices; + + if ( !(logicalDevices = (CFArrayRef)CFDictionaryGetValue(properties, CFSTR(kIOHIDElementKey))) ) + { + CFRelease( properties ); + return false; + } + CFRange r = { 0, CFArrayGetCount(logicalDevices) }; + + CFArrayApplyFunction( logicalDevices, r, HIDDevice::AddLogicalDevice, this ); + + CFRelease( properties ); + + // Create the interface + IOCFPlugInInterface **plugInInterface; + HRESULT hresult; + SInt32 score; + + ret = IOCreatePlugInInterfaceForService( device, kIOHIDDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, &plugInInterface, &score ); + if( ret != kIOReturnSuccess ) + { + PrintIOErr( ret, "Failed to create plugin interface." ); + return false; + } + + // Call a method of the plugin to create the device interface + CFUUIDBytes bytes = CFUUIDGetUUIDBytes( kIOHIDDeviceInterfaceID ); + + hresult = CALL( plugInInterface, QueryInterface, bytes, (void **)&m_Interface ); + + CALL( plugInInterface, Release ); + + if( hresult != S_OK ) + { + LOG->Warn( "Couldn't get device interface from plugin interface." ); + m_Interface = NULL; + return false; + } + + // open the interface + if( (ret = CALL(m_Interface, open, 0)) != kIOReturnSuccess ) + { + PrintIOErr( ret, "Failed to open the interface." ); + CALL( m_Interface, Release ); + m_Interface = NULL; + return false; + } + + // alloc/create queue + m_Queue = CALL( m_Interface, allocQueue ); + if( !m_Queue ) + { + LOG->Warn( "Couldn't allocate a queue." ); + return false; + } + + if( (ret = CALL(m_Queue, create, 0, 32)) != kIOReturnSuccess ) + { + PrintIOErr( ret, "Failed to create the queue." ); + CALL( m_Queue, Release ); + m_Queue = NULL; + return false; + } + + Open(); + return true; +} + +void HIDDevice::StartQueue( CFRunLoopRef loopRef, IOHIDCallbackFunction callback, void *target, int refCon ) +{ + CFRunLoopSourceRef runLoopSource; + // This creates a run loop source and a mach port. They are released in the dtor. + IOReturn ret = CALL( m_Queue, createAsyncEventSource, &runLoopSource ); + + if( ret != kIOReturnSuccess ) + { + PrintIOErr( ret, "Failed to create async event source." ); + return; + } + + if( !CFRunLoopContainsSource(loopRef, runLoopSource, kCFRunLoopDefaultMode) ) + CFRunLoopAddSource( loopRef, runLoopSource, kCFRunLoopDefaultMode ); + + CALL( m_Queue, setEventCallout, callback, target, (void *)refCon ); + + if( ret != kIOReturnSuccess ) + { + PrintIOErr( ret, "Failed to set the call back." ); + return; + } + + // start the queue + ret = CALL( m_Queue, start ); + + if( ret != kIOReturnSuccess ) + { + PrintIOErr( ret, "Failed to start the queue." ); + return; + } + m_bRunning = true; +} + +void HIDDevice::AddLogicalDevice( const void *value, void *context ) +{ + if( CFGetTypeID(CFTypeRef(value)) != CFDictionaryGetTypeID() ) + return; + + CFDictionaryRef dict = CFDictionaryRef( value ); + HIDDevice *This = (HIDDevice *)context; + CFArrayRef elements; + CFTypeRef object; + int usage, usagePage; + CFTypeID numID = CFNumberGetTypeID(); + + // Get usage page + object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementUsagePageKey) ); + if( !object || CFGetTypeID(object) != numID || !IntValue(object, &usagePage) ) + return; + + // Get usage + object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementUsageKey) ); + if( !object || CFGetTypeID(object) != numID || !IntValue(object, &usage) ) + return; + + if( !(elements = (CFArrayRef)CFDictionaryGetValue( dict, CFSTR(kIOHIDElementKey))) ) + return; + + if( !This->AddLogicalDevice(usagePage, usage) ) + return; + + CFRange r = { 0, CFArrayGetCount(elements) }; + + CFArrayApplyFunction( elements, r, HIDDevice::AddElement, This ); +} + +void HIDDevice::AddElement( const void *value, void *context ) +{ + if( CFGetTypeID(CFTypeRef(value)) != CFDictionaryGetTypeID() ) + return; + + CFDictionaryRef dict = CFDictionaryRef( value ); + HIDDevice *This = (HIDDevice *)context; + CFTypeRef object; + CFTypeID numID = CFNumberGetTypeID(); + int cookie, usage, usagePage; + CFArrayRef elements; + + // Recursively add elements + if( (elements = (CFArrayRef)CFDictionaryGetValue(dict, CFSTR(kIOHIDElementKey))) ) + { + CFRange r = { 0, CFArrayGetCount(elements) }; + + CFArrayApplyFunction( elements, r, AddElement, context ); + } + + // Get usage page + object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementUsagePageKey) ); + if( !object || CFGetTypeID(object) != numID || !IntValue(object, &usagePage) ) + return; + + // Get usage + object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementUsageKey) ); + if( !object || CFGetTypeID(object) != numID || !IntValue(object, &usage) ) + return; + + + // Get cookie + object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementCookieKey) ); + if( !object || CFGetTypeID(object) != numID || !IntValue(object, &cookie) ) + return; + This->AddElement( usagePage, usage, cookie, dict ); +} + diff --git a/stepmania/src/archutils/Darwin/HIDDevice.h b/stepmania/src/archutils/Darwin/HIDDevice.h new file mode 100644 index 0000000000..d25da68251 --- /dev/null +++ b/stepmania/src/archutils/Darwin/HIDDevice.h @@ -0,0 +1,86 @@ +#ifndef HIDDEVICE_H +#define HIDDEVICE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "RageLog.h" +#include "RageInputDevice.h" + +/* A few helper functions. */ + +// The result needs to be released. +static inline CFNumberRef CFInt( int n ) +{ + return CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &n ); +} + +static inline void PrintIOErr( IOReturn err, const char *s ) +{ + LOG->Warn( "%s - %s(%x,%d)", s, mach_error_string(err), err, err & 0xFFFFFF ); +} + +static inline Boolean IntValue( const void *o, int *n ) +{ + return CFNumberGetValue( CFNumberRef(o), kCFNumberIntType, n ); +} + +/* + * This is just awful, these aren't objects, treating them as such leads + * to: (*object)->function(object [, argument]...) + * Instead, do: CALL(object, function [, argument]...) + */ +#define CALL(o,f,...) (*(o))->f((o), ## __VA_ARGS__) + +class HIDDevice +{ +private: + IOHIDDeviceInterface **m_Interface; + IOHIDQueueInterface **m_Queue; + bool m_bRunning; + RString m_sDescription; + + static void AddLogicalDevice( const void *value, void *context ); + static void AddElement( const void *value, void *context ); + +protected: + virtual bool AddLogicalDevice( int usagePage, int usage ) = 0; + virtual void AddElement( int usagePage, int usage, int cookie, const CFDictionaryRef dict ) = 0; + virtual void Open() = 0; + + inline void AddElementToQueue( int cookie ) + { + CALL( m_Queue, addElement, IOHIDElementCookie(cookie), 0 ); + } +public: + HIDDevice(); + virtual ~HIDDevice(); + + bool Open( io_object_t device ); + void StartQueue( CFRunLoopRef loopRef, IOHIDCallbackFunction callback, void *target, int refCon ); + inline const RString& GetDescription() const { return m_sDescription; } + + + virtual void GetButtonPresses( vector >& vPresses, int cookie, + int value, const RageTimer& now ) const = 0; + + /* + * Returns the number of IDs assigned starting from startID. This is not meaningful for devices like + * keyboards that all share the same InputDevice id. + */ + virtual int AssignIDs( InputDevice startID ) { return 0; } + virtual void GetDevicesAndDescriptions( vector& dev, vector& desc ) const = 0; +}; + + + +#endif + diff --git a/stepmania/src/archutils/Darwin/JoystickDevice.cpp b/stepmania/src/archutils/Darwin/JoystickDevice.cpp new file mode 100644 index 0000000000..a78616d890 --- /dev/null +++ b/stepmania/src/archutils/Darwin/JoystickDevice.cpp @@ -0,0 +1,184 @@ +#include "global.h" +#include "JoystickDevice.h" +#include "Foreach.h" +#include "EnumHelper.h" +#include "RageUtil.h" + +using namespace std; +using __gnu_cxx::hash_map; + + +Joystick::Joystick() : id( DEVICE_NONE ), + x_axis( DeviceButton_Invalid ), + y_axis( DeviceButton_Invalid ), + z_axis( DeviceButton_Invalid ), + x_min( 0 ), y_min( 0 ), z_min( 0 ), + x_max( 0 ), y_max( 0 ), z_max( 0 ) +{ +} + + +bool JoystickDevice::AddLogicalDevice( int usagePage, int usage ) +{ + if( usagePage != kHIDPage_GenericDesktop || usage != kHIDUsage_GD_Joystick ) + return false; + m_vSticks.push_back( Joystick() ); + return true; +} + +void JoystickDevice::AddElement( int usagePage, int usage, int cookie, const CFDictionaryRef dict ) +{ + CFTypeRef object; + CFTypeID numID = CFNumberGetTypeID(); + + Joystick& js = m_vSticks.back(); + + switch( usagePage ) + { + case kHIDPage_GenericDesktop: + { + int min = 0; + int max = 0; + + object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementMinKey) ); + if( object && CFGetTypeID(object) == numID ) + IntValue( object, &min ); + + object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementMaxKey) ); + if( object && CFGetTypeID(object) == numID ) + IntValue( object, &max ); + + switch( usage ) + { + case kHIDUsage_GD_X: + js.x_axis = cookie; + js.x_min = min; + js.x_max = max; + break; + case kHIDUsage_GD_Y: + js.y_axis = cookie; + js.y_min = min; + js.y_max = max; + break; + case kHIDUsage_GD_Z: + js.z_axis = cookie; + js.z_min = min; + js.z_max = max; + break; + case kHIDUsage_GD_DPadUp: + js.mapping[cookie] = JOY_UP; + break; + case kHIDUsage_GD_DPadDown: + js.mapping[cookie] = JOY_DOWN; + break; + case kHIDUsage_GD_DPadRight: + js.mapping[cookie] = JOY_RIGHT; + break; + case kHIDUsage_GD_DPadLeft: + js.mapping[cookie] = JOY_LEFT; + break; + default: + return; + } + break; + } + case kHIDPage_Button: + { + // button n has usage = n, subtract 1 to ensure + // button 1 = JOY_BUTTON_1 + const DeviceButton buttonID = enum_add2( JOY_BUTTON_1, usage - 1 ); + + if( buttonID <= JOY_BUTTON_32 ) + js.mapping[cookie] = buttonID; + break; + } + default: + return; + } // end switch (usagePage) +} + +void JoystickDevice::Open() +{ + // Add elements to the queue for each Joystick + FOREACH_CONST( Joystick, m_vSticks, i ) + { + const Joystick& js = *i; + + if( js.x_axis ) + AddElementToQueue( js.x_axis ); + if( js.y_axis ) + AddElementToQueue( js.y_axis ); + if( js.z_axis ) + AddElementToQueue( js.z_axis ); + + for( hash_map::const_iterator j = js.mapping.begin(); j != js.mapping.end(); ++j ) + AddElementToQueue( j->first ); + } +} + +void JoystickDevice::GetButtonPresses( vector >& vPresses, int cookie, + int value, const RageTimer& now ) const +{ + typedef pair dib; + FOREACH_CONST( Joystick, m_vSticks, i ) + { + const Joystick& js = *i; + + if( js.x_axis == cookie ) + { + float level = SCALE( value, js.x_min, js.x_max, -1.0f, 1.0f ); + + vPresses.push_back( dib(DeviceInput(js.id, JOY_LEFT, max(-level, 0.0f), now), level < -0.5f) ); + vPresses.push_back( dib(DeviceInput(js.id, JOY_RIGHT, max(level, 0.0f), now), level > 0.5f) ); + break; + } + else if( js.y_axis == cookie ) + { + float level = SCALE( value, js.y_min, js.y_max, -1.0f, 1.0f ); + + vPresses.push_back( dib(DeviceInput(js.id, JOY_UP, max(-level, 0.0f), now), level < -0.5f) ); + vPresses.push_back( dib(DeviceInput(js.id, JOY_DOWN, max(level, 0.0f), now), level > 0.5f) ); + break; + } + else if( js.z_axis == cookie ) + { + float level = SCALE( value, js.z_min, js.z_max, -1.0f, 1.0f ); + + vPresses.push_back( dib(DeviceInput(js.id, JOY_Z_UP, max(-level, 0.0f), now), level < -0.5f) ); + vPresses.push_back( dib(DeviceInput(js.id, JOY_Z_DOWN, max(level, 0.0f), now), level > 0.5f) ); + break; + } + else + { + // hash_map::operator[] is not const + hash_map::const_iterator iter; + + iter = js.mapping.find( cookie ); + if( iter != js.mapping.end() ) + { + vPresses.push_back( dib(DeviceInput(js.id, iter->second, value, now), value) ); + break; + } + } + } +} + +int JoystickDevice::AssignIDs( InputDevice startID ) +{ + FOREACH( Joystick, m_vSticks, i ) + { + i->id = InputDevice( startID ); + enum_add( startID, 1 ); + } + return m_vSticks.size(); +} + +void JoystickDevice::GetDevicesAndDescriptions( vector& dev, vector& desc ) const +{ + FOREACH_CONST( Joystick, m_vSticks, i ) + { + dev.push_back( i->id ); + desc.push_back( GetDescription() ); + } +} + diff --git a/stepmania/src/archutils/Darwin/JoystickDevice.h b/stepmania/src/archutils/Darwin/JoystickDevice.h new file mode 100644 index 0000000000..097426e555 --- /dev/null +++ b/stepmania/src/archutils/Darwin/JoystickDevice.h @@ -0,0 +1,37 @@ +#ifndef JOYSTICK_DEVICE_H +#define JOYSTICK_DEVICE_H + +#include "HIDDevice.h" +#include + +struct Joystick +{ + InputDevice id; + // map cookie to button + __gnu_cxx::hash_map mapping; + int x_axis, y_axis, z_axis; + int x_min, y_min, z_min; + int x_max, y_max, z_max; + + Joystick(); +}; + +class JoystickDevice : public HIDDevice +{ +private: + vector m_vSticks; + +protected: + bool AddLogicalDevice( int usagePage, int usage ); + void AddElement( int usagePage, int usage, int cookie, const CFDictionaryRef dict ); + void Open(); + +public: + void GetButtonPresses( vector >& vPresses, int cookie, + int value, const RageTimer& now ) const; + int AssignIDs( InputDevice startID ); + void GetDevicesAndDescriptions( vector& dev, vector& desc ) const; +}; + + +#endif diff --git a/stepmania/src/archutils/Darwin/KeyboardDevice.cpp b/stepmania/src/archutils/Darwin/KeyboardDevice.cpp new file mode 100644 index 0000000000..06e717c623 --- /dev/null +++ b/stepmania/src/archutils/Darwin/KeyboardDevice.cpp @@ -0,0 +1,176 @@ +#include "global.h" +#include "KeyboardDevice.h" + +using namespace __gnu_cxx; + +bool KeyboardDevice::AddLogicalDevice( int usagePage, int usage ) +{ + return usagePage == kHIDPage_GenericDesktop && usage == kHIDUsage_GD_Keyboard; +} + +void KeyboardDevice::AddElement( int usagePage, int usage, int cookie, const CFDictionaryRef dict ) +{ + if( usagePage != kHIDPage_KeyboardOrKeypad ) + return; + + if( usage < kHIDUsage_KeyboardA ) + return; + + if( usage <= kHIDUsage_KeyboardZ ) + { + m_Mapping[cookie] = enum_add2( KEY_Ca, usage - kHIDUsage_KeyboardA ); + return; + } + + // KEY_C0 = KEY_C1 - 1, kHIDUsage_Keyboard0 = kHIDUsage_Keyboard9 + 1 + if( usage <= kHIDUsage_Keyboard9 ) + { + m_Mapping[cookie] = enum_add2( KEY_C1, usage - kHIDUsage_Keyboard1 ); + return; + } + + if( usage >= kHIDUsage_KeyboardF1 && usage <= kHIDUsage_KeyboardF12 ) + { + m_Mapping[cookie] = enum_add2( KEY_F1, usage - kHIDUsage_KeyboardF1 ); + return; + } + + if( usage >= kHIDUsage_KeyboardF13 && usage <= kHIDUsage_KeyboardF16 ) + { + m_Mapping[cookie] = enum_add2( KEY_F13, usage - kHIDUsage_KeyboardF13 ); + return; + } + + // keypad 0 is again backward + if( usage >= kHIDUsage_Keypad1 && usage <= kHIDUsage_Keypad9 ) + { + m_Mapping[cookie] = enum_add2( KEY_KP_C1, usage - kHIDUsage_Keypad1 ); + return; + } + +#define OTHER(n) (enum_add2(KEY_OTHER_0, (n))) + + // [0, 8] + if( usage >= kHIDUsage_KeyboardF17 && usage <= kHIDUsage_KeyboardExecute ) + { + m_Mapping[cookie] = OTHER( 0 + usage - kHIDUsage_KeyboardF17 ); + return; + } + + // [9, 19] + if( usage >= kHIDUsage_KeyboardSelect && usage <= kHIDUsage_KeyboardVolumeDown ) + { + m_Mapping[cookie] = OTHER( 9 + usage - kHIDUsage_KeyboardSelect ); + return; + } + + // [20, 31] + if( usage >= kHIDUsage_KeypadEqualSignAS400 && usage <= kHIDUsage_KeyboardCancel ) + { + m_Mapping[cookie] = OTHER( 20 + usage - kHIDUsage_KeypadEqualSignAS400 ); + return; + } + + // [32, 37] + // XXX kHIDUsage_KeyboardClearOrAgain + if( usage >= kHIDUsage_KeyboardSeparator && usage <= kHIDUsage_KeyboardExSel ) + { + m_Mapping[cookie] = OTHER( 32 + usage - kHIDUsage_KeyboardSeparator ); + return; + } + +#define X(x,y) case x: m_Mapping[cookie] = y; return + + // Time for the special cases + switch( usage ) + { + X( kHIDUsage_Keyboard0, KEY_C0 ); + X( kHIDUsage_Keypad0, KEY_KP_C0 ); + X( kHIDUsage_KeyboardReturnOrEnter, KEY_ENTER ); + X( kHIDUsage_KeyboardEscape, KEY_ESC ); + X( kHIDUsage_KeyboardDeleteOrBackspace, KEY_BACK ); + X( kHIDUsage_KeyboardTab, KEY_TAB ); + X( kHIDUsage_KeyboardSpacebar, KEY_SPACE ); + X( kHIDUsage_KeyboardHyphen, KEY_HYPHEN ); + X( kHIDUsage_KeyboardEqualSign, KEY_EQUAL ); + X( kHIDUsage_KeyboardOpenBracket, KEY_LBRACKET ); + X( kHIDUsage_KeyboardCloseBracket, KEY_RBRACKET ); + X( kHIDUsage_KeyboardBackslash, KEY_BACKSLASH ); + X( kHIDUsage_KeyboardNonUSPound, KEY_HASH ); + X( kHIDUsage_KeyboardSemicolon, KEY_SEMICOLON ); + X( kHIDUsage_KeyboardQuote, KEY_SQUOTE ); + X( kHIDUsage_KeyboardGraveAccentAndTilde, KEY_ACCENT ); + X( kHIDUsage_KeyboardComma, KEY_COMMA ); + X( kHIDUsage_KeyboardPeriod, KEY_PERIOD ); + X( kHIDUsage_KeyboardSlash, KEY_SLASH ); + X( kHIDUsage_KeyboardCapsLock, KEY_CAPSLOCK ); + X( kHIDUsage_KeyboardPrintScreen, KEY_PRTSC ); + X( kHIDUsage_KeyboardScrollLock, KEY_SCRLLOCK ); + X( kHIDUsage_KeyboardPause, OTHER(38) ); + X( kHIDUsage_KeyboardInsert, KEY_INSERT ); + X( kHIDUsage_KeyboardHome, KEY_HOME ); + X( kHIDUsage_KeyboardPageUp, KEY_PGUP ); + X( kHIDUsage_KeyboardDeleteForward, KEY_DEL ); + X( kHIDUsage_KeyboardEnd, KEY_END ); + X( kHIDUsage_KeyboardPageDown, KEY_PGDN ); + X( kHIDUsage_KeyboardRightArrow, KEY_RIGHT ); + X( kHIDUsage_KeyboardLeftArrow, KEY_LEFT ); + X( kHIDUsage_KeyboardDownArrow, KEY_DOWN ); + X( kHIDUsage_KeyboardUpArrow, KEY_UP ); + X( kHIDUsage_KeypadNumLock, KEY_NUMLOCK ); + X( kHIDUsage_KeypadSlash, KEY_KP_SLASH ); + X( kHIDUsage_KeypadEqualSign, KEY_KP_EQUAL ); + X( kHIDUsage_KeypadAsterisk, KEY_KP_ASTERISK ); + X( kHIDUsage_KeypadHyphen, KEY_KP_HYPHEN ); + X( kHIDUsage_KeypadPlus, KEY_KP_PLUS ); + X( kHIDUsage_KeypadEnter, KEY_KP_ENTER ); + X( kHIDUsage_KeypadPeriod, KEY_KP_PERIOD ); + X( kHIDUsage_KeyboardNonUSBackslash, OTHER(39) ); + X( kHIDUsage_KeyboardApplication, OTHER(40) ); + X( kHIDUsage_KeyboardClear, KEY_NUMLOCK ); // XXX + X( kHIDUsage_KeyboardHelp, KEY_INSERT ); + X( kHIDUsage_KeyboardMenu, KEY_MENU ); + // XXX kHIDUsage_KeyboardLockingCapsLock + // XXX kHIDUsage_KeyboardLockingNumLock + // XXX kHIDUsage_KeyboardLockingScrollLock + X( kHIDUsage_KeypadComma, KEY_KP_PERIOD ); // XXX + X( kHIDUsage_KeyboardReturn, KEY_ENTER ); + X( kHIDUsage_KeyboardPrior, OTHER(41) ); + X( kHIDUsage_KeyboardLeftControl, KEY_LCTRL ); + X( kHIDUsage_KeyboardLeftShift, KEY_LSHIFT ); + X( kHIDUsage_KeyboardLeftAlt, KEY_LALT ); + X( kHIDUsage_KeyboardLeftGUI, KEY_LMETA ); + X( kHIDUsage_KeyboardRightControl, KEY_RCTRL ); + X( kHIDUsage_KeyboardRightShift, KEY_RSHIFT ); + X( kHIDUsage_KeyboardRightAlt, KEY_RALT ); + X( kHIDUsage_KeyboardRightGUI, KEY_RMETA ); + } +#undef X +#undef OTHER +} + +void KeyboardDevice::Open() +{ + for( hash_map::const_iterator i = m_Mapping.begin(); i != m_Mapping.end(); ++i ) + AddElementToQueue( i->first ); +} + +void KeyboardDevice::GetButtonPresses( vector >& vPresses, int cookie, + int value, const RageTimer& now ) const +{ + hash_map::const_iterator iter = m_Mapping.find( cookie ); + + if( iter != m_Mapping.end() ) + vPresses.push_back( pair(DeviceInput(DEVICE_KEYBOARD, iter->second, value, now), value) ); + +} + +void KeyboardDevice::GetDevicesAndDescriptions( vector& dev, vector& desc ) const +{ + if( dev.size() && dev[0] == DEVICE_KEYBOARD ) + return; + dev.insert( dev.begin(), DEVICE_KEYBOARD ); + desc.insert( desc.begin(), "Keyboard" ); +} + + diff --git a/stepmania/src/archutils/Darwin/KeyboardDevice.h b/stepmania/src/archutils/Darwin/KeyboardDevice.h new file mode 100644 index 0000000000..1eff4a9e46 --- /dev/null +++ b/stepmania/src/archutils/Darwin/KeyboardDevice.h @@ -0,0 +1,24 @@ +#ifndef KEYBOARD_DEVICE_H +#define KEYBOARD_DEVICE_H + +#include "HIDDevice.h" +#include + +class KeyboardDevice : public HIDDevice +{ +private: + __gnu_cxx::hash_map m_Mapping; + +protected: + bool AddLogicalDevice( int usagePage, int usage ); + void AddElement( int usagePage, int usage, int cookie, const CFDictionaryRef dict ); + void Open(); + +public: + void GetButtonPresses( vector >& vPresses, int cookie, + int value, const RageTimer& now ) const; + void GetDevicesAndDescriptions( vector& dev, vector& desc ) const; +}; + + +#endif