Implement profile support

(cherry picked from commit 1aa6cd0224ebe4dc9ca72171728f7b500c624b65)
This commit is contained in:
pixl 2020-08-23 19:57:27 -04:00
parent f23326c660
commit f93a8b694d
No known key found for this signature in database
GPG Key ID: 1866C148CD593B6E
2 changed files with 125 additions and 18 deletions

View File

@ -218,7 +218,7 @@ std::shared_ptr<InputDevice> Device::virtualInput() const {
}
}
DeviceConfig& Device::config()
Device::Config& Device::config()
{
return _config;
}
@ -248,7 +248,7 @@ Device::DeviceIPC::DeviceIPC(Device* device) :
}
DeviceConfig::DeviceConfig(const std::shared_ptr<Configuration>& config, Device*
Device::Config::Config(const std::shared_ptr<Configuration>& config, Device*
device) : _device (device), _config (config)
{
try {
@ -256,10 +256,110 @@ DeviceConfig::DeviceConfig(const std::shared_ptr<Configuration>& config, Device*
} catch(Configuration::DeviceNotFound& e) {
logPrintf(INFO, "Device %s not configured, using default config.",
device->name().c_str());
return;
}
try {
auto& profiles = _config->getSetting(_root_setting + "/profiles");
int profile_index = 0;
if(!profiles.isList()) {
logPrintf(WARN, "Line %d: profiles must be a list, defaulting to"
"old-style config", profiles.getSourceLine());
}
try {
auto& default_profile = _config->getSetting(_root_setting +
"/default_profile");
if(default_profile.getType() == libconfig::Setting::TypeString) {
_profile_name = (const char*)default_profile;
} else if(default_profile.isNumber()) {
profile_index = default_profile;
} else {
logPrintf(WARN, "Line %d: default_profile must be a string or"
" integer, defaulting to first profile",
default_profile.getSourceLine());
}
} catch(libconfig::SettingNotFoundException& e) {
logPrintf(INFO, "Line %d: default_profile missing, defaulting to "
"first profile", profiles.getSourceLine());
}
if(profiles.getLength() <= profile_index) {
if(profiles.getLength() == 0) {
logPrintf(WARN, "Line %d: No profiles defined",
profiles.getSourceLine());
} else {
logPrintf(WARN, "Line %d: default_profile does not exist, "
"defaulting to first",
profiles.getSourceLine());
profile_index = 0;
}
}
for(int i = 0; i < profiles.getLength(); i++) {
const auto& profile = profiles[i];
std::string name;
if(!profile.isGroup()) {
logPrintf(WARN, "Line %d: Profile must be a group, "
"skipping", profile.getSourceLine());
continue;
}
try {
const auto& name_setting = profile.lookup("name");
if(name_setting.getType() !=
libconfig::Setting::TypeString) {
logPrintf(WARN, "Line %d: Profile names must be "
"strings, using name \"%d\"",
name_setting.getSourceLine(), i);
name = std::to_string(i);
} else {
name = (const char *) name_setting;
}
if(_profiles.find(name) != _profiles.end()) {
logPrintf(WARN, "Line %d: Profile with the same name "
"already exists, skipping.",
name_setting.getSourceLine());
continue;
}
} catch(libconfig::SettingNotFoundException& e) {
logPrintf(INFO, "Line %d: Profile is unnamed, using name "
"\"%d\"", profile.getSourceLine(), i);
}
if(i == profile_index && _profile_name.empty())
_profile_root = profile.getPath();
_profiles[name] = profile.getPath();
}
if(_profiles.empty()) {
_profile_name = "0";
}
if(_profile_root.empty())
_profile_root = _profiles[_profile_name];
} catch(libconfig::SettingNotFoundException& e) {
// No profiles, default to root
_profile_root = _root_setting;
}
}
libconfig::Setting& DeviceConfig::getSetting(const std::string& path)
libconfig::Setting& Device::Config::getSetting(const std::string& path)
{
return _config->getSetting(_root_setting + '/' + path);
if(_profile_root.empty())
throw libconfig::SettingNotFoundException((_root_setting + '/' +
path).c_str());
return _config->getSetting(_profile_root + '/' + path);
}
const std::map<std::string, std::string> & Device::Config::getProfiles() const
{
return _profiles;
}
void Device::Config::setProfile(const std::string &name)
{
_profile_name = name;
_profile_root = _profiles[name];
}

View File

@ -47,29 +47,19 @@ namespace logid
const std::weak_ptr<DeviceManager> _manager;
};
class DeviceConfig
{
public:
DeviceConfig(const std::shared_ptr<Configuration>& config, Device*
device);
libconfig::Setting& getSetting(const std::string& path);
private:
Device* _device;
std::string _root_setting;
std::shared_ptr<Configuration> _config;
};
/* TODO: Implement HID++ 1.0 support
* Currently, the logid::Device class has a hardcoded requirement
* for an HID++ 2.0 device.
*/
class Device : public ipcgull::object
{
private:
class Config;
public:
std::string name();
uint16_t pid();
DeviceConfig& config();
Config& config();
backend::hidpp20::Device& hidpp20();
static std::shared_ptr<Device> make(
@ -130,12 +120,29 @@ namespace logid
}
}
class Config
{
public:
Config(const std::shared_ptr<Configuration>& config, Device*
device);
libconfig::Setting& getSetting(const std::string& path);
const std::map<std::string, std::string>& getProfiles() const;
void setProfile(const std::string& name);
private:
Device* _device;
std::string _root_setting;
std::string _profile_root;
std::string _profile_name;
std::map<std::string, std::string> _profiles;
std::shared_ptr<Configuration> _config;
};
backend::hidpp20::Device _hidpp20;
std::string _path;
backend::hidpp::DeviceIndex _index;
std::map<std::string, std::shared_ptr<features::DeviceFeature>>
_features;
DeviceConfig _config;
Config _config;
Receiver* _receiver;
const std::weak_ptr<DeviceManager> _manager;