better event handling

This commit is contained in:
Jack Andersen 2015-04-22 11:48:23 -10:00
parent edaebc5e50
commit c1dc218bd1
12 changed files with 85 additions and 45 deletions

View File

@ -8,10 +8,12 @@ class CDeviceBase
{
CDeviceToken* m_token;
IHIDDevice* m_hidDev;
friend CDeviceToken;
void _deviceDisconnected();
public:
inline CDeviceBase(CDeviceToken* token, IHIDDevice* hidDev)
: m_token(token), m_hidDev(hidDev) {}
void _deviceDisconnected();
void closeDevice();
virtual void deviceDisconnected()=0;
};

View File

@ -44,8 +44,9 @@ private:
{
if (BooDeviceMatchToken(token, m_types)) {
m_tokensLock.lock();
m_tokens.insert(std::make_pair(token.getDeviceHandle(), token));
TInsertedDeviceToken inseredTok = m_tokens.insert(std::make_pair(token.getDeviceHandle(), std::move(token)));
m_tokensLock.unlock();
deviceConnected(inseredTok.first->second);
}
}
inline void _removeToken(TDeviceHandle handle)
@ -55,6 +56,7 @@ private:
{
CDeviceToken& tok = preCheck->second;
tok._deviceClose();
deviceDisconnected(tok);
m_tokensLock.lock();
m_tokens.erase(preCheck);
m_tokensLock.unlock();
@ -75,14 +77,12 @@ public:
};
/* Application must specify its interested device-types */
CDeviceFinder(EDeviceMask types, bool autoScan=true)
CDeviceFinder(EDeviceMask types)
: m_types(types), m_listener(NULL)
{
if (skDevFinder)
throw std::runtime_error("only one instance of CDeviceFinder may be constructed");
skDevFinder = this;
if (autoScan)
startScanning();
}
~CDeviceFinder()
{
@ -126,6 +126,9 @@ public:
return false;
}
virtual void deviceConnected(CDeviceToken&) {}
virtual void deviceDisconnected(CDeviceToken&) {}
};
#endif // CDEVICEFINDER_HPP

View File

@ -12,8 +12,6 @@ typedef IOHIDDeviceRef TDeviceHandle;
#elif __linux__
#endif
class CDeviceBase;
class CDeviceToken
{
unsigned m_vendorId;
@ -22,10 +20,21 @@ class CDeviceToken
std::string m_productName;
TDeviceHandle m_devHandle;
friend CDeviceBase;
friend class CDeviceBase;
CDeviceBase* m_connectedDev;
friend class CDeviceFinder;
inline void _deviceClose()
{
printf("CLOSE %p\n", this);
if (m_connectedDev)
m_connectedDev->_deviceDisconnected();
m_connectedDev = NULL;
}
public:
CDeviceToken(const CDeviceToken&) = delete;
CDeviceToken(CDeviceToken&&) = default;
inline CDeviceToken(unsigned vid, unsigned pid, const char* vname, const char* pname, TDeviceHandle handle)
: m_vendorId(vid), m_productId(pid), m_devHandle(handle), m_connectedDev(NULL)
{
@ -43,20 +52,12 @@ public:
inline bool isDeviceOpen() const {return m_connectedDev;}
inline CDeviceBase* openAndGetDevice()
{
printf("OPEN %p\n", this);
if (!m_connectedDev)
m_connectedDev = BooDeviceNew(this);
return m_connectedDev;
}
inline void _deviceClose()
{
if (m_connectedDev)
m_connectedDev->deviceDisconnected();
m_connectedDev = NULL;
}
inline CDeviceToken operator =(const CDeviceToken& other)
{return CDeviceToken(other);}
inline bool operator ==(const CDeviceToken& rhs) const
{return m_devHandle == rhs.m_devHandle;}
inline bool operator <(const CDeviceToken& rhs) const

View File

@ -7,11 +7,7 @@ class CDolphinSmashAdapter final : public CDeviceBase
{
void deviceDisconnected();
public:
CDolphinSmashAdapter(CDeviceToken* token, IHIDDevice* hidDev)
: CDeviceBase(token, hidDev)
{
}
CDolphinSmashAdapter(CDeviceToken* token, IHIDDevice* hidDev);
};
#endif // CDOLPHINSMASHADAPTER_HPP

View File

@ -49,12 +49,13 @@ unix:!macx:SOURCES += \
$$PWD/src/inputdev/CHIDListenerUdev.cpp
macx:SOURCES += \
$$PWD/src/mac/CCGLContext.cpp
$$PWD/src/mac/CCGLContext.cpp \
$$PWD/src/inputdev/CHIDDeviceIOKit.cpp \
$$PWD/src/inputdev/CHIDListenerIOKit.cpp
macx:OBJECTIVE_SOURCES += \
$$PWD/src/mac/CCGLCocoaView.mm \
$$PWD/src/inputdev/CHIDDeviceIOKit.mm \
$$PWD/src/inputdev/CHIDListenerIOKit.mm
win32:SOURCES += \
$$PWD/src/win/CWGLContext.cpp \

View File

@ -5,11 +5,18 @@
void CDeviceBase::_deviceDisconnected()
{
m_token->m_connectedDev = NULL;
deviceDisconnected();
m_token = NULL;
m_hidDev->deviceDisconnected();
m_hidDev->_deviceDisconnected();
m_hidDev = NULL;
}
void CDeviceBase::closeDevice()
{
if (m_token)
m_token->_deviceClose();
}

View File

@ -1,6 +1,13 @@
#include "inputdev/CDolphinSmashAdapter.hpp"
#include <stdio.h>
CDolphinSmashAdapter::CDolphinSmashAdapter(CDeviceToken* token, IHIDDevice* hidDev)
: CDeviceBase(token, hidDev)
{
printf("I've been plugged!!\n");
}
void CDolphinSmashAdapter::deviceDisconnected()
{
printf("I've been unplugged!!\n");
}

View File

@ -5,6 +5,12 @@
class CHIDDeviceIOKit final : public IHIDDevice
{
IOHIDDeviceRef m_dev;
void _deviceDisconnected()
{
IOHIDDeviceClose(m_dev, kIOHIDOptionsTypeNone);
}
public:
CHIDDeviceIOKit(CDeviceToken* token)
@ -13,15 +19,12 @@ public:
IOHIDDeviceOpen(m_dev, kIOHIDOptionsTypeNone);
}
CHIDDeviceIOKit()
~CHIDDeviceIOKit()
{
IOHIDDeviceClose(m_dev, kIOHIDOptionsTypeNone);
}
void deviceDisconnected()
{
IOHIDDeviceClose(m_dev, kIOHIDOptionsTypeNone);
}
};
IHIDDevice* IHIDDeviceNew(CDeviceToken* token)

View File

@ -34,23 +34,23 @@ class CHIDListenerIOKit final : public IHIDListener
IOReturn,
void*,
IOHIDDeviceRef device)
{listener->m_finder._removeToken(device);}
{
listener->m_finder._removeToken(device);
}
static void applyDevice(IOHIDDeviceRef device, CHIDListenerIOKit* listener)
{
auto preCheck = listener->m_finder.m_tokens.find(device);
if (preCheck != listener->m_finder.m_tokens.end())
if (listener->m_finder._hasToken(device))
return;
CFIndex vid, pid;
CFNumberGetValue((CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey)), kCFNumberCFIndexType, &vid);
CFNumberGetValue((CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey)), kCFNumberCFIndexType, &pid);
CFStringRef manuf = (CFStringRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDManufacturerKey));
CFStringRef product = (CFStringRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
listener->m_finder.m_tokens.insert(std::make_pair(device,
CDeviceToken(vid, pid,
CFStringGetCStringPtr(manuf, kCFStringEncodingUTF8),
CFStringGetCStringPtr(product, kCFStringEncodingUTF8),
device)));
listener->m_finder._insertToken(CDeviceToken(vid, pid,
CFStringGetCStringPtr(manuf, kCFStringEncodingUTF8),
CFStringGetCStringPtr(product, kCFStringEncodingUTF8),
device));
}
public:

View File

@ -7,7 +7,7 @@ class CDeviceBase;
class IHIDDevice
{
friend CDeviceBase;
virtual void deviceDisconnected()=0;
virtual void _deviceDisconnected()=0;
};
#endif // IHIDDEVICE_HPP

View File

@ -5,6 +5,7 @@
#include <mutex>
#include "CDeviceToken.hpp"
typedef std::map<TDeviceHandle, CDeviceToken> TDeviceTokens;
typedef std::pair<TDeviceTokens::iterator, bool> TInsertedDeviceToken;
class CDeviceFinder;
class IHIDListener

View File

@ -3,11 +3,30 @@
#include <stdio.h>
#include <boo.hpp>
class CTestDeviceFinder : public CDeviceFinder
{
CDolphinSmashAdapter* smashAdapter = NULL;
public:
CTestDeviceFinder()
: CDeviceFinder(DEV_DOL_SMASH_ADAPTER)
{}
void deviceConnected(CDeviceToken& tok)
{
printf("CONNECTED %s %s\n", tok.getVendorName().c_str(), tok.getProductName().c_str());
smashAdapter = dynamic_cast<CDolphinSmashAdapter*>(tok.openAndGetDevice());
}
void deviceDisconnected(CDeviceToken& tok)
{
printf("DISCONNECTED %s %s\n", tok.getVendorName().c_str(), tok.getProductName().c_str());
delete smashAdapter;
smashAdapter = NULL;
}
};
int main(int argc, char** argv)
{
CDeviceFinder finder(DEV_DOL_SMASH_ADAPTER);
CDeviceToken& smashToken = finder.getTokens().begin()->second;
CDolphinSmashAdapter* smashAdapter = dynamic_cast<CDolphinSmashAdapter*>(smashToken.openAndGetDevice());
CTestDeviceFinder finder;
finder.startScanning();
IGraphicsContext* ctx = new CGraphicsContext;