From 949a1ee2839e2b8e4ad2a9071694ac1d3eab2107 Mon Sep 17 00:00:00 2001 From: pixl Date: Sun, 12 Jul 2020 00:06:33 -0400 Subject: [PATCH] Add CycleDPI action --- src/logid/CMakeLists.txt | 1 + src/logid/actions/Action.cpp | 3 + src/logid/actions/CycleDPI.cpp | 133 +++++++++++++++++++++++++ src/logid/actions/CycleDPI.h | 56 +++++++++++ src/logid/actions/ToggleSmartShift.cpp | 5 +- src/logid/features/DPI.cpp | 10 ++ src/logid/features/DPI.h | 3 + 7 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 src/logid/actions/CycleDPI.cpp create mode 100644 src/logid/actions/CycleDPI.h diff --git a/src/logid/CMakeLists.txt b/src/logid/CMakeLists.txt index f544666..32746d4 100644 --- a/src/logid/CMakeLists.txt +++ b/src/logid/CMakeLists.txt @@ -25,6 +25,7 @@ add_executable(logid actions/KeypressAction.cpp actions/ToggleHiresScroll.cpp actions/ToggleSmartShift.cpp + actions/CycleDPI.cpp actions/GestureAction.cpp actions/gesture/Gesture.cpp actions/gesture/ReleaseGesture.cpp diff --git a/src/logid/actions/Action.cpp b/src/logid/actions/Action.cpp index b1cd85b..41cf325 100644 --- a/src/logid/actions/Action.cpp +++ b/src/logid/actions/Action.cpp @@ -24,6 +24,7 @@ #include "ToggleHiresScroll.h" #include "GestureAction.h" #include "NullAction.h" +#include "CycleDPI.h" using namespace logid; using namespace logid::actions; @@ -57,6 +58,8 @@ std::shared_ptr Action::makeAction(Device *device, libconfig::Setting return std::make_shared(device); else if(type == "gestures") return std::make_shared(device, setting); + else if(type == "cycledpi") + return std::make_shared(device, setting); else if(type == "none") return std::make_shared(device); else diff --git a/src/logid/actions/CycleDPI.cpp b/src/logid/actions/CycleDPI.cpp new file mode 100644 index 0000000..19b729c --- /dev/null +++ b/src/logid/actions/CycleDPI.cpp @@ -0,0 +1,133 @@ +/* + * Copyright 2019-2020 PixlOne + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#include "CycleDPI.h" +#include "../Device.h" +#include "../util/task.h" +#include "../util/log.h" +#include "../backend/hidpp20/Error.h" +#include "../backend/hidpp20/features/ReprogControls.h" + +using namespace logid::actions; +using namespace libconfig; + +CycleDPI::CycleDPI(Device* device, libconfig::Setting& setting) : + Action (device), _config (device, setting) +{ + _dpi = _device->getFeature("dpi"); + if(!_dpi) + logPrintf(WARN, "%s:%d: DPI feature not found, cannot use " + "CycleDPI action.", + _device->hidpp20().devicePath().c_str(), + _device->hidpp20().deviceIndex()); +} + +void CycleDPI::press() +{ + _pressed = true; + if(_dpi && !_config.empty()) { + task::spawn([this](){ + uint16_t dpi = _config.nextDPI(); + try { + _dpi->setDPI(dpi, _config.sensor()); + } catch (backend::hidpp20::Error& e) { + if(e.code() == backend::hidpp20::Error::InvalidArgument) + logPrintf(WARN, "%s:%d: Could not set DPI to %d for " + "sensor %d", _device->hidpp20().devicePath().c_str(), + _device->hidpp20().deviceIndex(), dpi, + _config.sensor()); + else + throw e; + } + }); + } +} + +void CycleDPI::release() +{ + _pressed = false; +} + +uint8_t CycleDPI::reprogFlags() const +{ + return backend::hidpp20::ReprogControls::TemporaryDiverted; +} + +CycleDPI::Config::Config(Device *device, libconfig::Setting &config) : + Action::Config(device), _current_index (0), _sensor (0) +{ + if(!config.isGroup()) { + logPrintf(WARN, "Line %d: action must be an object, skipping.", + config.getSourceLine()); + return; + } + + try { + auto& sensor = config.lookup("sensor"); + if(sensor.getType() != Setting::TypeInt) + logPrintf(WARN, "Line %d: sensor must be an integer", + sensor.getSourceLine()); + _sensor = (int)sensor; + } catch(libconfig::SettingNotFoundException& e) { + // Ignore + } + + try { + auto& dpis = config.lookup("dpis"); + if(!dpis.isList() && !dpis.isArray()) { + logPrintf(WARN, "Line %d: dpis must be a list or array, skipping.", + dpis.getSourceLine()); + return; + } + + int dpi_count = dpis.getLength(); + for(int i = 0; i < dpi_count; i++) { + if(dpis[i].getType() != Setting::TypeInt) { + logPrintf(WARN, "Line %d: dpis must be integers, skipping.", + dpis[i].getSourceLine()); + if(dpis.isList()) + continue; + else + break; + } + + _dpis.push_back((int)(dpis[i])); + } + + } catch (libconfig::SettingNotFoundException& e) { + logPrintf(WARN, "Line %d: dpis is a required field, skipping.", + config.getSourceLine()); + } +} + +uint16_t CycleDPI::Config::nextDPI() +{ + uint16_t dpi = _dpis[_current_index++]; + if(_current_index >= _dpis.size()) + _current_index = 0; + return dpi; +} + +bool CycleDPI::Config::empty() const +{ + return _dpis.empty(); +} + +uint8_t CycleDPI::Config::sensor() const +{ + return _sensor; +} \ No newline at end of file diff --git a/src/logid/actions/CycleDPI.h b/src/logid/actions/CycleDPI.h new file mode 100644 index 0000000..b6a5017 --- /dev/null +++ b/src/logid/actions/CycleDPI.h @@ -0,0 +1,56 @@ +/* + * Copyright 2019-2020 PixlOne + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef LOGID_ACTION_CYCLEDPI_H +#define LOGID_ACTION_CYCLEDPI_H + +#include +#include "Action.h" +#include "../features/DPI.h" + +namespace logid { +namespace actions { + class CycleDPI : public Action + { + public: + explicit CycleDPI(Device* device, libconfig::Setting& setting); + + virtual void press(); + virtual void release(); + + virtual uint8_t reprogFlags() const; + + class Config : public Action::Config + { + public: + Config(Device* device, libconfig::Setting& setting); + uint16_t nextDPI(); + bool empty() const; + uint8_t sensor() const; + private: + std::size_t _current_index; + std::vector _dpis; + uint8_t _sensor; + }; + + protected: + Config _config; + std::shared_ptr _dpi; + }; +}} + +#endif //LOGID_ACTION_CYCLEDPI_H \ No newline at end of file diff --git a/src/logid/actions/ToggleSmartShift.cpp b/src/logid/actions/ToggleSmartShift.cpp index 28885ae..5e4fd6e 100644 --- a/src/logid/actions/ToggleSmartShift.cpp +++ b/src/logid/actions/ToggleSmartShift.cpp @@ -30,14 +30,13 @@ ToggleSmartShift::ToggleSmartShift(Device *dev) : Action (dev) logPrintf(WARN, "%s:%d: SmartShift feature not found, cannot use " "ToggleSmartShift action.", _device->hidpp20().devicePath().c_str(), - _device->hidpp20().devicePath().c_str()); + _device->hidpp20().deviceIndex()); } void ToggleSmartShift::press() { _pressed = true; - if(_smartshift) - { + if(_smartshift) { task::spawn([ss=this->_smartshift](){ auto status = ss->getStatus(); status.setActive = true; diff --git a/src/logid/features/DPI.cpp b/src/logid/features/DPI.cpp index 5d1bfd2..ffc5482 100644 --- a/src/logid/features/DPI.cpp +++ b/src/logid/features/DPI.cpp @@ -80,6 +80,16 @@ void DPI::listen() { } +uint16_t DPI::getDPI(uint8_t sensor) +{ + return _adjustable_dpi.getSensorDPI(sensor); +} + +void DPI::setDPI(uint16_t dpi, uint8_t sensor) +{ + _adjustable_dpi.setSensorDPI(sensor, dpi); +} + /* Some devices have multiple sensors, but an older config format * only supports a single DPI. The dpi setting can be an array or * an integer. diff --git a/src/logid/features/DPI.h b/src/logid/features/DPI.h index b4c5ca6..78f102f 100644 --- a/src/logid/features/DPI.h +++ b/src/logid/features/DPI.h @@ -31,6 +31,9 @@ namespace features virtual void configure(); virtual void listen(); + uint16_t getDPI(uint8_t sensor=0); + void setDPI(uint16_t dpi, uint8_t sensor=0); + class Config : public DeviceFeature::Config { public: