Skip to content

Commit

Permalink
Update to peripheral API v1.0.24 - Allow partial list of features to …
Browse files Browse the repository at this point in the history
…be mapped
  • Loading branch information
garbear committed Aug 26, 2016
1 parent 4033986 commit 48538a7
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 65 deletions.
145 changes: 84 additions & 61 deletions src/storage/ButtonMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,32 @@ const ButtonMap& CButtonMap::GetButtonMap()

bool CButtonMap::MapFeatures(const std::string& controllerId, const FeatureVector& features)
{
FeatureVector& oldFeatures = m_buttonMap[controllerId];
FeatureVector& myFeatures = m_buttonMap[controllerId];

// TODO: Optimize case when features are unchanged
bool bChanged = true; // TODO

if (bChanged)
{
oldFeatures = features;
// Remove features with the same name
for (auto& newFeature : features)
{
myFeatures.erase(std::remove_if(myFeatures.begin(), myFeatures.end(),
[newFeature](const ADDON::JoystickFeature& feature)
{
return feature.Name() == newFeature.Name();
}), myFeatures.end());
}

myFeatures.insert(myFeatures.begin(), features.begin(), features.end());

Sanitize(controllerId, myFeatures);

std::sort(myFeatures.begin(), myFeatures.end(),
[](const ADDON::JoystickFeature& lhs, const ADDON::JoystickFeature& rhs)
{
return lhs.Name() < rhs.Name();
});

if (Save())
{
Expand Down Expand Up @@ -106,91 +124,96 @@ bool CButtonMap::Refresh(void)
if (!Load())
return false;

Sanitize();
for (auto it = m_buttonMap.begin(); it != m_buttonMap.end(); ++it)
Sanitize(it->first, it->second);

m_timestamp = now;
}

return true;
}

void CButtonMap::Sanitize()
void CButtonMap::Sanitize(const std::string& controllerId, FeatureVector& features)
{
for (auto it = m_buttonMap.begin(); it != m_buttonMap.end(); ++it)
// Loop through features
for (unsigned int iFeature = 0; iFeature < features.size(); ++iFeature)
{
const std::string& controllerId = it->first;
FeatureVector& features = it->second;
auto& feature = features[iFeature];

// Loop through features
for (unsigned int iFeature = 0; iFeature < features.size(); ++iFeature)
// Loop through feature's primitives
auto& primitives = feature.Primitives();
for (unsigned int iPrimitive = 0; iPrimitive < primitives.size(); ++iPrimitive)
{
auto& feature = features[iFeature];

// Loop through feature's primitives
auto& primitives = feature.Primitives();
for (unsigned int iPrimitive = 0; iPrimitive < primitives.size(); ++iPrimitive)
{
auto& primitive = primitives[iPrimitive];
auto& primitive = primitives[iPrimitive];

if (primitive.Type() == JOYSTICK_DRIVER_PRIMITIVE_TYPE_UNKNOWN)
continue;
if (primitive.Type() == JOYSTICK_DRIVER_PRIMITIVE_TYPE_UNKNOWN)
continue;

bool bFound = false;
bool bFound = false;

// Search for prior feature with the primitive
ADDON::JoystickFeature existingFeature;
// Search for prior feature with the primitive
ADDON::JoystickFeature existingFeature;

for (unsigned int iExistingFeature = 0; iExistingFeature < iFeature; ++iExistingFeature)
for (unsigned int iExistingFeature = 0; iExistingFeature < iFeature; ++iExistingFeature)
{
const auto& existingPrimitives = features[iExistingFeature].Primitives();
if (std::find(existingPrimitives.begin(), existingPrimitives.end(), primitive) != existingPrimitives.end())
{
const auto& existingPrimitives = features[iExistingFeature].Primitives();
if (std::find(existingPrimitives.begin(), existingPrimitives.end(), primitive) != existingPrimitives.end())
{
existingFeature = features[iExistingFeature];
bFound = true;
break;
}
existingFeature = features[iExistingFeature];
bFound = true;
break;
}
}

if (!bFound)
if (!bFound)
{
// Search for primitive in prior primitives
for (unsigned int iExistingPrimitive = 0; iExistingPrimitive < iPrimitive; ++iExistingPrimitive)
{
// Search for primitive in prior primitives
for (unsigned int iExistingPrimitive = 0; iExistingPrimitive < iPrimitive; ++iExistingPrimitive)
if (primitives[iExistingPrimitive] == primitive)
{
if (primitives[iExistingPrimitive] == primitive)
{
bFound = true;
break;
}
bFound = true;
break;
}
}
}

// Invalid the primitive if it has already been seen
if (bFound)
{
esyslog("%s: %s (%s) conflicts with %s (%s), skipping",
controllerId.c_str(),
CStorageUtils::PrimitiveToString(primitive).c_str(),
existingFeature.Type() != JOYSTICK_FEATURE_TYPE_UNKNOWN ? existingFeature.Name().c_str() : feature.Name().c_str(),
CStorageUtils::PrimitiveToString(primitive).c_str(),
feature.Name().c_str());

primitive = ADDON::DriverPrimitive();
}
// Invalid the primitive if it has already been seen
if (bFound)
{
esyslog("%s: %s (%s) conflicts with %s (%s)",
controllerId.c_str(),
CStorageUtils::PrimitiveToString(primitive).c_str(),
existingFeature.Type() != JOYSTICK_FEATURE_TYPE_UNKNOWN ? existingFeature.Name().c_str() : feature.Name().c_str(),
CStorageUtils::PrimitiveToString(primitive).c_str(),
feature.Name().c_str());

primitive = ADDON::DriverPrimitive();
}
}
}

// Erase invalid features
features.erase(std::remove_if(features.begin(), features.end(),
[](const ADDON::JoystickFeature& feature)
{
auto& primitives = feature.Primitives();
// Erase invalid features
features.erase(std::remove_if(features.begin(), features.end(),
[controllerId](const ADDON::JoystickFeature& feature)
{
auto& primitives = feature.Primitives();

return std::find_if(primitives.begin(), primitives.end(),
[](const ADDON::DriverPrimitive& primitive)
{
return primitive.Type() != JOYSTICK_DRIVER_PRIMITIVE_TYPE_UNKNOWN;
}) == primitives.end();
// Find invalid primitive
auto it = std::find_if(primitives.begin(), primitives.end(),
[](const ADDON::DriverPrimitive& primitive)
{
return primitive.Type() != JOYSTICK_DRIVER_PRIMITIVE_TYPE_UNKNOWN;
});

}), features.end());
}
const bool bIsValid = (it != primitives.end());

if (!bIsValid)
{
dsyslog("%s: Removing %s from button map", controllerId.c_str(), feature.Name().c_str());
return true;
}

return false;
}), features.end());
}
2 changes: 1 addition & 1 deletion src/storage/ButtonMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ namespace JOYSTICK
virtual bool Load(void) = 0;
virtual bool Save(void) const = 0;

void Sanitize();
static void Sanitize(const std::string& controllerId, FeatureVector& features);

const std::string m_strResourcePath;
DevicePtr m_device;
Expand Down
17 changes: 14 additions & 3 deletions src/storage/xml/ButtonMapXml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ bool CButtonMapXml::Deserialize(const TiXmlElement* pElement, FeatureVector& fea
return false;
}

while (pFeature)
for ( ; pFeature != nullptr; pFeature = pFeature->NextSiblingElement(BUTTONMAP_XML_ELEM_FEATURE))
{
const char* name = pFeature->Attribute(BUTTONMAP_XML_ATTR_FEATURE_NAME);
if (!name)
Expand All @@ -397,6 +397,19 @@ bool CButtonMapXml::Deserialize(const TiXmlElement* pElement, FeatureVector& fea
}
std::string strName(name);

// Check if the feature was already deserialized
auto it = std::find_if(features.begin(), features.end(),
[strName](const ADDON::JoystickFeature& feature)
{
return feature.Name() == strName;
});

if (it != features.end())
{
esyslog("Duplicate feature \"%s\" found, skipping", strName.c_str());
continue;
}

const TiXmlElement* pUp = nullptr;
const TiXmlElement* pDown = nullptr;
const TiXmlElement* pRight = nullptr;
Expand Down Expand Up @@ -536,8 +549,6 @@ bool CButtonMapXml::Deserialize(const TiXmlElement* pElement, FeatureVector& fea
}

features.push_back(feature);

pFeature = pFeature->NextSiblingElement(BUTTONMAP_XML_ELEM_FEATURE);
}

return true;
Expand Down

0 comments on commit 48538a7

Please sign in to comment.