Prepare code for adding a KeyboardDevice by putting common code into a Device abstract class.

This commit is contained in:
Steve Checkoway
2005-10-18 09:00:53 +00:00
parent fd65b7e34e
commit 85e0e3a1ec
@@ -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 );