Handle the files either skipped or not on windows.
This commit is contained in:
+2
-3
@@ -114,12 +114,11 @@ bool CsvFile::WriteFile( const RString &sPath ) const
|
||||
|
||||
bool CsvFile::WriteFile( RageFileBasic &f ) const
|
||||
{
|
||||
FOREACH_CONST( StringVector, m_vvs, line )
|
||||
for (StringVector &line : m_vvs)
|
||||
{
|
||||
RString sLine;
|
||||
FOREACH_CONST( RString, *line, value )
|
||||
for (RString sVal : line) // explicitly don't use a reference.
|
||||
{
|
||||
RString sVal = *value;
|
||||
sVal.Replace( "\"", "\"\"" ); // escape quotes to double-quotes
|
||||
sLine += "\"" + sVal + "\"";
|
||||
if( value != line->end()-1 )
|
||||
|
||||
@@ -1,499 +1,499 @@
|
||||
#include "global.h"
|
||||
#include "RageLog.h"
|
||||
#include "InputHandler_MacOSX_HID.h"
|
||||
#include "Foreach.h"
|
||||
#include "PrefsManager.h"
|
||||
#include "InputFilter.h"
|
||||
#include "archutils/Darwin/DarwinThreadHelpers.h"
|
||||
#include "archutils/Darwin/KeyboardDevice.h"
|
||||
#include "archutils/Darwin/MouseDevice.h"
|
||||
#include "archutils/Darwin/JoystickDevice.h"
|
||||
#include "archutils/Darwin/PumpDevice.h"
|
||||
|
||||
#include <IOKit/IOMessage.h>
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
REGISTER_INPUT_HANDLER_CLASS2( HID, MacOSX_HID );
|
||||
|
||||
void InputHandler_MacOSX_HID::QueueCallback( void *target, int result, void *refcon, void *sender )
|
||||
{
|
||||
// The result seems useless as you can't actually return anything...
|
||||
// refcon is the Device number
|
||||
|
||||
RageTimer now;
|
||||
InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)target;
|
||||
IOHIDQueueInterface **queue = (IOHIDQueueInterface **)sender;
|
||||
IOHIDEventStruct event;
|
||||
AbsoluteTime zeroTime = { 0, 0 };
|
||||
HIDDevice *dev = This->m_vDevices[int( refcon )];
|
||||
vector<DeviceInput> vPresses;
|
||||
|
||||
while( (result = CALL(queue, getNextEvent, &event, zeroTime, 0)) == kIOReturnSuccess )
|
||||
{
|
||||
if( event.longValueSize != 0 && event.longValue != NULL )
|
||||
{
|
||||
free( event.longValue );
|
||||
continue;
|
||||
}
|
||||
//LOG->Trace( "Got event with cookie %p, value %d", event.elementCookie, int(event.value) );
|
||||
dev->GetButtonPresses( vPresses, event.elementCookie, event.value, now );
|
||||
}
|
||||
FOREACH_CONST( DeviceInput, vPresses, i )
|
||||
INPUTFILTER->ButtonPressed( *i );
|
||||
}
|
||||
|
||||
static void RunLoopStarted( CFRunLoopObserverRef o, CFRunLoopActivity a, void *sem )
|
||||
{
|
||||
CFRunLoopObserverInvalidate( o );
|
||||
CFRelease( o ); // we don't need this any longer
|
||||
((RageSemaphore *)sem)->Post();
|
||||
}
|
||||
|
||||
int InputHandler_MacOSX_HID::Run( void *data )
|
||||
{
|
||||
InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)data;
|
||||
|
||||
This->m_LoopRef = CFRunLoopGetCurrent();
|
||||
CFRetain( This->m_LoopRef );
|
||||
|
||||
This->StartDevices();
|
||||
{
|
||||
const RString sError = SetThreadPrecedence( 1.0f );
|
||||
if( !sError.empty() )
|
||||
LOG->Warn( "Could not set precedence of the input thread: %s", sError.c_str() );
|
||||
}
|
||||
// Add an observer for the start of the run loop
|
||||
{
|
||||
/* 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->m_Sem, NULL, NULL, NULL };
|
||||
CFRunLoopObserverRef o = CFRunLoopObserverCreate( kCFAllocatorDefault, kCFRunLoopEntry,
|
||||
false, 0, RunLoopStarted, &context);
|
||||
CFRunLoopAddObserver( This->m_LoopRef, o, kCFRunLoopDefaultMode );
|
||||
}
|
||||
|
||||
/* Add a source for ending the run loop. This serves two purposes:
|
||||
* 1. it provides a way to terminate the run loop when IH_MacOSX_HID exists,
|
||||
* and 2. it ensures that CFRunLoopRun() doesn't return immediately if
|
||||
* there are no other sources. */
|
||||
{
|
||||
/* Being a little tricky here, the perform callback takes a void* and
|
||||
* returns nothing. CFRunLoopStop takes a CFRunLoopRef (a pointer) so
|
||||
* cast the function and pass the loop ref. */
|
||||
void *info = This->m_LoopRef;
|
||||
void (*perform)(void *) = (void (*)(void *))CFRunLoopStop;
|
||||
// { version, info, retain, release, copyDescription, equal, hash, schedule, cancel, perform }
|
||||
CFRunLoopSourceContext context = { 0, info, NULL, NULL, NULL, NULL, NULL, NULL, NULL, perform };
|
||||
|
||||
// Pass 1 so that it is called after all inputs have been handled (they will have order = 0)
|
||||
This->m_SourceRef = CFRunLoopSourceCreate( kCFAllocatorDefault, 1, &context );
|
||||
|
||||
CFRunLoopAddSource( This->m_LoopRef, This->m_SourceRef, kCFRunLoopDefaultMode );
|
||||
}
|
||||
CFRunLoopRun();
|
||||
LOG->Trace( "Shutting down input handler thread..." );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InputHandler_MacOSX_HID::DeviceAdded( void *refCon, io_iterator_t )
|
||||
{
|
||||
InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)refCon;
|
||||
|
||||
LockMut( This->m_ChangeLock );
|
||||
This->m_bChanged = true;
|
||||
}
|
||||
|
||||
void InputHandler_MacOSX_HID::DeviceChanged( void *refCon, io_service_t service, natural_t messageType, void *arg )
|
||||
{
|
||||
if( messageType == kIOMessageServiceIsTerminated )
|
||||
{
|
||||
InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)refCon;
|
||||
|
||||
LockMut( This->m_ChangeLock );
|
||||
This->m_bChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
// m_LoopRef needs to be set before this is called
|
||||
void InputHandler_MacOSX_HID::StartDevices()
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
ASSERT( m_LoopRef );
|
||||
FOREACH( HIDDevice *, m_vDevices, i )
|
||||
(*i)->StartQueue( m_LoopRef, InputHandler_MacOSX_HID::QueueCallback, this, n++ );
|
||||
|
||||
CFRunLoopSourceRef runLoopSource = IONotificationPortGetRunLoopSource( m_NotifyPort );
|
||||
|
||||
CFRunLoopAddSource( m_LoopRef, runLoopSource, kCFRunLoopDefaultMode );
|
||||
}
|
||||
|
||||
InputHandler_MacOSX_HID::~InputHandler_MacOSX_HID()
|
||||
{
|
||||
FOREACH( HIDDevice *, m_vDevices, i )
|
||||
delete *i;
|
||||
if( PREFSMAN->m_bThreadedInput )
|
||||
{
|
||||
CFRunLoopSourceSignal( m_SourceRef );
|
||||
CFRunLoopWakeUp( m_LoopRef );
|
||||
m_InputThread.Wait();
|
||||
CFRelease( m_SourceRef );
|
||||
CFRelease( m_LoopRef );
|
||||
LOG->Trace( "Input handler thread shut down." );
|
||||
}
|
||||
|
||||
FOREACH( io_iterator_t, m_vIters, i )
|
||||
IOObjectRelease( *i );
|
||||
IONotificationPortDestroy( m_NotifyPort );
|
||||
}
|
||||
|
||||
static CFDictionaryRef GetMatchingDictionary( int usagePage, int usage )
|
||||
{
|
||||
// Build the matching dictionary.
|
||||
CFMutableDictionaryRef dict;
|
||||
|
||||
if( (dict = IOServiceMatching(kIOHIDDeviceKey)) == NULL )
|
||||
FAIL_M( "Couldn't create a matching dictionary." );
|
||||
// Refine the search by only looking for joysticks
|
||||
CFNumberRef usagePageRef = CFInt( usagePage );
|
||||
CFNumberRef usageRef = CFInt( usage );
|
||||
|
||||
CFDictionarySetValue( dict, CFSTR(kIOHIDPrimaryUsagePageKey), usagePageRef );
|
||||
CFDictionarySetValue( dict, CFSTR(kIOHIDPrimaryUsageKey), usageRef );
|
||||
|
||||
// Cleanup after ourselves
|
||||
CFRelease( usagePageRef );
|
||||
CFRelease( usageRef );
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
// Factor this out because nothing else in IH_C::AddDevices() needs to know the type of the device.
|
||||
static HIDDevice *MakeDevice( InputDevice id )
|
||||
{
|
||||
if( id == DEVICE_KEYBOARD )
|
||||
return new KeyboardDevice;
|
||||
/*
|
||||
if( id == DEVICE_MOUSE )
|
||||
return new MouseDevice;
|
||||
*/
|
||||
if( IsJoystick(id) )
|
||||
return new JoystickDevice;
|
||||
if( IsPump(id) )
|
||||
return new PumpDevice;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void InputHandler_MacOSX_HID::AddDevices( int usagePage, int usage, InputDevice &id )
|
||||
{
|
||||
io_iterator_t iter;
|
||||
CFDictionaryRef dict = GetMatchingDictionary( usagePage, usage );
|
||||
kern_return_t ret = IOServiceAddMatchingNotification( m_NotifyPort, kIOFirstMatchNotification, dict,
|
||||
InputHandler_MacOSX_HID::DeviceAdded, this, &iter );
|
||||
io_object_t device;
|
||||
|
||||
if( ret != KERN_SUCCESS )
|
||||
return;
|
||||
|
||||
m_vIters.push_back( iter );
|
||||
|
||||
// Iterate over the devices and add them
|
||||
while( (device = IOIteratorNext(iter)) )
|
||||
{
|
||||
LOG->Trace( "\tFound device %d", id );
|
||||
HIDDevice *dev = MakeDevice( id );
|
||||
int num;
|
||||
|
||||
if( !dev )
|
||||
{
|
||||
LOG->Trace( "\t\tInvalid id, deleting device" );
|
||||
IOObjectRelease( device );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !dev->Open(device) || (num = dev->AssignIDs(id)) == -1 )
|
||||
{
|
||||
LOG->Trace( "\tFailed top open or assign id, deleting device" );
|
||||
delete dev;
|
||||
IOObjectRelease( device );
|
||||
continue;
|
||||
}
|
||||
io_iterator_t i;
|
||||
|
||||
enum_add( id, num );
|
||||
m_vDevices.push_back( dev );
|
||||
|
||||
ret = IOServiceAddInterestNotification(
|
||||
m_NotifyPort, device, kIOGeneralInterest,
|
||||
InputHandler_MacOSX_HID::DeviceChanged,
|
||||
this, &i
|
||||
);
|
||||
|
||||
if( ret == KERN_SUCCESS )
|
||||
m_vIters.push_back( i );
|
||||
else
|
||||
LOG->Trace( "\t\tFailed to add device changed notification, deleting device" );
|
||||
IOObjectRelease( device );
|
||||
}
|
||||
}
|
||||
|
||||
InputHandler_MacOSX_HID::InputHandler_MacOSX_HID() : m_Sem( "Input thread started" ), m_ChangeLock( "Input handler change lock" )
|
||||
{
|
||||
InputDevice id = DEVICE_KEYBOARD;
|
||||
|
||||
// Set up the notify ports.
|
||||
m_NotifyPort = IONotificationPortCreate( kIOMasterPortDefault );
|
||||
|
||||
// Add devices.
|
||||
LOG->Trace( "Finding keyboards" );
|
||||
AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard, id );
|
||||
|
||||
LOG->Trace( "Finding mice" );
|
||||
AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse, id );
|
||||
|
||||
LOG->Trace( "Finding joysticks" );
|
||||
id = DEVICE_JOY1;
|
||||
AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick, id );
|
||||
AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad, id );
|
||||
LOG->Trace( "Finding pump" );
|
||||
id = DEVICE_PUMP1;
|
||||
AddDevices( kHIDPage_VendorDefinedStart, 0x0001, id ); // Pump pads use the first vendor specific usage page.
|
||||
m_bChanged = false;
|
||||
|
||||
if( PREFSMAN->m_bThreadedInput )
|
||||
{
|
||||
m_InputThread.SetName( "Input thread" );
|
||||
m_InputThread.Create( InputHandler_MacOSX_HID::Run, this );
|
||||
// Wait for the run loop to start before returning.
|
||||
m_Sem.Wait();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_LoopRef = CFRunLoopRef( GetCFRunLoopFromEventLoop(GetMainEventLoop()) );
|
||||
CFRetain( m_LoopRef );
|
||||
StartDevices();
|
||||
}
|
||||
}
|
||||
|
||||
void InputHandler_MacOSX_HID::GetDevicesAndDescriptions( vector<InputDeviceInfo>& vDevices )
|
||||
{
|
||||
FOREACH_CONST( HIDDevice *, m_vDevices, i )
|
||||
(*i)->GetDevicesAndDescriptions( vDevices );
|
||||
}
|
||||
|
||||
RString InputHandler_MacOSX_HID::GetDeviceSpecificInputString( const DeviceInput &di )
|
||||
{
|
||||
if( di.device == DEVICE_KEYBOARD )
|
||||
{
|
||||
#define OTHER(n) (KEY_OTHER_0 + (n))
|
||||
switch( di.button )
|
||||
{
|
||||
case KEY_DEL: return "del";
|
||||
case KEY_BACK: return "delete";
|
||||
case KEY_ENTER: return "return";
|
||||
case KEY_LALT: return "left option";
|
||||
case KEY_RALT: return "right option";
|
||||
case KEY_LMETA: return "left cmd";
|
||||
case KEY_RMETA: return "right cmd";
|
||||
case KEY_INSERT: return "help";
|
||||
case OTHER(0): return "F17";
|
||||
case OTHER(1): return "F18";
|
||||
case OTHER(2): return "F19";
|
||||
case OTHER(3): return "F20";
|
||||
case OTHER(4): return "F21";
|
||||
case OTHER(5): return "F22";
|
||||
case OTHER(6): return "F23";
|
||||
case OTHER(7): return "F25";
|
||||
case OTHER(8): return "execute";
|
||||
case OTHER(9): return "select";
|
||||
case OTHER(10): return "stop";
|
||||
case OTHER(11): return "again";
|
||||
case OTHER(12): return "undo";
|
||||
case OTHER(13): return "cut";
|
||||
case OTHER(14): return "copy";
|
||||
case OTHER(15): return "paste";
|
||||
case OTHER(16): return "find";
|
||||
case OTHER(17): return "mute";
|
||||
case OTHER(18): return "volume up";
|
||||
case OTHER(19): return "volume down";
|
||||
case OTHER(20): return "AS/400 equal";
|
||||
case OTHER(21): return "international 1";
|
||||
case OTHER(22): return "international 2";
|
||||
case OTHER(23): return "international 3";
|
||||
case OTHER(24): return "international 4";
|
||||
case OTHER(25): return "international 5";
|
||||
case OTHER(26): return "international 6";
|
||||
case OTHER(27): return "international 7";
|
||||
case OTHER(28): return "international 8";
|
||||
case OTHER(29): return "international 9";
|
||||
case OTHER(30): return "lang 1";
|
||||
case OTHER(31): return "lang 2";
|
||||
case OTHER(32): return "lang 3";
|
||||
case OTHER(33): return "lang 4";
|
||||
case OTHER(34): return "lang 5";
|
||||
case OTHER(35): return "lang 6";
|
||||
case OTHER(36): return "lang 7";
|
||||
case OTHER(37): return "lang 8";
|
||||
case OTHER(38): return "lang 9";
|
||||
case OTHER(39): return "alt erase";
|
||||
case OTHER(40): return "sys req";
|
||||
case OTHER(41): return "cancel";
|
||||
case OTHER(42): return "separator";
|
||||
case OTHER(43): return "out";
|
||||
case OTHER(44): return "oper";
|
||||
case OTHER(45): return "clear/again"; // XXX huh?
|
||||
case OTHER(46): return "cr sel/props"; // XXX
|
||||
case OTHER(47): return "ex sel";
|
||||
case OTHER(48): return "non US backslash";
|
||||
case OTHER(49): return "application";
|
||||
case OTHER(50): return "prior";
|
||||
default: break;
|
||||
}
|
||||
#undef OTHER
|
||||
}
|
||||
if( di.device == DEVICE_PUMP1 || di.device == DEVICE_PUMP2 )
|
||||
{
|
||||
switch( di.button )
|
||||
{
|
||||
case JOY_BUTTON_1: return "UL";
|
||||
case JOY_BUTTON_2: return "UR";
|
||||
case JOY_BUTTON_3: return "MID";
|
||||
case JOY_BUTTON_4: return "DL";
|
||||
case JOY_BUTTON_5: return "DR";
|
||||
case JOY_BUTTON_6: return "Esc";
|
||||
case JOY_BUTTON_7: return "P2 UL";
|
||||
case JOY_BUTTON_8: return "P2 UR";
|
||||
case JOY_BUTTON_9: return "P2 MID";
|
||||
case JOY_BUTTON_10: return "P2 DL";
|
||||
case JOY_BUTTON_11: return "P2 DR";
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
return InputHandler::GetDeviceSpecificInputString( di );
|
||||
}
|
||||
|
||||
wchar_t InputHandler_MacOSX_HID::DeviceButtonToChar( DeviceButton button, bool bUseCurrentKeyModifiers )
|
||||
{
|
||||
// KeyTranslate maps these keys to a character. They shouldn't be mapped to any character.
|
||||
switch( button )
|
||||
{
|
||||
default:
|
||||
if( (button >= KEY_F1 && button <= KEY_F16) )
|
||||
return L'\0';
|
||||
break;
|
||||
case KEY_UP:
|
||||
case KEY_DOWN:
|
||||
case KEY_LEFT:
|
||||
case KEY_RIGHT:
|
||||
case KEY_ESC:
|
||||
case KEY_TAB:
|
||||
case KEY_ENTER:
|
||||
case KEY_PRTSC:
|
||||
case KEY_SCRLLOCK:
|
||||
case KEY_PAUSE:
|
||||
case KEY_DEL:
|
||||
case KEY_HOME:
|
||||
case KEY_END:
|
||||
case KEY_PGUP:
|
||||
case KEY_PGDN:
|
||||
case KEY_NUMLOCK:
|
||||
case KEY_KP_ENTER:
|
||||
return L'\0';
|
||||
}
|
||||
|
||||
// Find the USB key code for this DeviceButton
|
||||
UInt8 iMacVirtualKey;
|
||||
if( KeyboardDevice::DeviceButtonToMacVirtualKey( button, iMacVirtualKey ) )
|
||||
{
|
||||
UInt32 modifiers = 0;
|
||||
if( bUseCurrentKeyModifiers )
|
||||
modifiers = GetCurrentKeyModifiers();
|
||||
|
||||
// todo: handle Caps Lock -freem
|
||||
|
||||
SInt16 iCurrentKeyScript = GetScriptManagerVariable( smKeyScript );
|
||||
SInt16 iCurrentKeyLayoutID = GetScriptVariable( iCurrentKeyScript, smScriptKeys );
|
||||
static SInt16 iLastKeyLayoutID = !iCurrentKeyLayoutID; // Just be different.
|
||||
static UInt32 iDeadKeyState;
|
||||
static UCKeyboardLayout **KeyLayout;
|
||||
|
||||
if( iCurrentKeyLayoutID != iLastKeyLayoutID )
|
||||
{
|
||||
iDeadKeyState = 0;
|
||||
KeyLayout = (UCKeyboardLayout **)GetResource( 'uchr', iCurrentKeyLayoutID );
|
||||
iLastKeyLayoutID = iCurrentKeyLayoutID;
|
||||
}
|
||||
if( KeyLayout )
|
||||
{
|
||||
UInt32 keyboardType = LMGetKbdType();
|
||||
UInt32 nModifiers = bUseCurrentKeyModifiers ? GetCurrentKeyModifiers() : 0;
|
||||
UniChar unicodeInputString[4];
|
||||
UniCharCount length;
|
||||
OSStatus status = UCKeyTranslate( *KeyLayout, iMacVirtualKey, kUCKeyActionDown, nModifiers,
|
||||
keyboardType, 0, &iDeadKeyState, ARRAYLEN(unicodeInputString),
|
||||
&length, unicodeInputString );
|
||||
|
||||
if( status )
|
||||
return L'\0';
|
||||
|
||||
CFStringRef inputString = CFStringCreateWithCharacters( NULL, unicodeInputString, length );
|
||||
char utf8InputString[7]; // Max size is 6 (although really only 4 are used) + null.
|
||||
|
||||
if( !CFStringGetCString(inputString, utf8InputString, 7, kCFStringEncodingUTF8) )
|
||||
{
|
||||
CFRelease( inputString );
|
||||
return L'\0';
|
||||
}
|
||||
|
||||
wchar_t ch = utf8_get_char( utf8InputString );
|
||||
|
||||
CFRelease( inputString );
|
||||
return ch == INVALID_CHAR ? L'\0' : ch;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fall back on the 'KCHR' resource.
|
||||
static unsigned long state = 0;
|
||||
static Ptr keymap = NULL;
|
||||
Ptr new_keymap;
|
||||
|
||||
new_keymap = (Ptr)GetScriptManagerVariable(smKCHRCache);
|
||||
if( new_keymap != keymap )
|
||||
{
|
||||
keymap = new_keymap;
|
||||
state = 0;
|
||||
}
|
||||
// XXX: Only returns ascii. é will be returned as e.
|
||||
return KeyTranslate( keymap, UInt16(iMacVirtualKey)|modifiers, &state ) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
return InputHandler::DeviceButtonToChar( button, bUseCurrentKeyModifiers );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2005, 2006 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#include "global.h"
|
||||
#include "RageLog.h"
|
||||
#include "InputHandler_MacOSX_HID.h"
|
||||
#include "Foreach.h"
|
||||
#include "PrefsManager.h"
|
||||
#include "InputFilter.h"
|
||||
#include "archutils/Darwin/DarwinThreadHelpers.h"
|
||||
#include "archutils/Darwin/KeyboardDevice.h"
|
||||
#include "archutils/Darwin/MouseDevice.h"
|
||||
#include "archutils/Darwin/JoystickDevice.h"
|
||||
#include "archutils/Darwin/PumpDevice.h"
|
||||
|
||||
#include <IOKit/IOMessage.h>
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
REGISTER_INPUT_HANDLER_CLASS2( HID, MacOSX_HID );
|
||||
|
||||
void InputHandler_MacOSX_HID::QueueCallback( void *target, int result, void *refcon, void *sender )
|
||||
{
|
||||
// The result seems useless as you can't actually return anything...
|
||||
// refcon is the Device number
|
||||
|
||||
RageTimer now;
|
||||
InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)target;
|
||||
IOHIDQueueInterface **queue = (IOHIDQueueInterface **)sender;
|
||||
IOHIDEventStruct event;
|
||||
AbsoluteTime zeroTime = { 0, 0 };
|
||||
HIDDevice *dev = This->m_vDevices[int( refcon )];
|
||||
vector<DeviceInput> vPresses;
|
||||
|
||||
while( (result = CALL(queue, getNextEvent, &event, zeroTime, 0)) == kIOReturnSuccess )
|
||||
{
|
||||
if( event.longValueSize != 0 && event.longValue != NULL )
|
||||
{
|
||||
free( event.longValue );
|
||||
continue;
|
||||
}
|
||||
//LOG->Trace( "Got event with cookie %p, value %d", event.elementCookie, int(event.value) );
|
||||
dev->GetButtonPresses( vPresses, event.elementCookie, event.value, now );
|
||||
}
|
||||
for (DeviceInput &i : vPresses)
|
||||
INPUTFILTER->ButtonPressed( i );
|
||||
}
|
||||
|
||||
static void RunLoopStarted( CFRunLoopObserverRef o, CFRunLoopActivity a, void *sem )
|
||||
{
|
||||
CFRunLoopObserverInvalidate( o );
|
||||
CFRelease( o ); // we don't need this any longer
|
||||
((RageSemaphore *)sem)->Post();
|
||||
}
|
||||
|
||||
int InputHandler_MacOSX_HID::Run( void *data )
|
||||
{
|
||||
InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)data;
|
||||
|
||||
This->m_LoopRef = CFRunLoopGetCurrent();
|
||||
CFRetain( This->m_LoopRef );
|
||||
|
||||
This->StartDevices();
|
||||
{
|
||||
const RString sError = SetThreadPrecedence( 1.0f );
|
||||
if( !sError.empty() )
|
||||
LOG->Warn( "Could not set precedence of the input thread: %s", sError.c_str() );
|
||||
}
|
||||
// Add an observer for the start of the run loop
|
||||
{
|
||||
/* 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->m_Sem, NULL, NULL, NULL };
|
||||
CFRunLoopObserverRef o = CFRunLoopObserverCreate( kCFAllocatorDefault, kCFRunLoopEntry,
|
||||
false, 0, RunLoopStarted, &context);
|
||||
CFRunLoopAddObserver( This->m_LoopRef, o, kCFRunLoopDefaultMode );
|
||||
}
|
||||
|
||||
/* Add a source for ending the run loop. This serves two purposes:
|
||||
* 1. it provides a way to terminate the run loop when IH_MacOSX_HID exists,
|
||||
* and 2. it ensures that CFRunLoopRun() doesn't return immediately if
|
||||
* there are no other sources. */
|
||||
{
|
||||
/* Being a little tricky here, the perform callback takes a void* and
|
||||
* returns nothing. CFRunLoopStop takes a CFRunLoopRef (a pointer) so
|
||||
* cast the function and pass the loop ref. */
|
||||
void *info = This->m_LoopRef;
|
||||
void (*perform)(void *) = (void (*)(void *))CFRunLoopStop;
|
||||
// { version, info, retain, release, copyDescription, equal, hash, schedule, cancel, perform }
|
||||
CFRunLoopSourceContext context = { 0, info, NULL, NULL, NULL, NULL, NULL, NULL, NULL, perform };
|
||||
|
||||
// Pass 1 so that it is called after all inputs have been handled (they will have order = 0)
|
||||
This->m_SourceRef = CFRunLoopSourceCreate( kCFAllocatorDefault, 1, &context );
|
||||
|
||||
CFRunLoopAddSource( This->m_LoopRef, This->m_SourceRef, kCFRunLoopDefaultMode );
|
||||
}
|
||||
CFRunLoopRun();
|
||||
LOG->Trace( "Shutting down input handler thread..." );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InputHandler_MacOSX_HID::DeviceAdded( void *refCon, io_iterator_t )
|
||||
{
|
||||
InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)refCon;
|
||||
|
||||
LockMut( This->m_ChangeLock );
|
||||
This->m_bChanged = true;
|
||||
}
|
||||
|
||||
void InputHandler_MacOSX_HID::DeviceChanged( void *refCon, io_service_t service, natural_t messageType, void *arg )
|
||||
{
|
||||
if( messageType == kIOMessageServiceIsTerminated )
|
||||
{
|
||||
InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)refCon;
|
||||
|
||||
LockMut( This->m_ChangeLock );
|
||||
This->m_bChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
// m_LoopRef needs to be set before this is called
|
||||
void InputHandler_MacOSX_HID::StartDevices()
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
ASSERT( m_LoopRef );
|
||||
FOREACH( HIDDevice *, m_vDevices, i )
|
||||
(*i)->StartQueue( m_LoopRef, InputHandler_MacOSX_HID::QueueCallback, this, n++ );
|
||||
|
||||
CFRunLoopSourceRef runLoopSource = IONotificationPortGetRunLoopSource( m_NotifyPort );
|
||||
|
||||
CFRunLoopAddSource( m_LoopRef, runLoopSource, kCFRunLoopDefaultMode );
|
||||
}
|
||||
|
||||
InputHandler_MacOSX_HID::~InputHandler_MacOSX_HID()
|
||||
{
|
||||
FOREACH( HIDDevice *, m_vDevices, i )
|
||||
delete *i;
|
||||
if( PREFSMAN->m_bThreadedInput )
|
||||
{
|
||||
CFRunLoopSourceSignal( m_SourceRef );
|
||||
CFRunLoopWakeUp( m_LoopRef );
|
||||
m_InputThread.Wait();
|
||||
CFRelease( m_SourceRef );
|
||||
CFRelease( m_LoopRef );
|
||||
LOG->Trace( "Input handler thread shut down." );
|
||||
}
|
||||
|
||||
FOREACH( io_iterator_t, m_vIters, i )
|
||||
IOObjectRelease( *i );
|
||||
IONotificationPortDestroy( m_NotifyPort );
|
||||
}
|
||||
|
||||
static CFDictionaryRef GetMatchingDictionary( int usagePage, int usage )
|
||||
{
|
||||
// Build the matching dictionary.
|
||||
CFMutableDictionaryRef dict;
|
||||
|
||||
if( (dict = IOServiceMatching(kIOHIDDeviceKey)) == NULL )
|
||||
FAIL_M( "Couldn't create a matching dictionary." );
|
||||
// Refine the search by only looking for joysticks
|
||||
CFNumberRef usagePageRef = CFInt( usagePage );
|
||||
CFNumberRef usageRef = CFInt( usage );
|
||||
|
||||
CFDictionarySetValue( dict, CFSTR(kIOHIDPrimaryUsagePageKey), usagePageRef );
|
||||
CFDictionarySetValue( dict, CFSTR(kIOHIDPrimaryUsageKey), usageRef );
|
||||
|
||||
// Cleanup after ourselves
|
||||
CFRelease( usagePageRef );
|
||||
CFRelease( usageRef );
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
// Factor this out because nothing else in IH_C::AddDevices() needs to know the type of the device.
|
||||
static HIDDevice *MakeDevice( InputDevice id )
|
||||
{
|
||||
if( id == DEVICE_KEYBOARD )
|
||||
return new KeyboardDevice;
|
||||
/*
|
||||
if( id == DEVICE_MOUSE )
|
||||
return new MouseDevice;
|
||||
*/
|
||||
if( IsJoystick(id) )
|
||||
return new JoystickDevice;
|
||||
if( IsPump(id) )
|
||||
return new PumpDevice;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void InputHandler_MacOSX_HID::AddDevices( int usagePage, int usage, InputDevice &id )
|
||||
{
|
||||
io_iterator_t iter;
|
||||
CFDictionaryRef dict = GetMatchingDictionary( usagePage, usage );
|
||||
kern_return_t ret = IOServiceAddMatchingNotification( m_NotifyPort, kIOFirstMatchNotification, dict,
|
||||
InputHandler_MacOSX_HID::DeviceAdded, this, &iter );
|
||||
io_object_t device;
|
||||
|
||||
if( ret != KERN_SUCCESS )
|
||||
return;
|
||||
|
||||
m_vIters.push_back( iter );
|
||||
|
||||
// Iterate over the devices and add them
|
||||
while( (device = IOIteratorNext(iter)) )
|
||||
{
|
||||
LOG->Trace( "\tFound device %d", id );
|
||||
HIDDevice *dev = MakeDevice( id );
|
||||
int num;
|
||||
|
||||
if( !dev )
|
||||
{
|
||||
LOG->Trace( "\t\tInvalid id, deleting device" );
|
||||
IOObjectRelease( device );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !dev->Open(device) || (num = dev->AssignIDs(id)) == -1 )
|
||||
{
|
||||
LOG->Trace( "\tFailed top open or assign id, deleting device" );
|
||||
delete dev;
|
||||
IOObjectRelease( device );
|
||||
continue;
|
||||
}
|
||||
io_iterator_t i;
|
||||
|
||||
enum_add( id, num );
|
||||
m_vDevices.push_back( dev );
|
||||
|
||||
ret = IOServiceAddInterestNotification(
|
||||
m_NotifyPort, device, kIOGeneralInterest,
|
||||
InputHandler_MacOSX_HID::DeviceChanged,
|
||||
this, &i
|
||||
);
|
||||
|
||||
if( ret == KERN_SUCCESS )
|
||||
m_vIters.push_back( i );
|
||||
else
|
||||
LOG->Trace( "\t\tFailed to add device changed notification, deleting device" );
|
||||
IOObjectRelease( device );
|
||||
}
|
||||
}
|
||||
|
||||
InputHandler_MacOSX_HID::InputHandler_MacOSX_HID() : m_Sem( "Input thread started" ), m_ChangeLock( "Input handler change lock" )
|
||||
{
|
||||
InputDevice id = DEVICE_KEYBOARD;
|
||||
|
||||
// Set up the notify ports.
|
||||
m_NotifyPort = IONotificationPortCreate( kIOMasterPortDefault );
|
||||
|
||||
// Add devices.
|
||||
LOG->Trace( "Finding keyboards" );
|
||||
AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard, id );
|
||||
|
||||
LOG->Trace( "Finding mice" );
|
||||
AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse, id );
|
||||
|
||||
LOG->Trace( "Finding joysticks" );
|
||||
id = DEVICE_JOY1;
|
||||
AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick, id );
|
||||
AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad, id );
|
||||
LOG->Trace( "Finding pump" );
|
||||
id = DEVICE_PUMP1;
|
||||
AddDevices( kHIDPage_VendorDefinedStart, 0x0001, id ); // Pump pads use the first vendor specific usage page.
|
||||
m_bChanged = false;
|
||||
|
||||
if( PREFSMAN->m_bThreadedInput )
|
||||
{
|
||||
m_InputThread.SetName( "Input thread" );
|
||||
m_InputThread.Create( InputHandler_MacOSX_HID::Run, this );
|
||||
// Wait for the run loop to start before returning.
|
||||
m_Sem.Wait();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_LoopRef = CFRunLoopRef( GetCFRunLoopFromEventLoop(GetMainEventLoop()) );
|
||||
CFRetain( m_LoopRef );
|
||||
StartDevices();
|
||||
}
|
||||
}
|
||||
|
||||
void InputHandler_MacOSX_HID::GetDevicesAndDescriptions( vector<InputDeviceInfo>& vDevices )
|
||||
{
|
||||
for (HIDDevice *i : m_vDevices)
|
||||
i->GetDevicesAndDescriptions( vDevices );
|
||||
}
|
||||
|
||||
RString InputHandler_MacOSX_HID::GetDeviceSpecificInputString( const DeviceInput &di )
|
||||
{
|
||||
if( di.device == DEVICE_KEYBOARD )
|
||||
{
|
||||
#define OTHER(n) (KEY_OTHER_0 + (n))
|
||||
switch( di.button )
|
||||
{
|
||||
case KEY_DEL: return "del";
|
||||
case KEY_BACK: return "delete";
|
||||
case KEY_ENTER: return "return";
|
||||
case KEY_LALT: return "left option";
|
||||
case KEY_RALT: return "right option";
|
||||
case KEY_LMETA: return "left cmd";
|
||||
case KEY_RMETA: return "right cmd";
|
||||
case KEY_INSERT: return "help";
|
||||
case OTHER(0): return "F17";
|
||||
case OTHER(1): return "F18";
|
||||
case OTHER(2): return "F19";
|
||||
case OTHER(3): return "F20";
|
||||
case OTHER(4): return "F21";
|
||||
case OTHER(5): return "F22";
|
||||
case OTHER(6): return "F23";
|
||||
case OTHER(7): return "F25";
|
||||
case OTHER(8): return "execute";
|
||||
case OTHER(9): return "select";
|
||||
case OTHER(10): return "stop";
|
||||
case OTHER(11): return "again";
|
||||
case OTHER(12): return "undo";
|
||||
case OTHER(13): return "cut";
|
||||
case OTHER(14): return "copy";
|
||||
case OTHER(15): return "paste";
|
||||
case OTHER(16): return "find";
|
||||
case OTHER(17): return "mute";
|
||||
case OTHER(18): return "volume up";
|
||||
case OTHER(19): return "volume down";
|
||||
case OTHER(20): return "AS/400 equal";
|
||||
case OTHER(21): return "international 1";
|
||||
case OTHER(22): return "international 2";
|
||||
case OTHER(23): return "international 3";
|
||||
case OTHER(24): return "international 4";
|
||||
case OTHER(25): return "international 5";
|
||||
case OTHER(26): return "international 6";
|
||||
case OTHER(27): return "international 7";
|
||||
case OTHER(28): return "international 8";
|
||||
case OTHER(29): return "international 9";
|
||||
case OTHER(30): return "lang 1";
|
||||
case OTHER(31): return "lang 2";
|
||||
case OTHER(32): return "lang 3";
|
||||
case OTHER(33): return "lang 4";
|
||||
case OTHER(34): return "lang 5";
|
||||
case OTHER(35): return "lang 6";
|
||||
case OTHER(36): return "lang 7";
|
||||
case OTHER(37): return "lang 8";
|
||||
case OTHER(38): return "lang 9";
|
||||
case OTHER(39): return "alt erase";
|
||||
case OTHER(40): return "sys req";
|
||||
case OTHER(41): return "cancel";
|
||||
case OTHER(42): return "separator";
|
||||
case OTHER(43): return "out";
|
||||
case OTHER(44): return "oper";
|
||||
case OTHER(45): return "clear/again"; // XXX huh?
|
||||
case OTHER(46): return "cr sel/props"; // XXX
|
||||
case OTHER(47): return "ex sel";
|
||||
case OTHER(48): return "non US backslash";
|
||||
case OTHER(49): return "application";
|
||||
case OTHER(50): return "prior";
|
||||
default: break;
|
||||
}
|
||||
#undef OTHER
|
||||
}
|
||||
if( di.device == DEVICE_PUMP1 || di.device == DEVICE_PUMP2 )
|
||||
{
|
||||
switch( di.button )
|
||||
{
|
||||
case JOY_BUTTON_1: return "UL";
|
||||
case JOY_BUTTON_2: return "UR";
|
||||
case JOY_BUTTON_3: return "MID";
|
||||
case JOY_BUTTON_4: return "DL";
|
||||
case JOY_BUTTON_5: return "DR";
|
||||
case JOY_BUTTON_6: return "Esc";
|
||||
case JOY_BUTTON_7: return "P2 UL";
|
||||
case JOY_BUTTON_8: return "P2 UR";
|
||||
case JOY_BUTTON_9: return "P2 MID";
|
||||
case JOY_BUTTON_10: return "P2 DL";
|
||||
case JOY_BUTTON_11: return "P2 DR";
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
return InputHandler::GetDeviceSpecificInputString( di );
|
||||
}
|
||||
|
||||
wchar_t InputHandler_MacOSX_HID::DeviceButtonToChar( DeviceButton button, bool bUseCurrentKeyModifiers )
|
||||
{
|
||||
// KeyTranslate maps these keys to a character. They shouldn't be mapped to any character.
|
||||
switch( button )
|
||||
{
|
||||
default:
|
||||
if( (button >= KEY_F1 && button <= KEY_F16) )
|
||||
return L'\0';
|
||||
break;
|
||||
case KEY_UP:
|
||||
case KEY_DOWN:
|
||||
case KEY_LEFT:
|
||||
case KEY_RIGHT:
|
||||
case KEY_ESC:
|
||||
case KEY_TAB:
|
||||
case KEY_ENTER:
|
||||
case KEY_PRTSC:
|
||||
case KEY_SCRLLOCK:
|
||||
case KEY_PAUSE:
|
||||
case KEY_DEL:
|
||||
case KEY_HOME:
|
||||
case KEY_END:
|
||||
case KEY_PGUP:
|
||||
case KEY_PGDN:
|
||||
case KEY_NUMLOCK:
|
||||
case KEY_KP_ENTER:
|
||||
return L'\0';
|
||||
}
|
||||
|
||||
// Find the USB key code for this DeviceButton
|
||||
UInt8 iMacVirtualKey;
|
||||
if( KeyboardDevice::DeviceButtonToMacVirtualKey( button, iMacVirtualKey ) )
|
||||
{
|
||||
UInt32 modifiers = 0;
|
||||
if( bUseCurrentKeyModifiers )
|
||||
modifiers = GetCurrentKeyModifiers();
|
||||
|
||||
// todo: handle Caps Lock -freem
|
||||
|
||||
SInt16 iCurrentKeyScript = GetScriptManagerVariable( smKeyScript );
|
||||
SInt16 iCurrentKeyLayoutID = GetScriptVariable( iCurrentKeyScript, smScriptKeys );
|
||||
static SInt16 iLastKeyLayoutID = !iCurrentKeyLayoutID; // Just be different.
|
||||
static UInt32 iDeadKeyState;
|
||||
static UCKeyboardLayout **KeyLayout;
|
||||
|
||||
if( iCurrentKeyLayoutID != iLastKeyLayoutID )
|
||||
{
|
||||
iDeadKeyState = 0;
|
||||
KeyLayout = (UCKeyboardLayout **)GetResource( 'uchr', iCurrentKeyLayoutID );
|
||||
iLastKeyLayoutID = iCurrentKeyLayoutID;
|
||||
}
|
||||
if( KeyLayout )
|
||||
{
|
||||
UInt32 keyboardType = LMGetKbdType();
|
||||
UInt32 nModifiers = bUseCurrentKeyModifiers ? GetCurrentKeyModifiers() : 0;
|
||||
UniChar unicodeInputString[4];
|
||||
UniCharCount length;
|
||||
OSStatus status = UCKeyTranslate( *KeyLayout, iMacVirtualKey, kUCKeyActionDown, nModifiers,
|
||||
keyboardType, 0, &iDeadKeyState, ARRAYLEN(unicodeInputString),
|
||||
&length, unicodeInputString );
|
||||
|
||||
if( status )
|
||||
return L'\0';
|
||||
|
||||
CFStringRef inputString = CFStringCreateWithCharacters( NULL, unicodeInputString, length );
|
||||
char utf8InputString[7]; // Max size is 6 (although really only 4 are used) + null.
|
||||
|
||||
if( !CFStringGetCString(inputString, utf8InputString, 7, kCFStringEncodingUTF8) )
|
||||
{
|
||||
CFRelease( inputString );
|
||||
return L'\0';
|
||||
}
|
||||
|
||||
wchar_t ch = utf8_get_char( utf8InputString );
|
||||
|
||||
CFRelease( inputString );
|
||||
return ch == INVALID_CHAR ? L'\0' : ch;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fall back on the 'KCHR' resource.
|
||||
static unsigned long state = 0;
|
||||
static Ptr keymap = NULL;
|
||||
Ptr new_keymap;
|
||||
|
||||
new_keymap = (Ptr)GetScriptManagerVariable(smKCHRCache);
|
||||
if( new_keymap != keymap )
|
||||
{
|
||||
keymap = new_keymap;
|
||||
state = 0;
|
||||
}
|
||||
// XXX: Only returns ascii. é will be returned as e.
|
||||
return KeyTranslate( keymap, UInt16(iMacVirtualKey)|modifiers, &state ) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
return InputHandler::DeviceButtonToChar( button, bUseCurrentKeyModifiers );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2005, 2006 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
+330
-330
@@ -1,330 +1,330 @@
|
||||
/*
|
||||
* This file provides functions to create driver objects.
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
#include "PrefsManager.h"
|
||||
#include "arch.h"
|
||||
#include "arch_platform.h"
|
||||
#include "Foreach.h"
|
||||
#include "LocalizedString.h"
|
||||
#include "arch/arch_default.h"
|
||||
|
||||
#include "InputHandler/Selector_InputHandler.h"
|
||||
static LocalizedString INPUT_HANDLERS_EMPTY( "Arch", "Input Handlers cannot be empty." );
|
||||
void MakeInputHandlers( const RString &drivers, vector<InputHandler *> &Add )
|
||||
{
|
||||
vector<RString> DriversToTry;
|
||||
split( drivers, ",", DriversToTry, true );
|
||||
|
||||
if( DriversToTry.empty() )
|
||||
RageException::Throw( INPUT_HANDLERS_EMPTY.GetValue() );
|
||||
|
||||
RString Driver;
|
||||
|
||||
FOREACH_CONST( RString, DriversToTry, s )
|
||||
{
|
||||
InputHandler *ret = NULL;
|
||||
|
||||
#ifdef USE_INPUT_HANDLER_DIRECTINPUT
|
||||
if( !s->CompareNoCase("DirectInput") ) ret = new InputHandler_DInput;
|
||||
#endif
|
||||
#ifdef USE_INPUT_HANDLER_PIUIO
|
||||
if( !s->CompareNoCase("PIUIO") ) ret = new InputHandler_Linux_PIUIO;
|
||||
#endif
|
||||
#ifdef USE_INPUT_HANDLER_LINUX_JOYSTICK
|
||||
if( !s->CompareNoCase("Joystick") ) ret = new InputHandler_Linux_Joystick;
|
||||
#endif
|
||||
#ifdef USE_INPUT_HANDLER_LINUX_TTY
|
||||
if( !s->CompareNoCase("tty") ) ret = new InputHandler_Linux_tty;
|
||||
#endif
|
||||
#ifdef USE_INPUT_HANDLER_SDL
|
||||
if( !s->CompareNoCase("SDL") ) ret = new InputHandler_SDL;
|
||||
#endif
|
||||
#ifdef USE_INPUT_HANDLER_WIN32_PARA
|
||||
if( !s->CompareNoCase("Para") ) ret = new InputHandler_Win32_Para;
|
||||
#endif
|
||||
#ifdef USE_INPUT_HANDLER_WIN32_PUMP
|
||||
if( !s->CompareNoCase("Pump") ) ret = new InputHandler_Win32_Pump;
|
||||
#endif
|
||||
#ifdef USE_INPUT_HANDLER_WIN32_MIDI
|
||||
if( !s->CompareNoCase("MIDI") ) ret = new InputHandler_Win32_MIDI;
|
||||
#endif
|
||||
#ifdef USE_INPUT_HANDLER_X11
|
||||
if( !s->CompareNoCase("X11") ) ret = new InputHandler_X11;
|
||||
#endif
|
||||
#ifdef USE_INPUT_HANDLER_MACOSX_HID
|
||||
if( !s->CompareNoCase("MacOSX") ) ret = new InputHandler_MacOSX_HID;
|
||||
#endif
|
||||
|
||||
if( ret == NULL )
|
||||
LOG->Trace( "Unknown Input Handler name: %s", s->c_str() );
|
||||
else
|
||||
Add.push_back( ret );
|
||||
}
|
||||
|
||||
// Always add
|
||||
Add.push_back( new InputHandler_MonkeyKeyboard );
|
||||
|
||||
}
|
||||
|
||||
#include "Lights/Selector_LightsDriver.h"
|
||||
void MakeLightsDrivers( const RString &driver, vector<LightsDriver *> &Add )
|
||||
{
|
||||
LOG->Trace( "Initializing lights driver: %s", driver.c_str() );
|
||||
|
||||
LightsDriver *ret = NULL;
|
||||
|
||||
#ifdef USE_LIGHTS_DRIVER_LINUX_PIUIO
|
||||
if( !driver.CompareNoCase("PIUIO") ) ret = new LightsDriver_Linux_PIUIO;
|
||||
#endif
|
||||
#ifdef USE_LIGHTS_DRIVER_LINUX_PARALLEL
|
||||
if( !driver.CompareNoCase("LinuxParallel") ) ret = new LightsDriver_LinuxParallel;
|
||||
#endif
|
||||
#ifdef USE_LIGHTS_DRIVER_LINUX_WEEDTECH
|
||||
if( !driver.CompareNoCase("WeedTech") ) ret = new LightsDriver_LinuxWeedTech;
|
||||
#endif
|
||||
#ifdef USE_LIGHTS_DRIVER_WIN32_PARALLEL
|
||||
if( !driver.CompareNoCase("Parallel") ) ret = new LightsDriver_Win32Parallel;
|
||||
#endif
|
||||
|
||||
if( ret == NULL && driver.CompareNoCase("Null") )
|
||||
LOG->Trace( "Unknown lights driver name: %s", driver.c_str() );
|
||||
else if( ret != NULL )
|
||||
Add.push_back( ret );
|
||||
|
||||
Add.push_back( new LightsDriver_SystemMessage );
|
||||
}
|
||||
|
||||
#include "LoadingWindow/Selector_LoadingWindow.h"
|
||||
LoadingWindow *MakeLoadingWindow()
|
||||
{
|
||||
if( !PREFSMAN->m_bShowLoadingWindow )
|
||||
return new LoadingWindow_Null;
|
||||
#if defined(LINUX) && !defined(HAVE_GTK)
|
||||
return new LoadingWindow_Null;
|
||||
#endif
|
||||
// Don't load NULL by default.
|
||||
const RString drivers = "win32,cocoa,gtk";
|
||||
vector<RString> DriversToTry;
|
||||
split( drivers, ",", DriversToTry, true );
|
||||
|
||||
ASSERT( DriversToTry.size() != 0 );
|
||||
|
||||
RString Driver;
|
||||
LoadingWindow *ret = NULL;
|
||||
|
||||
for( unsigned i = 0; ret == NULL && i < DriversToTry.size(); ++i )
|
||||
{
|
||||
Driver = DriversToTry[i];
|
||||
|
||||
#ifdef USE_LOADING_WINDOW_COCOA
|
||||
if( !DriversToTry[i].CompareNoCase("Cocoa") ) ret = new LoadingWindow_Cocoa;
|
||||
#endif
|
||||
#ifdef USE_LOADING_WINDOW_GTK
|
||||
if( !DriversToTry[i].CompareNoCase("Gtk") ) ret = new LoadingWindow_Gtk;
|
||||
#endif
|
||||
#ifdef USE_LOADING_WINDOW_NULL
|
||||
if( !DriversToTry[i].CompareNoCase("Null") ) ret = new LoadingWindow_Null;
|
||||
#endif
|
||||
#ifdef USE_LOADING_WINDOW_WIN32
|
||||
if( !DriversToTry[i].CompareNoCase("Win32") ) ret = new LoadingWindow_Win32;
|
||||
#endif
|
||||
|
||||
if( ret == NULL )
|
||||
continue;
|
||||
|
||||
RString sError = ret->Init();
|
||||
if( sError != "" )
|
||||
{
|
||||
LOG->Info( "Couldn't load driver %s: %s", DriversToTry[i].c_str(), sError.c_str() );
|
||||
SAFE_DELETE( ret );
|
||||
}
|
||||
}
|
||||
|
||||
if(ret)
|
||||
LOG->Info( "Loading window: %s", Driver.c_str() );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(SUPPORT_OPENGL)
|
||||
#include "LowLevelWindow/Selector_LowLevelWindow.h"
|
||||
LowLevelWindow *MakeLowLevelWindow()
|
||||
{
|
||||
return new ARCH_LOW_LEVEL_WINDOW;
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "MemoryCard/MemoryCardDriver_Null.h"
|
||||
#include "MemoryCard/Selector_MemoryCardDriver.h"
|
||||
MemoryCardDriver *MakeMemoryCardDriver()
|
||||
{
|
||||
MemoryCardDriver *ret = NULL;
|
||||
|
||||
#ifdef ARCH_MEMORY_CARD_DRIVER
|
||||
ret = new ARCH_MEMORY_CARD_DRIVER;
|
||||
#endif
|
||||
|
||||
if( !ret )
|
||||
ret = new MemoryCardDriver_Null;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Preference<RString> g_sMovieDrivers( "MovieDrivers", "" ); // "" == default
|
||||
#include "MovieTexture/Selector_MovieTexture.h"
|
||||
static void DumpAVIDebugInfo( const RString& fn );
|
||||
// Try drivers in order of preference until we find one that works.
|
||||
static LocalizedString MOVIE_DRIVERS_EMPTY ( "Arch", "Movie Drivers cannot be empty." );
|
||||
static LocalizedString COULDNT_CREATE_MOVIE_DRIVER ( "Arch", "Couldn't create a movie driver." );
|
||||
RageMovieTexture *MakeRageMovieTexture( RageTextureID ID )
|
||||
{
|
||||
DumpAVIDebugInfo( ID.filename );
|
||||
|
||||
RString sDrivers = g_sMovieDrivers;
|
||||
if( sDrivers.empty() )
|
||||
sDrivers = DEFAULT_MOVIE_DRIVER_LIST;
|
||||
|
||||
vector<RString> DriversToTry;
|
||||
split( sDrivers, ",", DriversToTry, true );
|
||||
|
||||
if( DriversToTry.empty() )
|
||||
RageException::Throw( MOVIE_DRIVERS_EMPTY.GetValue() );
|
||||
|
||||
RString Driver;
|
||||
RageMovieTexture *ret = NULL;
|
||||
|
||||
for( unsigned i=0; ret==NULL && i<DriversToTry.size(); ++i )
|
||||
{
|
||||
Driver = DriversToTry[i];
|
||||
LOG->Trace( "Initializing driver: %s", Driver.c_str() );
|
||||
#ifdef USE_MOVIE_TEXTURE_DSHOW
|
||||
if( !Driver.CompareNoCase("DShow") ) ret = new MovieTexture_DShow(ID);
|
||||
#endif
|
||||
#ifdef USE_MOVIE_TEXTURE_FFMPEG
|
||||
if( !Driver.CompareNoCase("FFMpeg") ) ret = new MovieTexture_FFMpeg(ID);
|
||||
#endif
|
||||
#ifdef USE_MOVIE_TEXTURE_NULL
|
||||
if( !Driver.CompareNoCase("Null") ) ret = new MovieTexture_Null(ID);
|
||||
#endif
|
||||
if( ret == NULL )
|
||||
{
|
||||
LOG->Trace( "Unknown movie driver name: %s", Driver.c_str() );
|
||||
continue;
|
||||
}
|
||||
|
||||
RString sError = ret->Init();
|
||||
if( sError != "" )
|
||||
{
|
||||
LOG->Info( "Couldn't load driver %s: %s", Driver.c_str(), sError.c_str() );
|
||||
SAFE_DELETE( ret );
|
||||
}
|
||||
}
|
||||
if ( !ret )
|
||||
RageException::Throw( COULDNT_CREATE_MOVIE_DRIVER.GetValue() );
|
||||
|
||||
LOG->Trace( "Created movie texture \"%s\" with driver \"%s\"",
|
||||
ID.filename.c_str(), Driver.c_str() );
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include "Sound/Selector_RageSoundDriver.h"
|
||||
static LocalizedString SOUND_DRIVERS_CANNOT_EMPTY( "Arch", "Sound Drivers cannot be empty." );
|
||||
RageSoundDriver *MakeRageSoundDriver( const RString &drivers )
|
||||
{
|
||||
vector<RString> DriversToTry;
|
||||
split( drivers, ",", DriversToTry, true );
|
||||
|
||||
if( DriversToTry.empty() )
|
||||
RageException::Throw( SOUND_DRIVERS_CANNOT_EMPTY.GetValue() );
|
||||
|
||||
RString Driver;
|
||||
RageSoundDriver *ret = NULL;
|
||||
|
||||
for( unsigned i = 0; ret == NULL && i < DriversToTry.size(); ++i )
|
||||
{
|
||||
Driver = DriversToTry[i];
|
||||
LOG->Trace( "Initializing driver: %s", DriversToTry[i].c_str() );
|
||||
|
||||
#ifdef USE_RAGE_SOUND_ALSA9
|
||||
if( !DriversToTry[i].CompareNoCase("ALSA") ) ret = new RageSound_ALSA9;
|
||||
#endif
|
||||
#ifdef USE_RAGE_SOUND_ALSA9_SOFTWARE
|
||||
if( !DriversToTry[i].CompareNoCase("ALSA-sw") ) ret = new RageSound_ALSA9_Software;
|
||||
#endif
|
||||
#ifdef USE_RAGE_SOUND_AU
|
||||
if( !DriversToTry[i].CompareNoCase("AudioUnit") ) ret = new RageSoundDriver_AU;
|
||||
#endif
|
||||
#ifdef USE_RAGE_SOUND_DSOUND
|
||||
if( !DriversToTry[i].CompareNoCase("DirectSound") ) ret = new RageSound_DSound;
|
||||
#endif
|
||||
#ifdef USE_RAGE_SOUND_DSOUND_SOFTWARE
|
||||
if( !DriversToTry[i].CompareNoCase("DirectSound-sw") ) ret = new RageSound_DSound_Software;
|
||||
#endif
|
||||
#ifdef USE_RAGE_SOUND_NULL
|
||||
if( !DriversToTry[i].CompareNoCase("Null") ) ret = new RageSound_Null;
|
||||
#endif
|
||||
#ifdef USE_RAGE_SOUND_OSS
|
||||
if( !DriversToTry[i].CompareNoCase("OSS") ) ret = new RageSound_OSS;
|
||||
#endif
|
||||
#ifdef USE_RAGE_SOUND_WAVE_OUT
|
||||
if( !DriversToTry[i].CompareNoCase("WaveOut") ) ret = new RageSound_WaveOut;
|
||||
#endif
|
||||
|
||||
if( ret == NULL )
|
||||
{
|
||||
LOG->Trace( "Unknown sound driver name: %s", DriversToTry[i].c_str() );
|
||||
continue;
|
||||
}
|
||||
|
||||
RString sError = ret->Init();
|
||||
if( sError != "" )
|
||||
{
|
||||
LOG->Info( "Couldn't load driver %s: %s", DriversToTry[i].c_str(), sError.c_str() );
|
||||
SAFE_DELETE( ret );
|
||||
}
|
||||
}
|
||||
|
||||
if( ret )
|
||||
LOG->Info( "Sound driver: %s", Driver.c_str() );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Helper for MakeRageMovieTexture()
|
||||
static void DumpAVIDebugInfo( const RString& fn )
|
||||
{
|
||||
RString type, handler;
|
||||
if( !RageMovieTexture::GetFourCC( fn, handler, type ) )
|
||||
return;
|
||||
|
||||
LOG->Trace( "Movie %s has handler '%s', type '%s'", fn.c_str(), handler.c_str(), type.c_str() );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2002-2005 Glenn Maynard, Ben Anderson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
/*
|
||||
* This file provides functions to create driver objects.
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
#include "PrefsManager.h"
|
||||
#include "arch.h"
|
||||
#include "arch_platform.h"
|
||||
#include "Foreach.h"
|
||||
#include "LocalizedString.h"
|
||||
#include "arch/arch_default.h"
|
||||
|
||||
#include "InputHandler/Selector_InputHandler.h"
|
||||
static LocalizedString INPUT_HANDLERS_EMPTY( "Arch", "Input Handlers cannot be empty." );
|
||||
void MakeInputHandlers( const RString &drivers, vector<InputHandler *> &Add )
|
||||
{
|
||||
vector<RString> DriversToTry;
|
||||
split( drivers, ",", DriversToTry, true );
|
||||
|
||||
if( DriversToTry.empty() )
|
||||
RageException::Throw( INPUT_HANDLERS_EMPTY.GetValue() );
|
||||
|
||||
RString Driver;
|
||||
|
||||
for (RString const &s: DriversToTry)
|
||||
{
|
||||
InputHandler *ret = NULL;
|
||||
|
||||
#ifdef USE_INPUT_HANDLER_DIRECTINPUT
|
||||
if( !s.CompareNoCase("DirectInput") ) ret = new InputHandler_DInput;
|
||||
#endif
|
||||
#ifdef USE_INPUT_HANDLER_PIUIO
|
||||
if( !s.CompareNoCase("PIUIO") ) ret = new InputHandler_Linux_PIUIO;
|
||||
#endif
|
||||
#ifdef USE_INPUT_HANDLER_LINUX_JOYSTICK
|
||||
if( !s.CompareNoCase("Joystick") ) ret = new InputHandler_Linux_Joystick;
|
||||
#endif
|
||||
#ifdef USE_INPUT_HANDLER_LINUX_TTY
|
||||
if( !s.CompareNoCase("tty") ) ret = new InputHandler_Linux_tty;
|
||||
#endif
|
||||
#ifdef USE_INPUT_HANDLER_SDL
|
||||
if( !s.CompareNoCase("SDL") ) ret = new InputHandler_SDL;
|
||||
#endif
|
||||
#ifdef USE_INPUT_HANDLER_WIN32_PARA
|
||||
if( !s.CompareNoCase("Para") ) ret = new InputHandler_Win32_Para;
|
||||
#endif
|
||||
#ifdef USE_INPUT_HANDLER_WIN32_PUMP
|
||||
if( !s.CompareNoCase("Pump") ) ret = new InputHandler_Win32_Pump;
|
||||
#endif
|
||||
#ifdef USE_INPUT_HANDLER_WIN32_MIDI
|
||||
if( !s.CompareNoCase("MIDI") ) ret = new InputHandler_Win32_MIDI;
|
||||
#endif
|
||||
#ifdef USE_INPUT_HANDLER_X11
|
||||
if( !s.CompareNoCase("X11") ) ret = new InputHandler_X11;
|
||||
#endif
|
||||
#ifdef USE_INPUT_HANDLER_MACOSX_HID
|
||||
if( !s.CompareNoCase("MacOSX") ) ret = new InputHandler_MacOSX_HID;
|
||||
#endif
|
||||
|
||||
if( ret == NULL )
|
||||
LOG->Trace( "Unknown Input Handler name: %s", s.c_str() );
|
||||
else
|
||||
Add.push_back( ret );
|
||||
}
|
||||
|
||||
// Always add
|
||||
Add.push_back( new InputHandler_MonkeyKeyboard );
|
||||
|
||||
}
|
||||
|
||||
#include "Lights/Selector_LightsDriver.h"
|
||||
void MakeLightsDrivers( const RString &driver, vector<LightsDriver *> &Add )
|
||||
{
|
||||
LOG->Trace( "Initializing lights driver: %s", driver.c_str() );
|
||||
|
||||
LightsDriver *ret = NULL;
|
||||
|
||||
#ifdef USE_LIGHTS_DRIVER_LINUX_PIUIO
|
||||
if( !driver.CompareNoCase("PIUIO") ) ret = new LightsDriver_Linux_PIUIO;
|
||||
#endif
|
||||
#ifdef USE_LIGHTS_DRIVER_LINUX_PARALLEL
|
||||
if( !driver.CompareNoCase("LinuxParallel") ) ret = new LightsDriver_LinuxParallel;
|
||||
#endif
|
||||
#ifdef USE_LIGHTS_DRIVER_LINUX_WEEDTECH
|
||||
if( !driver.CompareNoCase("WeedTech") ) ret = new LightsDriver_LinuxWeedTech;
|
||||
#endif
|
||||
#ifdef USE_LIGHTS_DRIVER_WIN32_PARALLEL
|
||||
if( !driver.CompareNoCase("Parallel") ) ret = new LightsDriver_Win32Parallel;
|
||||
#endif
|
||||
|
||||
if( ret == NULL && driver.CompareNoCase("Null") )
|
||||
LOG->Trace( "Unknown lights driver name: %s", driver.c_str() );
|
||||
else if( ret != NULL )
|
||||
Add.push_back( ret );
|
||||
|
||||
Add.push_back( new LightsDriver_SystemMessage );
|
||||
}
|
||||
|
||||
#include "LoadingWindow/Selector_LoadingWindow.h"
|
||||
LoadingWindow *MakeLoadingWindow()
|
||||
{
|
||||
if( !PREFSMAN->m_bShowLoadingWindow )
|
||||
return new LoadingWindow_Null;
|
||||
#if defined(LINUX) && !defined(HAVE_GTK)
|
||||
return new LoadingWindow_Null;
|
||||
#endif
|
||||
// Don't load NULL by default.
|
||||
const RString drivers = "win32,cocoa,gtk";
|
||||
vector<RString> DriversToTry;
|
||||
split( drivers, ",", DriversToTry, true );
|
||||
|
||||
ASSERT( DriversToTry.size() != 0 );
|
||||
|
||||
RString Driver;
|
||||
LoadingWindow *ret = NULL;
|
||||
|
||||
for( unsigned i = 0; ret == NULL && i < DriversToTry.size(); ++i )
|
||||
{
|
||||
Driver = DriversToTry[i];
|
||||
|
||||
#ifdef USE_LOADING_WINDOW_COCOA
|
||||
if( !DriversToTry[i].CompareNoCase("Cocoa") ) ret = new LoadingWindow_Cocoa;
|
||||
#endif
|
||||
#ifdef USE_LOADING_WINDOW_GTK
|
||||
if( !DriversToTry[i].CompareNoCase("Gtk") ) ret = new LoadingWindow_Gtk;
|
||||
#endif
|
||||
#ifdef USE_LOADING_WINDOW_NULL
|
||||
if( !DriversToTry[i].CompareNoCase("Null") ) ret = new LoadingWindow_Null;
|
||||
#endif
|
||||
#ifdef USE_LOADING_WINDOW_WIN32
|
||||
if( !DriversToTry[i].CompareNoCase("Win32") ) ret = new LoadingWindow_Win32;
|
||||
#endif
|
||||
|
||||
if( ret == NULL )
|
||||
continue;
|
||||
|
||||
RString sError = ret->Init();
|
||||
if( sError != "" )
|
||||
{
|
||||
LOG->Info( "Couldn't load driver %s: %s", DriversToTry[i].c_str(), sError.c_str() );
|
||||
SAFE_DELETE( ret );
|
||||
}
|
||||
}
|
||||
|
||||
if(ret)
|
||||
LOG->Info( "Loading window: %s", Driver.c_str() );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(SUPPORT_OPENGL)
|
||||
#include "LowLevelWindow/Selector_LowLevelWindow.h"
|
||||
LowLevelWindow *MakeLowLevelWindow()
|
||||
{
|
||||
return new ARCH_LOW_LEVEL_WINDOW;
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "MemoryCard/MemoryCardDriver_Null.h"
|
||||
#include "MemoryCard/Selector_MemoryCardDriver.h"
|
||||
MemoryCardDriver *MakeMemoryCardDriver()
|
||||
{
|
||||
MemoryCardDriver *ret = NULL;
|
||||
|
||||
#ifdef ARCH_MEMORY_CARD_DRIVER
|
||||
ret = new ARCH_MEMORY_CARD_DRIVER;
|
||||
#endif
|
||||
|
||||
if( !ret )
|
||||
ret = new MemoryCardDriver_Null;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Preference<RString> g_sMovieDrivers( "MovieDrivers", "" ); // "" == default
|
||||
#include "MovieTexture/Selector_MovieTexture.h"
|
||||
static void DumpAVIDebugInfo( const RString& fn );
|
||||
// Try drivers in order of preference until we find one that works.
|
||||
static LocalizedString MOVIE_DRIVERS_EMPTY ( "Arch", "Movie Drivers cannot be empty." );
|
||||
static LocalizedString COULDNT_CREATE_MOVIE_DRIVER ( "Arch", "Couldn't create a movie driver." );
|
||||
RageMovieTexture *MakeRageMovieTexture( RageTextureID ID )
|
||||
{
|
||||
DumpAVIDebugInfo( ID.filename );
|
||||
|
||||
RString sDrivers = g_sMovieDrivers;
|
||||
if( sDrivers.empty() )
|
||||
sDrivers = DEFAULT_MOVIE_DRIVER_LIST;
|
||||
|
||||
vector<RString> DriversToTry;
|
||||
split( sDrivers, ",", DriversToTry, true );
|
||||
|
||||
if( DriversToTry.empty() )
|
||||
RageException::Throw( MOVIE_DRIVERS_EMPTY.GetValue() );
|
||||
|
||||
RString Driver;
|
||||
RageMovieTexture *ret = NULL;
|
||||
|
||||
for( unsigned i=0; ret==NULL && i<DriversToTry.size(); ++i )
|
||||
{
|
||||
Driver = DriversToTry[i];
|
||||
LOG->Trace( "Initializing driver: %s", Driver.c_str() );
|
||||
#ifdef USE_MOVIE_TEXTURE_DSHOW
|
||||
if( !Driver.CompareNoCase("DShow") ) ret = new MovieTexture_DShow(ID);
|
||||
#endif
|
||||
#ifdef USE_MOVIE_TEXTURE_FFMPEG
|
||||
if( !Driver.CompareNoCase("FFMpeg") ) ret = new MovieTexture_FFMpeg(ID);
|
||||
#endif
|
||||
#ifdef USE_MOVIE_TEXTURE_NULL
|
||||
if( !Driver.CompareNoCase("Null") ) ret = new MovieTexture_Null(ID);
|
||||
#endif
|
||||
if( ret == NULL )
|
||||
{
|
||||
LOG->Trace( "Unknown movie driver name: %s", Driver.c_str() );
|
||||
continue;
|
||||
}
|
||||
|
||||
RString sError = ret->Init();
|
||||
if( sError != "" )
|
||||
{
|
||||
LOG->Info( "Couldn't load driver %s: %s", Driver.c_str(), sError.c_str() );
|
||||
SAFE_DELETE( ret );
|
||||
}
|
||||
}
|
||||
if ( !ret )
|
||||
RageException::Throw( COULDNT_CREATE_MOVIE_DRIVER.GetValue() );
|
||||
|
||||
LOG->Trace( "Created movie texture \"%s\" with driver \"%s\"",
|
||||
ID.filename.c_str(), Driver.c_str() );
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include "Sound/Selector_RageSoundDriver.h"
|
||||
static LocalizedString SOUND_DRIVERS_CANNOT_EMPTY( "Arch", "Sound Drivers cannot be empty." );
|
||||
RageSoundDriver *MakeRageSoundDriver( const RString &drivers )
|
||||
{
|
||||
vector<RString> DriversToTry;
|
||||
split( drivers, ",", DriversToTry, true );
|
||||
|
||||
if( DriversToTry.empty() )
|
||||
RageException::Throw( SOUND_DRIVERS_CANNOT_EMPTY.GetValue() );
|
||||
|
||||
RString Driver;
|
||||
RageSoundDriver *ret = NULL;
|
||||
|
||||
for( unsigned i = 0; ret == NULL && i < DriversToTry.size(); ++i )
|
||||
{
|
||||
Driver = DriversToTry[i];
|
||||
LOG->Trace( "Initializing driver: %s", DriversToTry[i].c_str() );
|
||||
|
||||
#ifdef USE_RAGE_SOUND_ALSA9
|
||||
if( !DriversToTry[i].CompareNoCase("ALSA") ) ret = new RageSound_ALSA9;
|
||||
#endif
|
||||
#ifdef USE_RAGE_SOUND_ALSA9_SOFTWARE
|
||||
if( !DriversToTry[i].CompareNoCase("ALSA-sw") ) ret = new RageSound_ALSA9_Software;
|
||||
#endif
|
||||
#ifdef USE_RAGE_SOUND_AU
|
||||
if( !DriversToTry[i].CompareNoCase("AudioUnit") ) ret = new RageSoundDriver_AU;
|
||||
#endif
|
||||
#ifdef USE_RAGE_SOUND_DSOUND
|
||||
if( !DriversToTry[i].CompareNoCase("DirectSound") ) ret = new RageSound_DSound;
|
||||
#endif
|
||||
#ifdef USE_RAGE_SOUND_DSOUND_SOFTWARE
|
||||
if( !DriversToTry[i].CompareNoCase("DirectSound-sw") ) ret = new RageSound_DSound_Software;
|
||||
#endif
|
||||
#ifdef USE_RAGE_SOUND_NULL
|
||||
if( !DriversToTry[i].CompareNoCase("Null") ) ret = new RageSound_Null;
|
||||
#endif
|
||||
#ifdef USE_RAGE_SOUND_OSS
|
||||
if( !DriversToTry[i].CompareNoCase("OSS") ) ret = new RageSound_OSS;
|
||||
#endif
|
||||
#ifdef USE_RAGE_SOUND_WAVE_OUT
|
||||
if( !DriversToTry[i].CompareNoCase("WaveOut") ) ret = new RageSound_WaveOut;
|
||||
#endif
|
||||
|
||||
if( ret == NULL )
|
||||
{
|
||||
LOG->Trace( "Unknown sound driver name: %s", DriversToTry[i].c_str() );
|
||||
continue;
|
||||
}
|
||||
|
||||
RString sError = ret->Init();
|
||||
if( sError != "" )
|
||||
{
|
||||
LOG->Info( "Couldn't load driver %s: %s", DriversToTry[i].c_str(), sError.c_str() );
|
||||
SAFE_DELETE( ret );
|
||||
}
|
||||
}
|
||||
|
||||
if( ret )
|
||||
LOG->Info( "Sound driver: %s", Driver.c_str() );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Helper for MakeRageMovieTexture()
|
||||
static void DumpAVIDebugInfo( const RString& fn )
|
||||
{
|
||||
RString type, handler;
|
||||
if( !RageMovieTexture::GetFourCC( fn, handler, type ) )
|
||||
return;
|
||||
|
||||
LOG->Trace( "Movie %s has handler '%s', type '%s'", fn.c_str(), handler.c_str(), type.c_str() );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2002-2005 Glenn Maynard, Ben Anderson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
@@ -128,9 +128,8 @@ void JoystickDevice::AddElement( int usagePage, int usage, IOHIDElementCookie co
|
||||
void JoystickDevice::Open()
|
||||
{
|
||||
// Add elements to the queue for each Joystick
|
||||
FOREACH_CONST( Joystick, m_vSticks, i )
|
||||
for (Joystick const &js : m_vSticks)
|
||||
{
|
||||
const Joystick& js = *i;
|
||||
#define ADD(x) if( js.x ) AddElementToQueue( js.x )
|
||||
ADD( x_axis ); ADD( y_axis ); ADD( z_axis );
|
||||
ADD( x_rot ); ADD( y_rot ); ADD( z_rot );
|
||||
@@ -156,10 +155,8 @@ bool JoystickDevice::InitDevice( int vid, int pid )
|
||||
|
||||
void JoystickDevice::GetButtonPresses( vector<DeviceInput>& vPresses, IOHIDElementCookie cookie, int value, const RageTimer& now ) const
|
||||
{
|
||||
FOREACH_CONST( Joystick, m_vSticks, i )
|
||||
for (Joystick const &js : m_vSticks)
|
||||
{
|
||||
const Joystick& js = *i;
|
||||
|
||||
if( js.x_axis == cookie )
|
||||
{
|
||||
float level = SCALE( value, js.x_min, js.x_max, -1.0f, 1.0f );
|
||||
@@ -266,8 +263,8 @@ int JoystickDevice::AssignIDs( InputDevice startID )
|
||||
|
||||
void JoystickDevice::GetDevicesAndDescriptions( vector<InputDeviceInfo>& vDevices ) const
|
||||
{
|
||||
FOREACH_CONST( Joystick, m_vSticks, i )
|
||||
vDevices.push_back( InputDeviceInfo(i->id,GetDescription()) );
|
||||
for (Joystick &i : m_vSticks)
|
||||
vDevices.push_back( InputDeviceInfo(i.id,GetDescription()) );
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user