Skip to content

Commit

Permalink
Serialize anomalous triggers to button map XML
Browse files Browse the repository at this point in the history
  • Loading branch information
garbear committed Aug 19, 2016
1 parent 513bf5c commit f0c5af5
Show file tree
Hide file tree
Showing 10 changed files with 152 additions and 23 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
34 changes: 23 additions & 11 deletions src/api/AnomalousTriggerFilter.cpp → src/api/AnomalousTrigger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
* <http://www.gnu.org/licenses/>.
*/

#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),
Expand All @@ -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)
Expand All @@ -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
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}
25 changes: 16 additions & 9 deletions src/api/AnomalousTriggerFilter.h → src/api/AnomalousTrigger.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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;
Expand Down
22 changes: 20 additions & 2 deletions src/api/Joystick.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
* <http://www.gnu.org/licenses/>.
*/

#include "AnomalousTriggerFilter.h"
#include "Joystick.h"
#include "AnomalousTrigger.h"
#include "log/Log.h"
#include "settings/Settings.h"
#include "utils/CommonMacros.h"
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -137,6 +138,23 @@ bool CJoystick::SendEvent(const ADDON::PeripheralEvent& event)
return bHandled;
}

std::vector<CAnomalousTrigger*> CJoystick::GetAnomalousTriggers()
{
std::vector<CAnomalousTrigger*> result;

for (IJoystickAxisFilter* filter : m_axisFilters)
{
CAnomalousTrigger* trigger = dynamic_cast<CAnomalousTrigger*>(filter);
if (!trigger)
continue;

if (trigger->IsAnomalousTrigger())
result.push_back(trigger);
}

return result;
}

void CJoystick::GetButtonEvents(std::vector<ADDON::PeripheralEvent>& events)
{
const std::vector<JOYSTICK_STATE_BUTTON>& buttons = m_stateBuffer.buttons;
Expand Down
3 changes: 3 additions & 0 deletions src/api/Joystick.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

namespace JOYSTICK
{
class CAnomalousTrigger;
class IJoystickAxisFilter;

class CJoystick : public ADDON::Joystick
Expand Down Expand Up @@ -90,6 +91,8 @@ namespace JOYSTICK
*/
virtual void PowerOff() { }

std::vector<CAnomalousTrigger*> GetAnomalousTriggers();

protected:
/*!
* Implemented by derived class to scan for events
Expand Down
18 changes: 18 additions & 0 deletions src/api/JoystickManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<ADDON::PeripheralEvent>& events)
{
CLockObject lock(m_joystickMutex);
Expand Down
2 changes: 2 additions & 0 deletions src/api/JoystickManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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()
*/
Expand Down
6 changes: 6 additions & 0 deletions src/storage/xml/ButtonMapDefinitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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"
60 changes: 60 additions & 0 deletions src/storage/xml/ButtonMapXml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <algorithm>
#include <cmath>
#include <cstdlib>
#include <sstream>
Expand Down Expand Up @@ -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<unsigned int, CAnomalousTrigger*> triggers;

// Get triggers
JoystickVector joysticks = CJoystickManager::Get().GetJoysticks(*m_device);
for (const auto& joystick : joysticks)
{
std::vector<CAnomalousTrigger*> 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)
Expand Down
3 changes: 3 additions & 0 deletions src/storage/xml/ButtonMapXml.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ namespace ADDON

namespace JOYSTICK
{
class CAnomalousTrigger;
class CButtonMap;

class CButtonMapXml : public CButtonMap
Expand All @@ -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);
Expand Down

0 comments on commit f0c5af5

Please sign in to comment.