diff --git a/xbmc/games/controllers/dialogs/GUIDialogButtonCapture.h b/xbmc/games/controllers/dialogs/GUIDialogButtonCapture.h index b3936e88d5..6eb4fd72bb 100644 --- a/xbmc/games/controllers/dialogs/GUIDialogButtonCapture.h +++ b/xbmc/games/controllers/dialogs/GUIDialogButtonCapture.h @@ -43,6 +43,7 @@ namespace GAME JOYSTICK::IActionMap* actionMap, const JOYSTICK::CDriverPrimitive& primitive) override; virtual void OnEventFrame(const JOYSTICK::IButtonMap* buttonMap, bool bMotion) override { } + virtual void OnLateAxis(const JOYSTICK::IButtonMap* buttonMap, unsigned int axisIndex) override { } // implementation of Observer virtual void Notify(const Observable &obs, const ObservableMessage msg) override; diff --git a/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp b/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp index 0375cab027..25da841280 100644 --- a/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp +++ b/xbmc/games/controllers/windows/GUIConfigurationWizard.cpp @@ -256,6 +256,11 @@ void CGUIConfigurationWizard::OnEventFrame(const JOYSTICK::IButtonMap* buttonMap OnMotionless(buttonMap); } +void CGUIConfigurationWizard::OnLateAxis(const JOYSTICK::IButtonMap* buttonMap, unsigned int axisIndex) +{ + //! @todo +} + void CGUIConfigurationWizard::OnMotion(const JOYSTICK::IButtonMap* buttonMap) { CSingleLock lock(m_motionMutex); diff --git a/xbmc/games/controllers/windows/GUIConfigurationWizard.h b/xbmc/games/controllers/windows/GUIConfigurationWizard.h index de9c14f763..9c4ab01cd3 100644 --- a/xbmc/games/controllers/windows/GUIConfigurationWizard.h +++ b/xbmc/games/controllers/windows/GUIConfigurationWizard.h @@ -57,6 +57,7 @@ namespace GAME JOYSTICK::IActionMap* actionMap, const JOYSTICK::CDriverPrimitive& primitive) override; virtual void OnEventFrame(const JOYSTICK::IButtonMap* buttonMap, bool bMotion) override; + virtual void OnLateAxis(const JOYSTICK::IButtonMap* buttonMap, unsigned int axisIndex) override; // implementation of IKeyboardHandler virtual bool OnKeyPress(const CKey& key) override; diff --git a/xbmc/input/joysticks/IButtonMapper.h b/xbmc/input/joysticks/IButtonMapper.h index 27457b8243..890760e901 100644 --- a/xbmc/input/joysticks/IButtonMapper.h +++ b/xbmc/input/joysticks/IButtonMapper.h @@ -93,6 +93,17 @@ namespace JOYSTICK */ virtual void OnEventFrame(const IButtonMap* buttonMap, bool bMotion) = 0; + /*! + * \brief Called when an axis has been detected after mapping began + * + * \param axisIndex The index of the axis being discovered + * + * Some joystick drivers don't report an initial value for analog axes. + * + * Called in the same thread as \ref IButtonMapper::MapPrimitive. + */ + virtual void OnLateAxis(const IButtonMap* buttonMap, unsigned int axisIndex) = 0; + // Button map callback interface void SetButtonMapCallback(const std::string& deviceName, IButtonMapCallback* callback) { m_callbacks[deviceName] = callback; } void ResetButtonMapCallbacks(void) { m_callbacks.clear(); } diff --git a/xbmc/input/joysticks/generic/ButtonMapping.cpp b/xbmc/input/joysticks/generic/ButtonMapping.cpp index 122c2f6ff3..4dea7f2fcf 100644 --- a/xbmc/input/joysticks/generic/ButtonMapping.cpp +++ b/xbmc/input/joysticks/generic/ButtonMapping.cpp @@ -181,6 +181,12 @@ void CAxisDetector::SetEmitted(const CDriverPrimitive& activePrimitive) void CAxisDetector::DetectType(float position) { + // Some platforms don't report a value until the axis is first changed. + // Detection relies on an initial value, so this axis will be disabled until + // the user begins button mapping again. + if (m_config.bLateDiscovery) + return; + // Update range if a range of > 1 is observed if (std::abs(position - m_config.center) > 1.0f) m_config.range = 2; @@ -237,7 +243,8 @@ CButtonMapping::CButtonMapping(IButtonMapper* buttonMapper, IButtonMap* buttonMa m_buttonMapper(buttonMapper), m_buttonMap(buttonMap), m_actionMap(actionMap), - m_lastAction(0) + m_lastAction(0), + m_frameCount(0) { assert(m_buttonMapper != nullptr); assert(m_buttonMap != nullptr); @@ -270,7 +277,7 @@ CButtonMapping::CButtonMapping(IButtonMapper* buttonMapper, IButtonMap* buttonMa axisConfig.center = primitive.Center(); axisConfig.range = primitive.Range(); - GetAxis(primitive.Index(), axisConfig).SetEmitted(primitive); + GetAxis(primitive.Index(), primitive.Center(), axisConfig).SetEmitted(primitive); } } } @@ -287,7 +294,7 @@ bool CButtonMapping::OnHatMotion(unsigned int hatIndex, HAT_STATE state) bool CButtonMapping::OnAxisMotion(unsigned int axisIndex, float position, int center, unsigned int range) { - return GetAxis(axisIndex).OnMotion(position); + return GetAxis(axisIndex, position).OnMotion(position); } void CButtonMapping::ProcessAxisMotions(void) @@ -296,6 +303,8 @@ void CButtonMapping::ProcessAxisMotions(void) axis.second.ProcessMotion(); m_buttonMapper->OnEventFrame(m_buttonMap, IsMapping()); + + m_frameCount++; } void CButtonMapping::SaveButtonMap() @@ -390,15 +399,33 @@ CHatDetector& CButtonMapping::GetHat(unsigned int hatIndex) } CAxisDetector& CButtonMapping::GetAxis(unsigned int axisIndex, + float position, const AxisConfiguration& initialConfig /* = AxisConfiguration() */) { auto itAxis = m_axes.find(axisIndex); if (itAxis == m_axes.end()) { - m_axes.insert(std::make_pair(axisIndex, CAxisDetector(this, axisIndex, initialConfig))); + AxisConfiguration config(initialConfig); + + if (m_frameCount >= 2) + { + config.bLateDiscovery = true; + OnLateDiscovery(axisIndex); + } + + // Report axis + CLog::Log(LOGDEBUG, "Axis %u discovered at position %.04f after %lu frames", + axisIndex, position, static_cast(m_frameCount)); + + m_axes.insert(std::make_pair(axisIndex, CAxisDetector(this, axisIndex, config))); itAxis = m_axes.find(axisIndex); } return itAxis->second; } + +void CButtonMapping::OnLateDiscovery(unsigned int axisIndex) +{ + m_buttonMapper->OnLateAxis(m_buttonMap, axisIndex); +} diff --git a/xbmc/input/joysticks/generic/ButtonMapping.h b/xbmc/input/joysticks/generic/ButtonMapping.h index fc935de476..6e8fec14dc 100644 --- a/xbmc/input/joysticks/generic/ButtonMapping.h +++ b/xbmc/input/joysticks/generic/ButtonMapping.h @@ -24,6 +24,7 @@ #include "input/joysticks/IDriverHandler.h" #include +#include namespace JOYSTICK { @@ -75,6 +76,7 @@ namespace JOYSTICK bool bKnown = false; int center = 0; unsigned int range = 1; + bool bLateDiscovery = false; }; class CAxisDetector @@ -242,9 +244,11 @@ namespace JOYSTICK private: bool IsMapping() const; + void OnLateDiscovery(unsigned int axisIndex); + CButtonDetector& GetButton(unsigned int buttonIndex); CHatDetector& GetHat(unsigned int hatIndex); - CAxisDetector& GetAxis(unsigned int axisIndex, const AxisConfiguration& initialConfig = AxisConfiguration()); + CAxisDetector& GetAxis(unsigned int axisIndex, float position, const AxisConfiguration& initialConfig = AxisConfiguration()); // Construction parameters IButtonMapper* const m_buttonMapper; @@ -254,6 +258,7 @@ namespace JOYSTICK std::map m_buttons; std::map m_hats; std::map m_axes; - unsigned int m_lastAction; + unsigned int m_lastAction; + uint64_t m_frameCount; }; }