Add Input thread. Remove DictValue since I managed to break it converting from a macro to a static inline function. That took about an hour to track down.

This commit is contained in:
Steve Checkoway
2005-10-17 11:04:31 +00:00
parent c2bc8c3b61
commit 19631fe280
@@ -32,11 +32,6 @@ 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 CFTypeRef DictValue( CFDictionaryRef d, const char *k )
{
return CFDictionaryGetValue( d, k );
}
static inline int IntValue( const void *o, int *n )
{
return CFNumberGetValue( CFNumberRef(o), kCFNumberIntType, n );
@@ -84,9 +79,10 @@ public:
JoystickDevice();
~JoystickDevice();
bool Open( io_object_t device, int num, InputHandler_Carbon *handler );
bool Open( io_object_t device, int foo, void *bar );
// returns the number of IDs assigned starting from startID
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; }
@@ -96,7 +92,7 @@ JoystickDevice::JoystickDevice() : mInterface(NULL), mQueue(NULL), mRunning(fals
{
}
bool JoystickDevice::Open( io_object_t device, int num, InputHandler_Carbon *handler )
bool JoystickDevice::Open( io_object_t device, int foo, void *bar )
{
IOReturn ret;
CFMutableDictionaryRef properties;
@@ -114,7 +110,7 @@ bool JoystickDevice::Open( io_object_t device, int num, InputHandler_Carbon *han
CFArrayRef sticks;
if ( !(sticks = (CFArrayRef)DictValue(properties, kIOHIDElementKey)) )
if ( !(sticks = (CFArrayRef)CFDictionaryGetValue(properties, CFSTR(kIOHIDElementKey))) )
{
CFRelease( properties );
return false;
@@ -191,44 +187,9 @@ bool JoystickDevice::Open( io_object_t device, int num, InputHandler_Carbon *han
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)
for( hash_map<int,int>::const_iterator j = js.mapping.begin(); j != js.mapping.end(); ++j )
CALL( mQueue, addElement, IOHIDElementCookie(j->first), 0 );
}
// add the callback
CFRunLoopSourceRef runLoopSource;
ret = CALL( mQueue, createAsyncEventSource, &runLoopSource );
if( ret != kIOReturnSuccess )
{
PrintIOErr( ret, "Failed to create async event source." );
return false;
}
CFRunLoopRef runLoop;
runLoop = CFRunLoopRef( GetCFRunLoopFromEventLoop(GetMainEventLoop()) );
if( !CFRunLoopContainsSource(runLoop, runLoopSource, kCFRunLoopDefaultMode) )
CFRunLoopAddSource( runLoop, runLoopSource, kCFRunLoopDefaultMode );
CALL( mQueue, setEventCallout, InputHandler_Carbon::QueueCallBack, handler, (void *)num );
if( ret != kIOReturnSuccess )
{
PrintIOErr( ret, "Failed to set the call back." );
return false;
}
// start the queue
ret = CALL( mQueue, start );
if( ret != kIOReturnSuccess )
{
PrintIOErr( ret, "Failed to start the queue." );
return false;
}
mRunning = true;
return true;
}
@@ -274,19 +235,19 @@ void JoystickDevice::AddJoystick( const void *value, void *context )
CFTypeID numID = CFNumberGetTypeID();
// Get usage page
object = DictValue( dict, kIOHIDElementUsagePageKey );
object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementUsagePageKey) );
if( !object || CFGetTypeID(object) != numID || !IntValue(object, &usagePage) )
return;
// Get usage
object = DictValue( dict, kIOHIDElementUsageKey );
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)DictValue(dict, kIOHIDElementKey)) )
if( !(elements = (CFArrayRef)CFDictionaryGetValue(dict, CFSTR(kIOHIDElementKey))) )
return;
Joystick js;
@@ -304,6 +265,43 @@ int JoystickDevice::AssignJoystickIDs( int startID )
return mSticks.size();
}
void JoystickDevice::StartQueue( CFRunLoopRef loopRef, int num, InputHandler_Carbon *handler )
{
CFRunLoopSourceRef runLoopSource;
IOReturn ret = CALL( mQueue, createAsyncEventSource, &runLoopSource );
if( ret != kIOReturnSuccess )
{
PrintIOErr( ret, "Failed to create async event source." );
return;
}
CFRunLoopRef runLoop;
runLoop = CFRunLoopRef( GetCFRunLoopFromEventLoop(GetMainEventLoop()) );
if( !CFRunLoopContainsSource(runLoop, runLoopSource, kCFRunLoopDefaultMode) )
CFRunLoopAddSource( runLoop, runLoopSource, kCFRunLoopDefaultMode );
CALL( mQueue, setEventCallout, InputHandler_Carbon::QueueCallBack, handler, (void *)num );
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;
}
// Callback
static void AddElement( const void *value, void *context )
{
@@ -318,7 +316,7 @@ static void AddElement( const void *value, void *context )
CFArrayRef elements;
// Recursively add elements
if( (elements = (CFArrayRef)DictValue(dict, kIOHIDElementKey)) )
if( (elements = (CFArrayRef)CFDictionaryGetValue(dict, CFSTR(kIOHIDElementKey))) )
{
CFRange r = { 0, CFArrayGetCount(elements) };
@@ -326,18 +324,18 @@ static void AddElement( const void *value, void *context )
}
// Get usage page
object = DictValue( dict, kIOHIDElementUsagePageKey );
object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementUsagePageKey) );
if( !object || CFGetTypeID(object) != numID || !IntValue(object, &usagePage) )
return;
// Get usage
object = DictValue( dict, kIOHIDElementUsageKey );
object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementUsageKey) );
if( !object || CFGetTypeID(object) != numID || !IntValue(object, &usage) )
return;
// Get cookie
object = DictValue( dict, kIOHIDElementCookieKey );
object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementCookieKey) );
if( !object || CFGetTypeID(object) != numID || !IntValue(object, &cookie) )
return;
@@ -348,11 +346,11 @@ static void AddElement( const void *value, void *context )
int min = 0;
int max = 0;
object = DictValue( dict, kIOHIDElementMinKey );
object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementMinKey) );
if( object && CFGetTypeID(object) == numID )
IntValue( object, &min );
object = DictValue( dict, kIOHIDElementMaxKey );
object = CFDictionaryGetValue( dict, CFSTR(kIOHIDElementMaxKey) );
if( object && CFGetTypeID(object) == numID )
IntValue( object, &max );
@@ -496,8 +494,38 @@ OSStatus InputHandler_Carbon::EventHandler( EventHandlerCallRef callRef, EventRe
return 0;
}
static void RunLoopStarted( CFRunLoopObserverRef o, CFRunLoopActivity a, void *sem )
{
CFRelease(o); // we don't need this any longer
((RageSemaphore *)sem)->Post();
}
int InputHandler_Carbon::Run(void *data)
{
InputHandler_Carbon *This = (InputHandler_Carbon *)data;
CFRunLoopRef loopRef = CFRunLoopGetCurrent();
int n = 0;
CFRetain(loopRef);
FOREACH( JoystickDevice *, This->mDevices, i )
(*i)->StartQueue( loopRef, n++, This );
This->mLoopRef = loopRef;
/* The function copies the information out of the structure, so the memory pointed
* to by context does not need to persist beyond the function call.
*/
CFRunLoopObserverContext context = { 0, &This->mSem, NULL, NULL, NULL };
CFRunLoopObserverRef o = CFRunLoopObserverCreate( kCFAllocatorDefault, kCFRunLoopEntry,
false, 0, RunLoopStarted, &context);
CFRunLoopAddObserver( loopRef, o, kCFRunLoopDefaultMode );
CFRunLoopRun();
return 0;
}
InputHandler_Carbon::~InputHandler_Carbon()
{
CFRunLoopStop( CFRunLoopRef(mLoopRef) );
mInputThread.Wait();
FOREACH( JoystickDevice *, mDevices, i )
delete *i;
if( mMasterPort )
@@ -506,7 +534,7 @@ InputHandler_Carbon::~InputHandler_Carbon()
DisposeEventHandlerUPP( mEventHandlerUPP );
}
InputHandler_Carbon::InputHandler_Carbon()
InputHandler_Carbon::InputHandler_Carbon() : mSem("Input thread started")
{
// Install a Carbon Event handler
mEventHandlerUPP = NewEventHandlerUPP( EventHandler );
@@ -574,7 +602,7 @@ InputHandler_Carbon::InputHandler_Carbon()
{
JoystickDevice *jd = new JoystickDevice;
if( jd->Open(device, mDevices.size(), this) )
if( jd->Open(device, 0, this) )
{
id += jd->AssignJoystickIDs( id );
mDevices.push_back( jd );
@@ -589,6 +617,11 @@ InputHandler_Carbon::InputHandler_Carbon()
}
IOObjectRelease( iter );
mInputThread.SetName( "Input thread." );
mInputThread.Create(InputHandler_Carbon::Run, this);
// Wait for the run loop to start before returning.
mSem.Wait();
}
void InputHandler_Carbon::GetDevicesAndDescriptions( vector<InputDevice>& dev, vector<CString>& desc )