mirror of
https://github.com/libretro/Play-.git
synced 2025-02-02 06:32:00 +00:00
188 lines
6.2 KiB
C++
188 lines
6.2 KiB
C++
#include "PH_HidMacOSX.h"
|
|
#include <stdexcept>
|
|
|
|
CPH_HidMacOSX::CPH_HidMacOSX()
|
|
{
|
|
m_bindings[PS2::CControllerInfo::ANALOG_LEFT_X] = std::make_shared<CSimulatedAxisBinding>(kHIDUsage_KeyboardD, kHIDUsage_KeyboardG);
|
|
m_bindings[PS2::CControllerInfo::ANALOG_LEFT_Y] = std::make_shared<CSimulatedAxisBinding>(kHIDUsage_KeyboardR, kHIDUsage_KeyboardF);
|
|
|
|
m_bindings[PS2::CControllerInfo::ANALOG_RIGHT_X] = std::make_shared<CSimulatedAxisBinding>(kHIDUsage_KeyboardH, kHIDUsage_KeyboardK);
|
|
m_bindings[PS2::CControllerInfo::ANALOG_RIGHT_Y] = std::make_shared<CSimulatedAxisBinding>(kHIDUsage_KeyboardU, kHIDUsage_KeyboardJ);
|
|
|
|
m_bindings[PS2::CControllerInfo::START] = std::make_shared<CSimpleBinding>(kHIDUsage_KeyboardReturnOrEnter);
|
|
m_bindings[PS2::CControllerInfo::SELECT] = std::make_shared<CSimpleBinding>(kHIDUsage_KeyboardRightShift);
|
|
m_bindings[PS2::CControllerInfo::DPAD_LEFT] = std::make_shared<CSimpleBinding>(kHIDUsage_KeyboardLeftArrow);
|
|
m_bindings[PS2::CControllerInfo::DPAD_RIGHT] = std::make_shared<CSimpleBinding>(kHIDUsage_KeyboardRightArrow);
|
|
m_bindings[PS2::CControllerInfo::DPAD_UP] = std::make_shared<CSimpleBinding>(kHIDUsage_KeyboardUpArrow);
|
|
m_bindings[PS2::CControllerInfo::DPAD_DOWN] = std::make_shared<CSimpleBinding>(kHIDUsage_KeyboardDownArrow);
|
|
m_bindings[PS2::CControllerInfo::SQUARE] = std::make_shared<CSimpleBinding>(kHIDUsage_KeyboardA);
|
|
m_bindings[PS2::CControllerInfo::CROSS] = std::make_shared<CSimpleBinding>(kHIDUsage_KeyboardZ);
|
|
m_bindings[PS2::CControllerInfo::TRIANGLE] = std::make_shared<CSimpleBinding>(kHIDUsage_KeyboardS);
|
|
m_bindings[PS2::CControllerInfo::CIRCLE] = std::make_shared<CSimpleBinding>(kHIDUsage_KeyboardX);
|
|
|
|
m_hidManager = IOHIDManagerCreate(kCFAllocatorDefault, 0);
|
|
{
|
|
CFDictionaryRef matchingDict = CreateDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard);
|
|
IOHIDManagerSetDeviceMatching(m_hidManager, matchingDict);
|
|
CFRelease(matchingDict);
|
|
}
|
|
IOHIDManagerScheduleWithRunLoop(m_hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
|
IOHIDManagerOpen(m_hidManager, kIOHIDOptionsTypeNone);
|
|
IOHIDManagerRegisterInputValueCallback(m_hidManager, InputValueCallbackStub, this);
|
|
}
|
|
|
|
CPH_HidMacOSX::~CPH_HidMacOSX()
|
|
{
|
|
IOHIDManagerClose(m_hidManager, 0);
|
|
}
|
|
|
|
void CPH_HidMacOSX::Update(uint8* ram)
|
|
{
|
|
for(auto listenerIterator(std::begin(m_listeners));
|
|
listenerIterator != std::end(m_listeners); listenerIterator++)
|
|
{
|
|
auto* listener(*listenerIterator);
|
|
|
|
for(unsigned int i = 0; i < PS2::CControllerInfo::MAX_BUTTONS; i++)
|
|
{
|
|
const auto& binding = m_bindings[i];
|
|
if(!binding) continue;
|
|
uint32 value = binding->GetValue();
|
|
auto currentButtonId = static_cast<PS2::CControllerInfo::BUTTON>(i);
|
|
if(PS2::CControllerInfo::IsAxis(currentButtonId))
|
|
{
|
|
listener->SetAxisState(0, currentButtonId, value & 0xFF, ram);
|
|
}
|
|
else
|
|
{
|
|
listener->SetButtonState(0, currentButtonId, value != 0, ram);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CPadHandler::FactoryFunction CPH_HidMacOSX::GetFactoryFunction()
|
|
{
|
|
//Needs to be created in the same thread as UI
|
|
return std::bind(&CPH_HidMacOSX::PadHandlerFactory, new CPH_HidMacOSX());
|
|
}
|
|
|
|
CPadHandler* CPH_HidMacOSX::PadHandlerFactory(CPH_HidMacOSX* handler)
|
|
{
|
|
return handler;
|
|
}
|
|
|
|
CFMutableDictionaryRef CPH_HidMacOSX::CreateDeviceMatchingDictionary(uint32 usagePage, uint32 usage)
|
|
{
|
|
CFMutableDictionaryRef result = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
|
|
if(result == NULL) throw std::runtime_error("CFDictionaryCreateMutable failed.");
|
|
if(usagePage != 0)
|
|
{
|
|
// Add key for device type to refine the matching dictionary.
|
|
CFNumberRef pageCFNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usagePage);
|
|
if(pageCFNumberRef == NULL) throw std::runtime_error("CFNumberCreate failed.");
|
|
CFDictionarySetValue(result, CFSTR(kIOHIDDeviceUsagePageKey), pageCFNumberRef);
|
|
CFRelease(pageCFNumberRef);
|
|
// note: the usage is only valid if the usage page is also defined
|
|
if(usage != 0)
|
|
{
|
|
CFNumberRef usageCFNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage);
|
|
if(usageCFNumberRef == NULL) throw std::runtime_error("CFNumberCreate failed.");
|
|
CFDictionarySetValue(result, CFSTR(kIOHIDDeviceUsageKey), usageCFNumberRef);
|
|
CFRelease(usageCFNumberRef);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void CPH_HidMacOSX::InputValueCallbackStub(void* context, IOReturn result, void* sender, IOHIDValueRef valueRef)
|
|
{
|
|
reinterpret_cast<CPH_HidMacOSX*>(context)->InputValueCallback(valueRef);
|
|
}
|
|
|
|
void CPH_HidMacOSX::InputValueCallback(IOHIDValueRef valueRef)
|
|
{
|
|
IOHIDElementRef elementRef = IOHIDValueGetElement(valueRef);
|
|
uint32 usage = IOHIDElementGetUsage(elementRef);
|
|
uint32 usagePage = IOHIDElementGetUsagePage(elementRef);
|
|
CFIndex state = IOHIDValueGetIntegerValue(valueRef);
|
|
if(usagePage != kHIDPage_KeyboardOrKeypad) return;
|
|
for(auto bindingIterator(std::begin(m_bindings));
|
|
bindingIterator != std::end(m_bindings); bindingIterator++)
|
|
{
|
|
const auto& binding = (*bindingIterator);
|
|
if(!binding) continue;
|
|
binding->ProcessEvent(usage, state);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
CPH_HidMacOSX::CSimpleBinding::CSimpleBinding(uint32 keyCode)
|
|
: m_keyCode(keyCode)
|
|
, m_state(0)
|
|
{
|
|
|
|
}
|
|
|
|
CPH_HidMacOSX::CSimpleBinding::~CSimpleBinding()
|
|
{
|
|
|
|
}
|
|
|
|
void CPH_HidMacOSX::CSimpleBinding::ProcessEvent(uint32 keyCode, uint32 state)
|
|
{
|
|
if(keyCode != m_keyCode) return;
|
|
m_state = state;
|
|
}
|
|
|
|
uint32 CPH_HidMacOSX::CSimpleBinding::GetValue() const
|
|
{
|
|
return m_state;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------
|
|
|
|
CPH_HidMacOSX::CSimulatedAxisBinding::CSimulatedAxisBinding(uint32 negativeKeyCode, uint32 positiveKeyCode)
|
|
: m_negativeKeyCode(negativeKeyCode)
|
|
, m_positiveKeyCode(positiveKeyCode)
|
|
, m_negativeState(0)
|
|
, m_positiveState(0)
|
|
{
|
|
|
|
}
|
|
|
|
CPH_HidMacOSX::CSimulatedAxisBinding::~CSimulatedAxisBinding()
|
|
{
|
|
|
|
}
|
|
|
|
void CPH_HidMacOSX::CSimulatedAxisBinding::ProcessEvent(uint32 keyCode, uint32 state)
|
|
{
|
|
if(keyCode == m_negativeKeyCode)
|
|
{
|
|
m_negativeState = state;
|
|
}
|
|
|
|
if(keyCode == m_positiveKeyCode)
|
|
{
|
|
m_positiveState = state;
|
|
}
|
|
}
|
|
|
|
uint32 CPH_HidMacOSX::CSimulatedAxisBinding::GetValue() const
|
|
{
|
|
uint32 value = 0x7F;
|
|
|
|
if(m_negativeState)
|
|
{
|
|
value -= 0x7F;
|
|
}
|
|
if(m_positiveState)
|
|
{
|
|
value += 0x7F;
|
|
}
|
|
|
|
return value;
|
|
}
|