Prepare code for adding a KeyboardDevice by putting common code into a Device abstract class.
This commit is contained in:
@@ -19,8 +19,6 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
using __gnu_cxx::hash_map;
|
using __gnu_cxx::hash_map;
|
||||||
|
|
||||||
static void AddElement( const void *value, void *context );
|
|
||||||
|
|
||||||
// Simple helper, still need to release it
|
// Simple helper, still need to release it
|
||||||
static inline CFNumberRef CFInt( int n )
|
static inline CFNumberRef CFInt( int n )
|
||||||
{
|
{
|
||||||
@@ -64,35 +62,67 @@ Joystick::Joystick() : id( DEVICE_NONE ),
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
class JoystickDevice
|
class Device
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
vector<Joystick> mSticks;
|
|
||||||
IOHIDDeviceInterface **mInterface;
|
IOHIDDeviceInterface **mInterface;
|
||||||
IOHIDQueueInterface **mQueue;
|
IOHIDQueueInterface **mQueue;
|
||||||
bool mRunning;
|
bool mRunning;
|
||||||
CString mDescription;
|
CString mDescription;
|
||||||
|
|
||||||
static void AddJoystick( const void *value, void *context );
|
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:
|
public:
|
||||||
JoystickDevice();
|
Device();
|
||||||
~JoystickDevice();
|
virtual ~Device();
|
||||||
|
|
||||||
bool Open( io_object_t device );
|
bool Open( io_object_t device );
|
||||||
// returns the number of IDs assigned starting from startID
|
void StartQueue( CFRunLoopRef loopRef, IOHIDCallbackFunction callback, void *target, int refCon );
|
||||||
int AssignJoystickIDs( int startID );
|
|
||||||
void StartQueue(CFRunLoopRef loopRef, int num, InputHandler_Carbon *handler);
|
|
||||||
inline int NumberOfSticks() const { return mSticks.size(); }
|
|
||||||
inline const Joystick& GetStick( int index ) const { return mSticks[index]; }
|
|
||||||
inline const CString& GetDescription() const { return mDescription; }
|
inline const CString& GetDescription() const { return mDescription; }
|
||||||
};
|
};
|
||||||
|
|
||||||
JoystickDevice::JoystickDevice() : mInterface(NULL), mQueue(NULL), mRunning(false)
|
Device::Device() : mInterface( NULL ), mQueue( NULL ), mRunning( false )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JoystickDevice::Open( io_object_t device )
|
Device::~Device()
|
||||||
|
{
|
||||||
|
if( mQueue )
|
||||||
|
{
|
||||||
|
CFRunLoopSourceRef runLoopSource;
|
||||||
|
|
||||||
|
if( mRunning )
|
||||||
|
CALL( mQueue, stop );
|
||||||
|
if( (runLoopSource = CALL(mQueue, getAsyncEventSource)) )
|
||||||
|
{
|
||||||
|
CFRunLoopRef ref;
|
||||||
|
|
||||||
|
ref = CFRunLoopRef( GetCFRunLoopFromEventLoop(GetMainEventLoop()) );
|
||||||
|
|
||||||
|
if( CFRunLoopContainsSource(ref, runLoopSource, kCFRunLoopDefaultMode) )
|
||||||
|
CFRunLoopRemoveSource( ref, runLoopSource, kCFRunLoopDefaultMode );
|
||||||
|
CFRelease( runLoopSource );
|
||||||
|
}
|
||||||
|
|
||||||
|
CALL( mQueue, dispose );
|
||||||
|
CALL( mQueue, Release );
|
||||||
|
}
|
||||||
|
if( mInterface )
|
||||||
|
{
|
||||||
|
CALL( mInterface, close );
|
||||||
|
CALL( mInterface, Release );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Device::Open( io_object_t device )
|
||||||
{
|
{
|
||||||
IOReturn ret;
|
IOReturn ret;
|
||||||
CFMutableDictionaryRef properties;
|
CFMutableDictionaryRef properties;
|
||||||
@@ -108,18 +138,16 @@ bool JoystickDevice::Open( io_object_t device )
|
|||||||
// XXX Get Device Info
|
// XXX Get Device Info
|
||||||
mDescription = "XXX Device Info";
|
mDescription = "XXX Device Info";
|
||||||
|
|
||||||
CFArrayRef sticks;
|
CFArrayRef logicalDevices;
|
||||||
|
|
||||||
if ( !(sticks = (CFArrayRef)CFDictionaryGetValue(properties, CFSTR(kIOHIDElementKey))) )
|
if ( !(logicalDevices = (CFArrayRef)CFDictionaryGetValue(properties, CFSTR(kIOHIDElementKey))) )
|
||||||
{
|
{
|
||||||
CFRelease( properties );
|
CFRelease( properties );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
size_t count = CFArrayGetCount( sticks );
|
CFRange r = { 0, CFArrayGetCount(logicalDevices) };
|
||||||
CFRange r = { 0, count };
|
|
||||||
|
|
||||||
mSticks.reserve( count );
|
CFArrayApplyFunction( logicalDevices, r, Device::AddLogicalDevice, this );
|
||||||
CFArrayApplyFunction( sticks, r, JoystickDevice::AddJoystick, this );
|
|
||||||
|
|
||||||
CFRelease( properties );
|
CFRelease( properties );
|
||||||
|
|
||||||
@@ -175,97 +203,11 @@ bool JoystickDevice::Open( io_object_t device )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add elements to the queue for each Joystick
|
Open();
|
||||||
FOREACH_CONST( Joystick, mSticks, i )
|
|
||||||
{
|
|
||||||
const Joystick& js = *i;
|
|
||||||
|
|
||||||
if( js.x_axis )
|
|
||||||
CALL( mQueue, addElement, IOHIDElementCookie(js.x_axis), 0 );
|
|
||||||
if( js.y_axis )
|
|
||||||
CALL( mQueue, addElement, IOHIDElementCookie(js.y_axis), 0 );
|
|
||||||
if( js.z_axis )
|
|
||||||
CALL( mQueue, addElement, IOHIDElementCookie(js.z_axis), 0 );
|
|
||||||
|
|
||||||
for( hash_map<int,int>::const_iterator j = js.mapping.begin(); j != js.mapping.end(); ++j )
|
|
||||||
CALL( mQueue, addElement, IOHIDElementCookie(j->first), 0 );
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
JoystickDevice::~JoystickDevice()
|
void Device::StartQueue( CFRunLoopRef loopRef, IOHIDCallbackFunction callback, void *target, int refCon )
|
||||||
{
|
|
||||||
if( mQueue )
|
|
||||||
{
|
|
||||||
CFRunLoopSourceRef runLoopSource;
|
|
||||||
|
|
||||||
if( mRunning )
|
|
||||||
CALL( mQueue, stop );
|
|
||||||
if( (runLoopSource = CALL(mQueue, getAsyncEventSource)) )
|
|
||||||
{
|
|
||||||
CFRunLoopRef ref;
|
|
||||||
|
|
||||||
ref = CFRunLoopRef( GetCFRunLoopFromEventLoop(GetMainEventLoop()) );
|
|
||||||
|
|
||||||
if( CFRunLoopContainsSource(ref, runLoopSource, kCFRunLoopDefaultMode) )
|
|
||||||
CFRunLoopRemoveSource( ref, runLoopSource, kCFRunLoopDefaultMode );
|
|
||||||
CFRelease( runLoopSource );
|
|
||||||
}
|
|
||||||
|
|
||||||
CALL( mQueue, dispose );
|
|
||||||
CALL( mQueue, Release );
|
|
||||||
}
|
|
||||||
if( mInterface )
|
|
||||||
{
|
|
||||||
CALL( mInterface, close );
|
|
||||||
CALL( mInterface, Release );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JoystickDevice::AddJoystick( const void *value, void *context )
|
|
||||||
{
|
|
||||||
if( CFGetTypeID(CFTypeRef(value)) != CFDictionaryGetTypeID() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
CFDictionaryRef dict = CFDictionaryRef( value );
|
|
||||||
JoystickDevice *This = (JoystickDevice *)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( usagePage != kHIDPage_GenericDesktop || usage != kHIDUsage_GD_Joystick )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( !(elements = (CFArrayRef)CFDictionaryGetValue(dict, CFSTR(kIOHIDElementKey))) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
Joystick js;
|
|
||||||
CFRange r = { 0, CFArrayGetCount(elements) };
|
|
||||||
|
|
||||||
CFArrayApplyFunction( elements, r, AddElement, &js );
|
|
||||||
This->mSticks.push_back( js );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int JoystickDevice::AssignJoystickIDs( int startID )
|
|
||||||
{
|
|
||||||
for( vector<Joystick>::iterator i = mSticks.begin(); i != mSticks.end(); ++i )
|
|
||||||
i->id = InputDevice( startID++ );
|
|
||||||
return mSticks.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JoystickDevice::StartQueue( CFRunLoopRef loopRef, int num, InputHandler_Carbon *handler )
|
|
||||||
{
|
{
|
||||||
CFRunLoopSourceRef runLoopSource;
|
CFRunLoopSourceRef runLoopSource;
|
||||||
IOReturn ret = CALL( mQueue, createAsyncEventSource, &runLoopSource );
|
IOReturn ret = CALL( mQueue, createAsyncEventSource, &runLoopSource );
|
||||||
@@ -283,7 +225,7 @@ void JoystickDevice::StartQueue( CFRunLoopRef loopRef, int num, InputHandler_Car
|
|||||||
if( !CFRunLoopContainsSource(runLoop, runLoopSource, kCFRunLoopDefaultMode) )
|
if( !CFRunLoopContainsSource(runLoop, runLoopSource, kCFRunLoopDefaultMode) )
|
||||||
CFRunLoopAddSource( runLoop, runLoopSource, kCFRunLoopDefaultMode );
|
CFRunLoopAddSource( runLoop, runLoopSource, kCFRunLoopDefaultMode );
|
||||||
|
|
||||||
CALL( mQueue, setEventCallout, InputHandler_Carbon::QueueCallBack, handler, (void *)num );
|
CALL( mQueue, setEventCallout, callback, target, (void *)refCon );
|
||||||
|
|
||||||
if( ret != kIOReturnSuccess )
|
if( ret != kIOReturnSuccess )
|
||||||
{
|
{
|
||||||
@@ -302,14 +244,46 @@ void JoystickDevice::StartQueue( CFRunLoopRef loopRef, int num, InputHandler_Car
|
|||||||
mRunning = true;
|
mRunning = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callback
|
void Device::AddLogicalDevice( const void *value, void *context )
|
||||||
static void AddElement( const void *value, void *context )
|
|
||||||
{
|
{
|
||||||
if( CFGetTypeID(CFTypeRef(value)) != CFDictionaryGetTypeID() )
|
if( CFGetTypeID(CFTypeRef(value)) != CFDictionaryGetTypeID() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CFDictionaryRef dict = CFDictionaryRef( value );
|
CFDictionaryRef dict = CFDictionaryRef( value );
|
||||||
Joystick& js = *(Joystick *)context;
|
Device *This = (Device *)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, Device::AddElement, This );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::AddElement( const void *value, void *context )
|
||||||
|
{
|
||||||
|
if( CFGetTypeID(CFTypeRef(value)) != CFDictionaryGetTypeID() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
CFDictionaryRef dict = CFDictionaryRef( value );
|
||||||
|
Device *This = (Device *)context;
|
||||||
CFTypeRef object;
|
CFTypeRef object;
|
||||||
CFTypeID numID = CFNumberGetTypeID();
|
CFTypeID numID = CFNumberGetTypeID();
|
||||||
int cookie, usage, usagePage;
|
int cookie, usage, usagePage;
|
||||||
@@ -338,6 +312,40 @@ static void AddElement( const void *value, void *context )
|
|||||||
object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementCookieKey) );
|
object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementCookieKey) );
|
||||||
if( !object || CFGetTypeID(object) != numID || !IntValue(object, &cookie) )
|
if( !object || CFGetTypeID(object) != numID || !IntValue(object, &cookie) )
|
||||||
return;
|
return;
|
||||||
|
This->AddElement( usagePage, usage, cookie, dict );
|
||||||
|
}
|
||||||
|
|
||||||
|
class JoystickDevice : public Device
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
vector<Joystick> mSticks;
|
||||||
|
|
||||||
|
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 mSticks.size(); }
|
||||||
|
inline const Joystick& GetStick( int index ) const { return mSticks[index]; }
|
||||||
|
};
|
||||||
|
|
||||||
|
bool JoystickDevice::AddLogicalDevice( int usagePage, int usage )
|
||||||
|
{
|
||||||
|
if( usagePage != kHIDPage_GenericDesktop || usage != kHIDUsage_GD_Joystick )
|
||||||
|
return false;
|
||||||
|
mSticks.push_back( Joystick() );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JoystickDevice::AddElement( int usagePage, int usage, int cookie, const CFDictionaryRef dict )
|
||||||
|
{
|
||||||
|
CFTypeRef object;
|
||||||
|
CFTypeID numID = CFNumberGetTypeID();
|
||||||
|
|
||||||
|
Joystick& js = mSticks.back();
|
||||||
|
|
||||||
switch( usagePage )
|
switch( usagePage )
|
||||||
{
|
{
|
||||||
@@ -403,6 +411,32 @@ static void AddElement( const void *value, void *context )
|
|||||||
} // end switch (usagePage)
|
} // end switch (usagePage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JoystickDevice::Open()
|
||||||
|
{
|
||||||
|
// Add elements to the queue for each Joystick
|
||||||
|
FOREACH_CONST( Joystick, mSticks, 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<int,int>::const_iterator j = js.mapping.begin(); j != js.mapping.end(); ++j )
|
||||||
|
AddElementToQueue( j->first );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int JoystickDevice::AssignJoystickIDs( int startID )
|
||||||
|
{
|
||||||
|
for( vector<Joystick>::iterator i = mSticks.begin(); i != mSticks.end(); ++i )
|
||||||
|
i->id = InputDevice( startID++ );
|
||||||
|
return mSticks.size();
|
||||||
|
}
|
||||||
|
|
||||||
void InputHandler_Carbon::QueueCallBack( void *target, int result, void *refcon, void *sender )
|
void InputHandler_Carbon::QueueCallBack( void *target, int result, void *refcon, void *sender )
|
||||||
{
|
{
|
||||||
// The result seems useless as you can't actually return anything...
|
// The result seems useless as you can't actually return anything...
|
||||||
@@ -478,7 +512,7 @@ int InputHandler_Carbon::Run(void *data)
|
|||||||
|
|
||||||
CFRetain(loopRef);
|
CFRetain(loopRef);
|
||||||
FOREACH( JoystickDevice *, This->mDevices, i )
|
FOREACH( JoystickDevice *, This->mDevices, i )
|
||||||
(*i)->StartQueue( loopRef, n++, This );
|
(*i)->StartQueue( loopRef, InputHandler_Carbon::QueueCallBack, This, n++ );
|
||||||
This->mLoopRef = loopRef;
|
This->mLoopRef = loopRef;
|
||||||
|
|
||||||
/* The function copies the information out of the structure, so the memory pointed
|
/* The function copies the information out of the structure, so the memory pointed
|
||||||
@@ -559,7 +593,7 @@ InputHandler_Carbon::InputHandler_Carbon() : mSem("Input thread started")
|
|||||||
{
|
{
|
||||||
JoystickDevice *jd = new JoystickDevice;
|
JoystickDevice *jd = new JoystickDevice;
|
||||||
|
|
||||||
if( jd->Open(device) )
|
if( static_cast<Device *>(jd)->Open(device) )
|
||||||
{
|
{
|
||||||
id += jd->AssignJoystickIDs( id );
|
id += jd->AssignJoystickIDs( id );
|
||||||
mDevices.push_back( jd );
|
mDevices.push_back( jd );
|
||||||
|
|||||||
Reference in New Issue
Block a user