diff --git a/CMakeLists.txt b/CMakeLists.txt
index 17046915..863f50bc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -22,7 +22,7 @@ include_directories(${INCLUDES}
${PCRE_INCLUDE_DIRS})
set(JOYSTICK_SOURCES src/addon.cpp
- src/api/AnomalousTriggerFilter.cpp
+ src/api/AnomalousTrigger.cpp
src/api/Joystick.cpp
src/api/JoystickAsync.cpp
src/api/JoystickInterfaceCallback.cpp
diff --git a/src/api/AnomalousTriggerFilter.cpp b/src/api/AnomalousTrigger.cpp
similarity index 80%
rename from src/api/AnomalousTriggerFilter.cpp
rename to src/api/AnomalousTrigger.cpp
index e23781eb..b22300d1 100644
--- a/src/api/AnomalousTriggerFilter.cpp
+++ b/src/api/AnomalousTrigger.cpp
@@ -17,15 +17,15 @@
* .
*/
-#include "AnomalousTriggerFilter.h"
+#include "AnomalousTrigger.h"
#include "log/Log.h"
using namespace JOYSTICK;
#define ANOMOLOUS_MAGNITUDE 0.5f
-CAnomalousTriggerFilter::CAnomalousTriggerFilter(unsigned int axisIndex)
- : axisIndex(axisIndex),
+CAnomalousTrigger::CAnomalousTrigger(unsigned int axisIndex)
+ : m_axisIndex(axisIndex),
m_state(STATE_UNKNOWN),
m_center(CENTER_ZERO),
m_range(TRIGGER_RANGE_HALF),
@@ -35,7 +35,7 @@ CAnomalousTriggerFilter::CAnomalousTriggerFilter(unsigned int axisIndex)
{
}
-float CAnomalousTriggerFilter::Filter(float value)
+float CAnomalousTrigger::Filter(float value)
{
// First, check for discrete D-pad
if (m_state == STATE_UNKNOWN)
@@ -51,7 +51,7 @@ float CAnomalousTriggerFilter::Filter(float value)
if (m_bCenterSeen && m_bPositiveOneSeen && m_bNegativeOneSeen)
{
m_state = STATE_DISCRETE_DPAD;
- dsyslog("Discrete D-pad detected on axis %u", axisIndex);
+ dsyslog("Discrete D-pad detected on axis %u", m_axisIndex);
}
}
else
@@ -71,7 +71,7 @@ float CAnomalousTriggerFilter::Filter(float value)
m_center = CENTER_ZERO;
if (IsAnomalousTrigger())
- dsyslog("Anomalous trigger detected on axis %u (initial value = %f)", axisIndex, value);
+ dsyslog("Anomalous trigger detected on axis %u (initial value = %f)", m_axisIndex, value);
m_state = STATE_CENTER_KNOWN;
}
@@ -105,19 +105,31 @@ float CAnomalousTriggerFilter::Filter(float value)
return value;
}
-bool CAnomalousTriggerFilter::IsAnomalousTrigger(void)
+bool CAnomalousTrigger::IsAnomalousTrigger(void) const
{
return m_center != CENTER_ZERO;
}
-float CAnomalousTriggerFilter::GetCenter(AXIS_CENTER center)
+int CAnomalousTrigger::GetCenter(AXIS_CENTER center)
{
switch (center)
{
- case CENTER_NEGATIVE_ONE: return -1.0f;
- case CENTER_POSITIVE_ONE: return 1.0f;
+ case CENTER_NEGATIVE_ONE: return -1;
+ case CENTER_POSITIVE_ONE: return 1;
default:
break;
}
- return 0.0f;
+ return 0;
+}
+
+int CAnomalousTrigger::GetRange(TRIGGER_RANGE range)
+{
+ switch (range)
+ {
+ case TRIGGER_RANGE_HALF: return 1;
+ case TRIGGER_RANGE_FULL: return 2;
+ default:
+ break;
+ }
+ return 1;
}
diff --git a/src/api/AnomalousTriggerFilter.h b/src/api/AnomalousTrigger.h
similarity index 87%
rename from src/api/AnomalousTriggerFilter.h
rename to src/api/AnomalousTrigger.h
index 4b946bfe..d10de676 100644
--- a/src/api/AnomalousTriggerFilter.h
+++ b/src/api/AnomalousTrigger.h
@@ -45,14 +45,25 @@ namespace JOYSTICK
*
* Triggers centered about 1.0 are transformed to travel from zero to -1.0.
*/
- class CAnomalousTriggerFilter : public IJoystickAxisFilter
+ class CAnomalousTrigger : public IJoystickAxisFilter
{
public:
- CAnomalousTriggerFilter(unsigned int axisIndex);
+ CAnomalousTrigger(unsigned int axisIndex);
// implementation of IJoystickAxisFilter
virtual float Filter(float value) override;
+ /*!
+ * \brief Has this axis been detected as an anomalous trigger
+ */
+ bool IsAnomalousTrigger(void) const;
+
+ unsigned int AxisIndex(void) const { return m_axisIndex; }
+
+ unsigned int Center(void) const { return GetCenter(m_center); }
+
+ unsigned int Range(void) const { return GetRange(m_range); }
+
private:
enum AXIS_STATE
{
@@ -95,17 +106,13 @@ namespace JOYSTICK
TRIGGER_RANGE_FULL, // trigger value is in the interval [-1.0, 1.0]
};
- /*!
- * \brief Has this axis been detected as an anomalous trigger
- */
- bool IsAnomalousTrigger(void);
-
/*!
* \brief Helper functions
*/
- static float GetCenter(AXIS_CENTER center);
+ static int GetCenter(AXIS_CENTER center);
+ static int GetRange(TRIGGER_RANGE range);
- const unsigned int axisIndex;
+ const unsigned int m_axisIndex;
AXIS_STATE m_state;
AXIS_CENTER m_center;
TRIGGER_RANGE m_range;
diff --git a/src/api/Joystick.cpp b/src/api/Joystick.cpp
index d2f2d08a..2f32761b 100644
--- a/src/api/Joystick.cpp
+++ b/src/api/Joystick.cpp
@@ -17,8 +17,8 @@
* .
*/
-#include "AnomalousTriggerFilter.h"
#include "Joystick.h"
+#include "AnomalousTrigger.h"
#include "log/Log.h"
#include "settings/Settings.h"
#include "utils/CommonMacros.h"
@@ -82,8 +82,9 @@ bool CJoystick::Initialize(void)
m_stateBuffer.axes.assign(AxisCount(), 0.0f);
// Filter for anomalous triggers
+ m_axisFilters.reserve(AxisCount());
for (unsigned int i = 0; i < AxisCount(); i++)
- m_axisFilters.push_back(new CAnomalousTriggerFilter(i));
+ m_axisFilters.push_back(new CAnomalousTrigger(i));
return true;
}
@@ -137,6 +138,23 @@ bool CJoystick::SendEvent(const ADDON::PeripheralEvent& event)
return bHandled;
}
+std::vector CJoystick::GetAnomalousTriggers()
+{
+ std::vector result;
+
+ for (IJoystickAxisFilter* filter : m_axisFilters)
+ {
+ CAnomalousTrigger* trigger = dynamic_cast(filter);
+ if (!trigger)
+ continue;
+
+ if (trigger->IsAnomalousTrigger())
+ result.push_back(trigger);
+ }
+
+ return result;
+}
+
void CJoystick::GetButtonEvents(std::vector& events)
{
const std::vector& buttons = m_stateBuffer.buttons;
diff --git a/src/api/Joystick.h b/src/api/Joystick.h
index d0edd522..ed347088 100644
--- a/src/api/Joystick.h
+++ b/src/api/Joystick.h
@@ -25,6 +25,7 @@
namespace JOYSTICK
{
+ class CAnomalousTrigger;
class IJoystickAxisFilter;
class CJoystick : public ADDON::Joystick
@@ -90,6 +91,8 @@ namespace JOYSTICK
*/
virtual void PowerOff() { }
+ std::vector GetAnomalousTriggers();
+
protected:
/*!
* Implemented by derived class to scan for events
diff --git a/src/api/JoystickManager.cpp b/src/api/JoystickManager.cpp
index 2bda5a93..ab2e9e80 100644
--- a/src/api/JoystickManager.cpp
+++ b/src/api/JoystickManager.cpp
@@ -219,6 +219,24 @@ JoystickPtr CJoystickManager::GetJoystick(unsigned int index) const
return JoystickPtr();
}
+JoystickVector CJoystickManager::GetJoysticks(const ADDON::Joystick& joystickInfo) const
+{
+ JoystickVector result;
+
+ CLockObject lock(m_joystickMutex);
+
+ for (const auto& joystick : m_joysticks)
+ {
+ if (joystick->Name() == joystickInfo.Name() &&
+ joystick->Provider() == joystickInfo.Provider())
+ {
+ result.push_back(joystick);
+ }
+ }
+
+ return result;
+}
+
bool CJoystickManager::GetEvents(std::vector& events)
{
CLockObject lock(m_joystickMutex);
diff --git a/src/api/JoystickManager.h b/src/api/JoystickManager.h
index 8af98be5..69f0c626 100644
--- a/src/api/JoystickManager.h
+++ b/src/api/JoystickManager.h
@@ -74,6 +74,8 @@ namespace JOYSTICK
JoystickPtr GetJoystick(unsigned int index) const;
+ JoystickVector GetJoysticks(const ADDON::Joystick& joystickInfo) const;
+
/*!
* \brief Get all events that have occurred since the last call to GetEvents()
*/
diff --git a/src/storage/xml/ButtonMapDefinitions.h b/src/storage/xml/ButtonMapDefinitions.h
index 332f6bcf..b069e2e5 100644
--- a/src/storage/xml/ButtonMapDefinitions.h
+++ b/src/storage/xml/ButtonMapDefinitions.h
@@ -21,6 +21,8 @@
#define BUTTONMAP_XML_ROOT "buttonmap"
#define BUTTONMAP_XML_ELEM_DEVICE "device"
+#define BUTTONMAP_XML_ELEM_CONFIGURATION "configuration"
+#define BUTTONMAP_XML_ELEM_AXIS "axis"
#define BUTTONMAP_XML_ELEM_CONTROLLER "controller"
#define BUTTONMAP_XML_ELEM_FEATURE "feature"
@@ -50,3 +52,7 @@
#define BUTTONMAP_XML_ATTR_FEATURE_HAT "hat"
#define BUTTONMAP_XML_ATTR_FEATURE_AXIS "axis"
#define BUTTONMAP_XML_ATTR_FEATURE_MOTOR "motor"
+
+#define BUTTONMAP_XML_ATTR_AXIS_INDEX "index"
+#define BUTTONMAP_XML_ATTR_AXIS_CENTER "center"
+#define BUTTONMAP_XML_ATTR_AXIS_RANGE "range"
diff --git a/src/storage/xml/ButtonMapXml.cpp b/src/storage/xml/ButtonMapXml.cpp
index ff0e3e3c..b04b971d 100644
--- a/src/storage/xml/ButtonMapXml.cpp
+++ b/src/storage/xml/ButtonMapXml.cpp
@@ -21,12 +21,16 @@
#include "ButtonMapXml.h"
#include "ButtonMapDefinitions.h"
#include "DeviceXml.h"
+#include "api/AnomalousTrigger.h"
+#include "api/Joystick.h"
+#include "api/JoystickManager.h"
#include "buttonmapper/ButtonMapTranslator.h"
#include "storage/Device.h"
#include "log/Log.h"
#include "tinyxml.h"
+#include
#include
#include
#include
@@ -145,12 +149,68 @@ bool CButtonMapXml::Save(void) const
CDeviceXml::Serialize(*m_device, deviceElem);
+ if (!SerializeTriggers(deviceElem))
+ return false;
+
if (!SerializeButtonMaps(deviceElem))
return false;
return xmlFile.SaveFile(m_strResourcePath);
}
+bool CButtonMapXml::SerializeTriggers(TiXmlElement* pElement) const
+{
+ std::map triggers;
+
+ // Get triggers
+ JoystickVector joysticks = CJoystickManager::Get().GetJoysticks(*m_device);
+ for (const auto& joystick : joysticks)
+ {
+ std::vector triggerVec = joystick->GetAnomalousTriggers();
+ for (CAnomalousTrigger* trigger : triggerVec)
+ triggers[trigger->AxisIndex()] = trigger;
+ }
+
+ // Serialize triggers
+ if (!triggers.empty())
+ {
+ TiXmlElement configurationElement(BUTTONMAP_XML_ELEM_CONFIGURATION);
+ TiXmlNode* configurationNode = pElement->InsertEndChild(configurationElement);
+ if (configurationNode == nullptr)
+ return false;
+
+ TiXmlElement* configurationElem = configurationNode->ToElement();
+ if (configurationElem == nullptr)
+ return false;
+
+ for (auto itTrigger = triggers.begin(); itTrigger != triggers.end(); ++itTrigger)
+ {
+ if (!SerializeTrigger(configurationElem, itTrigger->second))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool CButtonMapXml::SerializeTrigger(TiXmlElement* pElement, const CAnomalousTrigger* trigger)
+{
+ TiXmlElement axisElement(BUTTONMAP_XML_ELEM_AXIS);
+ TiXmlNode* axisNode = pElement->InsertEndChild(axisElement);
+ if (axisNode == nullptr)
+ return false;
+
+ TiXmlElement* axisElem = axisNode->ToElement();
+ if (axisElem == nullptr)
+ return false;
+
+ axisElem->SetAttribute(BUTTONMAP_XML_ATTR_AXIS_INDEX, trigger->AxisIndex());
+ axisElem->SetAttribute(BUTTONMAP_XML_ATTR_AXIS_CENTER, trigger->Center());
+ axisElem->SetAttribute(BUTTONMAP_XML_ATTR_AXIS_RANGE, trigger->Range());
+
+ return true;
+}
+
bool CButtonMapXml::SerializeButtonMaps(TiXmlElement* pElement) const
{
for (ButtonMap::const_iterator it = m_buttonMap.begin(); it != m_buttonMap.end(); ++it)
diff --git a/src/storage/xml/ButtonMapXml.h b/src/storage/xml/ButtonMapXml.h
index 0a260670..b87b1067 100644
--- a/src/storage/xml/ButtonMapXml.h
+++ b/src/storage/xml/ButtonMapXml.h
@@ -33,6 +33,7 @@ namespace ADDON
namespace JOYSTICK
{
+ class CAnomalousTrigger;
class CButtonMap;
class CButtonMapXml : public CButtonMap
@@ -50,11 +51,13 @@ namespace JOYSTICK
private:
bool SerializeButtonMaps(TiXmlElement* pElement) const;
+ bool SerializeTriggers(TiXmlElement* pElement) const;
static bool Serialize(const FeatureVector& features, TiXmlElement* pElement);
static bool Deserialize(const TiXmlElement* pElement, FeatureVector& features);
static bool IsValid(const ADDON::JoystickFeature& feature);
+ static bool SerializeTrigger(TiXmlElement* pElement, const CAnomalousTrigger* trigger);
static bool SerializeFeature(TiXmlElement* pElement, const ADDON::DriverPrimitive& primitive, const char* tagName);
static bool SerializePrimitiveTag(TiXmlElement* pElement, const ADDON::DriverPrimitive& primitive, const char* tagName);
static void SerializePrimitive(TiXmlElement* pElement, const ADDON::DriverPrimitive& primitive);