void Song::addController( Controller * controller ) { if( controller && !m_controllers.contains( controller ) ) { m_controllers.append( controller ); emit controllerAdded( controller ); this->setModified(); } }
void Remapper::commandIn( Command command, QVariant data, qint64 timeStamp ) { switch( command ) { case Command::Stop: case Command::Load: case Command::Pause: case Command::Unload: case Command::Reset: { emit commandOut( command, data, timeStamp ); playing = false; break; } case Command::Play: { emit commandOut( command, data, timeStamp ); playing = true; break; } case Command::HandleGlobalPipelineReady: { emit commandOut( command, data, timeStamp ); emit controllerAdded( "", "Keyboard", 0, 0, 0 ); // TODO: Read keyboard setting from disk too dpadToAnalogKeyboard = true; // Give the model friendly names for all the keys set for( int physicalKey : keyboardKeyToSDLButton.keys() ) { int virtualButton = keyboardKeyToSDLButton[ physicalKey ]; // This prints garbage as-is, so change it to something that doesn't // Confirmed on Windows but looks okay in OS X? // https://bugreports.qt.io/browse/QTBUG-40030 if( physicalKey == Qt::Key_Shift ) { physicalKey = Qt::ShiftModifier; } if( physicalKey == Qt::Key_Control ) { physicalKey = Qt::ControlModifier; } if( physicalKey == Qt::Key_Meta ) { physicalKey = Qt::MetaModifier; } if( physicalKey == Qt::Key_Alt ) { physicalKey = Qt::AltModifier; } if( physicalKey == Qt::Key_AltGr ) { physicalKey = Qt::AltModifier; } QString keyString = QKeySequence( physicalKey ).toString( QKeySequence::NativeText ); // Strip out trailing + in the corrected keys if( keyString.length() > 1 ) { keyString = keyString.section( '+', 0, 0 ); } emit setMapping( "", keyString, gameControllerIDToMappingString( virtualButton ) ); } break; } case Command::SetUserDataPath: { userDataPath = data.toString(); qDebug() << "Using path" << userDataPath; break; } case Command::Heartbeat: { emit commandOut( command, data, timeStamp ); // Tell the model to clear its stored states emit heartbeat(); // Send out per-GUID OR'd states to RemapperModel then clear stored pressed states for( QString GUID : pressed.keys() ) { emit buttonUpdate( GUID, pressed[ GUID ] ); pressed[ GUID ] = false; } // Do the same for the keyboard emit buttonUpdate( "", keyboardKeyPressed ); keyboardKeyPressed = false; // If in remap mode, make sure the GUID in question still exists, exit remap mode if not if( remapMode && !GUIDCount.contains( remapModeGUID ) ) { qCWarning( phxInput ) << "No controllers with GUID" << remapModeGUID << "remaining, exiting remap mode!"; remapMode = false; emit remappingEnded(); } break; } case Command::AddController: { emit commandOut( command, data, timeStamp ); GamepadState gamepad = data.value<GamepadState>(); int instanceID = gamepad.instanceID; QString GUID( QByteArray( reinterpret_cast<const char *>( gamepad.GUID.data ), 16 ).toHex() ); // Add to map if it hasn't been encountered yet // Otherwise, just increment the count if( !GUIDCount.contains( GUID ) ) { GUIDCount[ GUID ] = 1; emit controllerAdded( GUID, gamepad.friendlyName, gamepad.joystickNumButtons, gamepad.joystickNumHats, gamepad.joystickNumAxes ); } else { GUIDCount[ GUID ]++; } // Initialize mappings with invalid values for( int i = 0; i < SDL_CONTROLLER_BUTTON_MAX; i++ ) { Key key = Key( BUTTON, i ); Val val = Val( INVALID, VHat( -1, -1 ) ); gameControllerToJoystick[ GUID ][ key ] = val; emit setMapping( GUID, keyToMappingString( key ), valToFriendlyString( val ) ); } // Grab gamepad handle gameControllerHandles[ instanceID ] = gamepad.gamecontrollerHandle; for( int i = 0; i < SDL_CONTROLLER_AXIS_MAX; i++ ) { Key key = Key( AXIS, i ); Val val = Val( INVALID, VHat( -1, -1 ) ); gameControllerToJoystick[ GUID ][ key ] = val; emit setMapping( GUID, keyToMappingString( key ), valToFriendlyString( val ) ); } // TODO: Read value from disk analogToDpad[ GUID ] = false; dpadToAnalog[ GUID ] = false; // Set calibration flag, analog values will be read and deadzone values will be calculated the first time // we get data deadzoneFlag[ GUID ] = true; QString mappingString = gamepad.mappingString; if( mappingString.isEmpty() ) { return; } // Parse mapping string { QStringList mappings = mappingString.split( ',', QString::SkipEmptyParts ); // No one likes QList asserts failing if( mappings.isEmpty() ) { return; } /*QString gamepadGUID =*/ mappings.takeFirst(); if( mappings.isEmpty() ) { return; } QString friendlyName = mappings.takeFirst(); if( mappings.isEmpty() ) { return; } QString platform; // Parse the main part of the remapping string for( QString mapping : mappings ) { if( mapping.contains( "platform" ) ) { platform = mapping; continue; } QString keyString = mapping.section( ':', 0, 0 ); QString valueString = mapping.section( ':', 1, 1 ); // Give up if there's nothing parsed if( keyString.isEmpty() || valueString.isEmpty() ) { continue; } Type valueType; // Parse the key Key key = Key( BUTTON, SDL_CONTROLLER_BUTTON_INVALID ); { bool okay; key = mappingStringToKey( keyString, &okay ); if( !okay ) { continue; } } // Parse the value int value = -1; int hatValue = -1; { // Button, format: bX if( valueString.startsWith( "b" ) ) { valueType = BUTTON; bool okay; value = valueString.right( valueString.size() - 1 ).toInt( &okay ); if( !okay ) { continue; } } // Hat, format: hX.Y else if( valueString.startsWith( "h" ) ) { valueType = HAT; bool okay; value = valueString.right( valueString.size() - 1 ).split( '.' )[ 0 ].toInt( &okay ); if( !okay ) { continue; } hatValue = valueString.split( '.' )[ 1 ].toInt( &okay ); if( !okay ) { continue; } } // Axis, format aX else if( valueString.startsWith( "a" ) ) { valueType = AXIS; bool okay; value = valueString.right( valueString.size() - 1 ).toInt( &okay ); if( !okay ) { continue; } } else { continue; } } //qDebug() << keyString << valueString << key << keyType << value << hatValue << valueType; gameControllerToJoystick[ GUID ][ key ] = Val( valueType, VHat( value, hatValue ) ); emit setMapping( GUID, keyToMappingString( key ), valToFriendlyString( Val( valueType, VHat( value, hatValue ) ) ) ); } } break; } case Command::RemoveController: { GamepadState gamepad = data.value<GamepadState>(); int instanceID = gamepad.instanceID; QString GUID( QByteArray( reinterpret_cast<const char *>( gamepad.GUID.data ), 16 ).toHex() ); GUIDCount[ GUID ]--; // Remove from map if no longer there if( GUIDCount[ GUID ] == 0 ) { GUIDCount.remove( GUID ); emit controllerRemoved( GUID ); } // If we opened an SDL2 Game controller handle from this class, keep it and inject it into all gamepads we send out if( gameControllerHandles[ instanceID ] ) { gamepad.gamecontrollerHandle = gameControllerHandles[ instanceID ]; } gameControllerHandles.remove( instanceID ); emit commandOut( Command::RemoveController, QVariant::fromValue( gamepad ), nodeCurrentTime() ); break; } default: { emit commandOut( command, data, timeStamp ); break; } } }