From 69e24b891c7261547594e59fa5cc480a6d9798ba Mon Sep 17 00:00:00 2001 From: Ingo Ruhnke Date: Tue, 12 Apr 2011 12:16:21 +0200 Subject: [PATCH] Split AxisEvent into separate files --- SConstruct | 3 +- src/axis_event.cpp | 440 +----------------- src/axis_event.hpp | 93 ---- src/axisevent/abs_axis_event_handler.cpp | 105 +++++ src/axisevent/abs_axis_event_handler.hpp | 47 ++ src/axisevent/key_axis_event_handler.cpp | 189 ++++++++ src/axisevent/key_axis_event_handler.hpp | 51 ++ src/axisevent/rel_axis_event_handler.cpp | 135 ++++++ src/axisevent/rel_axis_event_handler.hpp | 50 ++ .../rel_repeat_axis_event_handler.cpp | 113 +++++ .../rel_repeat_axis_event_handler.hpp | 49 ++ src/ui_event.cpp | 13 + src/ui_event.hpp | 1 + 13 files changed, 760 insertions(+), 529 deletions(-) create mode 100644 src/axisevent/abs_axis_event_handler.cpp create mode 100644 src/axisevent/abs_axis_event_handler.hpp create mode 100644 src/axisevent/key_axis_event_handler.cpp create mode 100644 src/axisevent/key_axis_event_handler.hpp create mode 100644 src/axisevent/rel_axis_event_handler.cpp create mode 100644 src/axisevent/rel_axis_event_handler.hpp create mode 100644 src/axisevent/rel_repeat_axis_event_handler.cpp create mode 100644 src/axisevent/rel_repeat_axis_event_handler.hpp diff --git a/SConstruct b/SConstruct index cebd3f1..08d9a34 100644 --- a/SConstruct +++ b/SConstruct @@ -149,7 +149,8 @@ libxboxdrv = env.StaticLibrary('xboxdrv', Glob('src/*.cpp') + Glob('src/axisfilter/*.cpp') + Glob('src/buttonfilter/*.cpp') + - Glob('src/buttonevent/*.cpp') + + Glob('src/axisevent/*.cpp') + + Glob('src/buttonevent/*.cpp') + Glob('src/modifier/*.cpp')) env.Append(LIBS = libxboxdrv) diff --git a/src/axis_event.cpp b/src/axis_event.cpp index 06726cc..35c4c37 100644 --- a/src/axis_event.cpp +++ b/src/axis_event.cpp @@ -26,6 +26,11 @@ #include "helper.hpp" #include "raise_exception.hpp" #include "uinput.hpp" + +#include "axisevent/abs_axis_event_handler.hpp" +#include "axisevent/key_axis_event_handler.hpp" +#include "axisevent/rel_axis_event_handler.hpp" +#include "axisevent/rel_repeat_axis_event_handler.hpp" AxisEventPtr AxisEvent::invalid() @@ -182,439 +187,4 @@ AxisEventHandler::set_axis_range(int min, int max) m_max = max; } -RelAxisEventHandler* -RelAxisEventHandler::from_string(const std::string& str) -{ - typedef boost::tokenizer > tokenizer; - tokenizer tokens(str, boost::char_separator(":", "", boost::keep_empty_tokens)); - - std::auto_ptr ev(new RelAxisEventHandler); - - int j = 0; - for(tokenizer::iterator i = tokens.begin(); i != tokens.end(); ++i, ++j) - { - switch(j) - { - case 0: - ev->m_code = str2rel_event(*i); - break; - - case 1: - ev->m_value = boost::lexical_cast(*i); - break; - - case 2: - ev->m_repeat = boost::lexical_cast(*i); - break; - - default: - throw std::runtime_error("AxisEvent::rel_from_string(): to many arguments: " + str); - } - } - - if (j == 0) - { - throw std::runtime_error("AxisEvent::rel_from_string(): at least one argument required: " + str); - } - - return ev.release(); -} - -RelAxisEventHandler::RelAxisEventHandler() : - m_code(UIEvent::invalid()), - m_value(5), - m_repeat(10), - m_stick_value(0.0f), - m_rest_value(0.0f) -{ -} - -RelAxisEventHandler::RelAxisEventHandler(int device_id, int code, int repeat, float value) : - m_code(UIEvent::create(device_id, EV_REL, code)), - m_value(value), - m_repeat(repeat), - m_stick_value(0.0f), - m_rest_value(0.0f) -{ -} - -void -RelAxisEventHandler::init(UInput& uinput, int slot, bool extra_devices) -{ - m_code.resolve_device_id(slot, extra_devices); - uinput.add_rel(m_code.get_device_id(), m_code.code); -} - -void -RelAxisEventHandler::send(UInput& uinput, int value) -{ - if (value < 0) - m_stick_value = value / static_cast(-m_min); - else - m_stick_value = value / static_cast(m_max); - - if (m_repeat != -1) - { - // regular old style sending of REL events - float v = m_value * m_stick_value; - - if (v == 0) - uinput.send_rel_repetitive(m_code, v, -1); - else - uinput.send_rel_repetitive(m_code, v, m_repeat); - } -} - -void -RelAxisEventHandler::update(UInput& uinput, int msec_delta) -{ - if (m_repeat == -1 && m_stick_value != 0.0f) - { - // new and improved REL style event sending - - float rel_value = m_stick_value * m_value * static_cast(msec_delta) / 1000.0f; - - // keep track of the rest that we lose when converting to integer - rel_value += m_rest_value; - m_rest_value = rel_value - truncf(rel_value); - - uinput.send_rel(m_code.get_device_id(), m_code.code, static_cast(rel_value)); - } -} - -std::string -RelAxisEventHandler::str() const -{ - std::ostringstream out; - out << m_code.get_device_id() << "-" << m_code.code << ":" << m_value << ":" << m_repeat; - return out.str(); -} - - -RelRepeatAxisEventHandler* -RelRepeatAxisEventHandler::from_string(const std::string& str) -{ - // split string at ':' - boost::tokenizer > - tokens(str, boost::char_separator(":", "", boost::keep_empty_tokens)); - std::vector args; - std::copy(tokens.begin(), tokens.end(), std::back_inserter(args)); - - if (args.size() == 3) - { - return new RelRepeatAxisEventHandler(str2rel_event(args[0]), - boost::lexical_cast(args[1]), - boost::lexical_cast(args[2])); - } - else - { - raise_exception(std::runtime_error, "must have three arguments"); - } -} - -RelRepeatAxisEventHandler::RelRepeatAxisEventHandler(const UIEvent& code, int value, int repeat) : - m_code(code), - m_value(value), - m_repeat(repeat), - m_stick_value(0), - m_timer(0) -{ -} - -void -RelRepeatAxisEventHandler::init(UInput& uinput, int slot, bool extra_devices) -{ - m_code.resolve_device_id(slot, extra_devices); - uinput.add_rel(m_code.get_device_id(), m_code.code); -} - -void -RelRepeatAxisEventHandler::send(UInput& uinput, int value) -{ - if (value < 0) - { - m_stick_value = value / static_cast(-m_min); - } - else - { - m_stick_value = value / static_cast(m_max); - } - - // reset timer when in center position - if (value == 0) - { - m_timer = 0; - } -} - -void -RelRepeatAxisEventHandler::update(UInput& uinput, int msec_delta) -{ - // time ticks slower depending on how fr the stick is moved - m_timer += msec_delta * fabsf(m_stick_value); - - while(m_timer > m_repeat) - { - if (m_stick_value < 0) - { - uinput.send_rel(m_code.get_device_id(), m_code.code, -m_value); - } - else - { - uinput.send_rel(m_code.get_device_id(), m_code.code, m_value); - } - - m_timer -= m_repeat; - } -} - -std::string -RelRepeatAxisEventHandler::str() const -{ - std::ostringstream out; - out << "rel-repeat:" << m_value << ":" << m_repeat; - return out.str(); -} - -AbsAxisEventHandler* -AbsAxisEventHandler::from_string(const std::string& str) -{ - typedef boost::tokenizer > tokenizer; - tokenizer tokens(str, boost::char_separator(":", "", boost::keep_empty_tokens)); - - int j = 0; - UIEvent code = UIEvent::invalid(); - for(tokenizer::iterator i = tokens.begin(); i != tokens.end(); ++i, ++j) - { - switch(j) - { - case 0: - code = str2abs_event(*i); - break; - - default: - throw std::runtime_error("AxisEventHandlers::abs_from_string(): to many arguments: " + str); - } - } - - if (j == 0) - { - throw std::runtime_error("AxisEventHandler::abs_from_string(): at least one argument required: " + str); - } - else if (j > 1) - { - throw std::runtime_error("AxisEventHandler::abs_from_string(): invalid extra arguments in " + str); - } - else - { - return new AbsAxisEventHandler(code, -1, -1, 0, 0); - } -} - -AbsAxisEventHandler::AbsAxisEventHandler() : - m_code(UIEvent::invalid()), - m_fuzz(0), - m_flat(0) -{ -} - -AbsAxisEventHandler::AbsAxisEventHandler(const UIEvent& code, int min, int max, int fuzz, int flat) : - m_code(code), - m_fuzz(fuzz), - m_flat(flat) -{ - set_axis_range(min, max); -} - -void -AbsAxisEventHandler::init(UInput& uinput, int slot, bool extra_devices) -{ - m_code.resolve_device_id(slot, extra_devices); - uinput.add_abs(m_code.get_device_id(), m_code.code, - m_min, m_max, m_fuzz, m_flat); -} - -void -AbsAxisEventHandler::send(UInput& uinput, int value) -{ - uinput.send_abs(m_code.get_device_id(), m_code.code, value); -} - -void -AbsAxisEventHandler::update(UInput& uinput, int msec_delta) -{ -} - -std::string -AbsAxisEventHandler::str() const -{ - std::ostringstream out; - out << m_code.get_device_id() << "-" << m_code.code << ":" - << m_min << ":" << m_max << ":" - << m_fuzz << ":" << m_flat; - return out.str(); -} - -KeyAxisEventHandler* -KeyAxisEventHandler::from_string(const std::string& str) -{ - typedef boost::tokenizer > tokenizer; - tokenizer tokens(str, boost::char_separator(":", "", boost::keep_empty_tokens)); - - std::auto_ptr ev(new KeyAxisEventHandler); - - int j = 0; - for(tokenizer::iterator i = tokens.begin(); i != tokens.end(); ++i, ++j) - { - switch(j) - { - case 0: - { - int k = 0; - tokenizer ev_tokens(*i, boost::char_separator("+", "", boost::keep_empty_tokens)); - for(tokenizer::iterator m = ev_tokens.begin(); m != ev_tokens.end(); ++m, ++k) - { - ev->m_up_codes[k] = str2key_event(*m); - } - } - break; - - case 1: - { - if (is_number(*i)) - { - // bit of hackery to handle simplified syntax for trigger button that don't need up/down events - ev->m_threshold = boost::lexical_cast(*i); - - for(int k = 0; ev->m_up_codes[k].is_valid(); ++k) - { - ev->m_down_codes[k] = ev->m_up_codes[k]; - ev->m_up_codes[k] = UIEvent::invalid(); - } - } - else - { - tokenizer ev_tokens(*i, boost::char_separator("+", "", boost::keep_empty_tokens)); - int k = 0; - for(tokenizer::iterator m = ev_tokens.begin(); m != ev_tokens.end(); ++m, ++k) - { - ev->m_down_codes[k] = str2key_event(*m); - } - } - } - break; - - case 2: - ev->m_threshold = boost::lexical_cast(*i); - break; - - default: - throw std::runtime_error("AxisEvent::key_from_string(): to many arguments: " + str); - } - } - - if (j == 0) - { - throw std::runtime_error("AxisEvent::key_from_string(): at least one argument required: " + str); - } - - return ev.release(); -} - -KeyAxisEventHandler::KeyAxisEventHandler() : - m_old_value(0), - m_up_codes(), - m_down_codes(), - m_threshold(8000) // FIXME: this doesn't work for triggers -{ - std::fill_n(m_up_codes, MAX_MODIFIER+1, UIEvent::invalid()); - std::fill_n(m_down_codes, MAX_MODIFIER+1, UIEvent::invalid()); -} - -void -KeyAxisEventHandler::init(UInput& uinput, int slot, bool extra_devices) -{ - for(int i = 0; m_up_codes[i].is_valid(); ++i) - { - m_up_codes[i].resolve_device_id(slot, extra_devices); - uinput.add_key(m_up_codes[i].get_device_id(), m_up_codes[i].code); - } - - for(int i = 0; m_down_codes[i].is_valid(); ++i) - { - m_down_codes[i].resolve_device_id(slot, extra_devices); - uinput.add_key(m_down_codes[i].get_device_id(), m_down_codes[i].code); - } -} - -void -KeyAxisEventHandler::send(UInput& uinput, int value) -{ - if (::abs(m_old_value) < m_threshold && - ::abs(value) >= m_threshold) - { // entering bigger then threshold zone - if (value < 0) - { - for(int i = 0; m_down_codes[i].is_valid(); ++i) - uinput.send_key(m_down_codes[i].get_device_id(), m_down_codes[i].code, false); - - for(int i = 0; m_up_codes[i].is_valid(); ++i) - uinput.send_key(m_up_codes[i].get_device_id(), m_up_codes[i].code, true); - } - else // (value > 0) - { - for(int i = 0; m_down_codes[i].is_valid(); ++i) - uinput.send_key(m_down_codes[i].get_device_id(), m_down_codes[i].code, true); - - for(int i = 0; m_up_codes[i].is_valid(); ++i) - uinput.send_key(m_up_codes[i].get_device_id(), m_up_codes[i].code, false); - } - } - else if (::abs(m_old_value) >= m_threshold && - ::abs(value) < m_threshold) - { // entering zero zone - for(int i = 0; m_down_codes[i].is_valid(); ++i) - uinput.send_key(m_down_codes[i].get_device_id(), m_down_codes[i].code, false); - - for(int i = 0; m_up_codes[i].is_valid(); ++i) - uinput.send_key(m_up_codes[i].get_device_id(), m_up_codes[i].code, false); - } - - m_old_value = value; -} - -void -KeyAxisEventHandler::update(UInput& uinput, int msec_delta) -{ -} - -std::string -KeyAxisEventHandler::str() const -{ - std::ostringstream out; - for(int i = 0; m_up_codes[i].is_valid();) - { - out << m_up_codes[i].get_device_id() << "-" << m_up_codes[i].code; - - ++i; - if (m_up_codes[i].is_valid()) - out << "+"; - } - - out << ":"; - - for(int i = 0; m_down_codes[i].is_valid();) - { - out << m_down_codes[i].get_device_id() << "-" << m_down_codes[i].code; - - ++i; - if (m_down_codes[i].is_valid()) - out << "+"; - } - - out << ":" << m_threshold; - - return out.str(); -} - /* EOF */ diff --git a/src/axis_event.hpp b/src/axis_event.hpp index dbc3104..a90c731 100644 --- a/src/axis_event.hpp +++ b/src/axis_event.hpp @@ -83,99 +83,6 @@ public: virtual std::string str() const =0; }; -class RelAxisEventHandler : public AxisEventHandler -{ -public: - static RelAxisEventHandler* from_string(const std::string& str); - -public: - RelAxisEventHandler(); - RelAxisEventHandler(int device_id, int code, int repeat = 10, float value = 5); - - void init(UInput& uinput, int slot, bool extra_devices); - void send(UInput& uinput, int value); - void update(UInput& uinput, int msec_delta); - - std::string str() const; - -private: - UIEvent m_code; - float m_value; - int m_repeat; - - float m_stick_value; - float m_rest_value; -}; - -class RelRepeatAxisEventHandler : public AxisEventHandler -{ -public: - static RelRepeatAxisEventHandler* from_string(const std::string& str); - -public: - RelRepeatAxisEventHandler(const UIEvent& code, int value, int repeat); - - void init(UInput& uinput, int slot, bool extra_devices); - void send(UInput& uinput, int value); - void update(UInput& uinput, int msec_delta); - - std::string str() const; - -private: - UIEvent m_code; - int m_value; - float m_repeat; - - float m_stick_value; - int m_timer; -}; - -class AbsAxisEventHandler : public AxisEventHandler -{ -public: - static AbsAxisEventHandler* from_string(const std::string& str); - -public: - AbsAxisEventHandler(); - AbsAxisEventHandler(const UIEvent& code, int min, int max, int fuzz, int flat); - - void init(UInput& uinput, int slot, bool extra_devices); - void send(UInput& uinput, int value); - void update(UInput& uinput, int msec_delta); - - std::string str() const; - -private: - UIEvent m_code; - int m_fuzz; - int m_flat; -}; - -class KeyAxisEventHandler : public AxisEventHandler -{ -public: - static KeyAxisEventHandler* from_string(const std::string& str); - -public: - KeyAxisEventHandler(); - - void init(UInput& uinput, int slot, bool extra_devices); - void send(UInput& uinput, int value); - void update(UInput& uinput, int msec_delta); - - std::string str() const; - -private: - static const int MAX_MODIFIER = 4; - - int m_old_value; - - // Array is terminated by -1 - UIEvent m_up_codes[MAX_MODIFIER+1]; - UIEvent m_down_codes[MAX_MODIFIER+1]; - int m_threshold; -}; - #endif /* EOF */ diff --git a/src/axisevent/abs_axis_event_handler.cpp b/src/axisevent/abs_axis_event_handler.cpp new file mode 100644 index 0000000..f3c64f9 --- /dev/null +++ b/src/axisevent/abs_axis_event_handler.cpp @@ -0,0 +1,105 @@ +/* +** Xbox360 USB Gamepad Userspace Driver +** Copyright (C) 2011 Ingo Ruhnke +** +** 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 "abs_axis_event_handler.hpp" + +#include + +#include "evdev_helper.hpp" +#include "uinput.hpp" + +AbsAxisEventHandler* +AbsAxisEventHandler::from_string(const std::string& str) +{ + typedef boost::tokenizer > tokenizer; + tokenizer tokens(str, boost::char_separator(":", "", boost::keep_empty_tokens)); + + int j = 0; + UIEvent code = UIEvent::invalid(); + for(tokenizer::iterator i = tokens.begin(); i != tokens.end(); ++i, ++j) + { + switch(j) + { + case 0: + code = str2abs_event(*i); + break; + + default: + throw std::runtime_error("AxisEventHandlers::abs_from_string(): to many arguments: " + str); + } + } + + if (j == 0) + { + throw std::runtime_error("AxisEventHandler::abs_from_string(): at least one argument required: " + str); + } + else if (j > 1) + { + throw std::runtime_error("AxisEventHandler::abs_from_string(): invalid extra arguments in " + str); + } + else + { + return new AbsAxisEventHandler(code, -1, -1, 0, 0); + } +} + +AbsAxisEventHandler::AbsAxisEventHandler() : + m_code(UIEvent::invalid()), + m_fuzz(0), + m_flat(0) +{ +} + +AbsAxisEventHandler::AbsAxisEventHandler(const UIEvent& code, int min, int max, int fuzz, int flat) : + m_code(code), + m_fuzz(fuzz), + m_flat(flat) +{ + set_axis_range(min, max); +} + +void +AbsAxisEventHandler::init(UInput& uinput, int slot, bool extra_devices) +{ + m_code.resolve_device_id(slot, extra_devices); + uinput.add_abs(m_code.get_device_id(), m_code.code, + m_min, m_max, m_fuzz, m_flat); +} + +void +AbsAxisEventHandler::send(UInput& uinput, int value) +{ + uinput.send_abs(m_code.get_device_id(), m_code.code, value); +} + +void +AbsAxisEventHandler::update(UInput& uinput, int msec_delta) +{ +} + +std::string +AbsAxisEventHandler::str() const +{ + std::ostringstream out; + out << m_code.get_device_id() << "-" << m_code.code << ":" + << m_min << ":" << m_max << ":" + << m_fuzz << ":" << m_flat; + return out.str(); +} + +/* EOF */ diff --git a/src/axisevent/abs_axis_event_handler.hpp b/src/axisevent/abs_axis_event_handler.hpp new file mode 100644 index 0000000..00b1963 --- /dev/null +++ b/src/axisevent/abs_axis_event_handler.hpp @@ -0,0 +1,47 @@ +/* +** Xbox360 USB Gamepad Userspace Driver +** Copyright (C) 2011 Ingo Ruhnke +** +** 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 HEADER_XBOXDRV_AXISEVENT_ABS_AXIS_EVENT_HANDLER_HPP +#define HEADER_XBOXDRV_AXISEVENT_ABS_AXIS_EVENT_HANDLER_HPP + +#include "axis_event.hpp" + +class AbsAxisEventHandler : public AxisEventHandler +{ +public: + static AbsAxisEventHandler* from_string(const std::string& str); + +public: + AbsAxisEventHandler(); + AbsAxisEventHandler(const UIEvent& code, int min, int max, int fuzz, int flat); + + void init(UInput& uinput, int slot, bool extra_devices); + void send(UInput& uinput, int value); + void update(UInput& uinput, int msec_delta); + + std::string str() const; + +private: + UIEvent m_code; + int m_fuzz; + int m_flat; +}; + +#endif + +/* EOF */ diff --git a/src/axisevent/key_axis_event_handler.cpp b/src/axisevent/key_axis_event_handler.cpp new file mode 100644 index 0000000..d6208c2 --- /dev/null +++ b/src/axisevent/key_axis_event_handler.cpp @@ -0,0 +1,189 @@ +/* +** Xbox360 USB Gamepad Userspace Driver +** Copyright (C) 2011 Ingo Ruhnke +** +** 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 "key_axis_event_handler.hpp" + +#include + +#include "evdev_helper.hpp" +#include "helper.hpp" +#include "uinput.hpp" + +KeyAxisEventHandler* +KeyAxisEventHandler::from_string(const std::string& str) +{ + typedef boost::tokenizer > tokenizer; + tokenizer tokens(str, boost::char_separator(":", "", boost::keep_empty_tokens)); + + std::auto_ptr ev(new KeyAxisEventHandler); + + int j = 0; + for(tokenizer::iterator i = tokens.begin(); i != tokens.end(); ++i, ++j) + { + switch(j) + { + case 0: + { + int k = 0; + tokenizer ev_tokens(*i, boost::char_separator("+", "", boost::keep_empty_tokens)); + for(tokenizer::iterator m = ev_tokens.begin(); m != ev_tokens.end(); ++m, ++k) + { + ev->m_up_codes[k] = str2key_event(*m); + } + } + break; + + case 1: + { + if (is_number(*i)) + { + // bit of hackery to handle simplified syntax for trigger button that don't need up/down events + ev->m_threshold = boost::lexical_cast(*i); + + for(int k = 0; ev->m_up_codes[k].is_valid(); ++k) + { + ev->m_down_codes[k] = ev->m_up_codes[k]; + ev->m_up_codes[k] = UIEvent::invalid(); + } + } + else + { + tokenizer ev_tokens(*i, boost::char_separator("+", "", boost::keep_empty_tokens)); + int k = 0; + for(tokenizer::iterator m = ev_tokens.begin(); m != ev_tokens.end(); ++m, ++k) + { + ev->m_down_codes[k] = str2key_event(*m); + } + } + } + break; + + case 2: + ev->m_threshold = boost::lexical_cast(*i); + break; + + default: + throw std::runtime_error("AxisEvent::key_from_string(): to many arguments: " + str); + } + } + + if (j == 0) + { + throw std::runtime_error("AxisEvent::key_from_string(): at least one argument required: " + str); + } + + return ev.release(); +} + +KeyAxisEventHandler::KeyAxisEventHandler() : + m_old_value(0), + m_up_codes(), + m_down_codes(), + m_threshold(8000) // FIXME: this doesn't work for triggers +{ + std::fill_n(m_up_codes, MAX_MODIFIER+1, UIEvent::invalid()); + std::fill_n(m_down_codes, MAX_MODIFIER+1, UIEvent::invalid()); +} + +void +KeyAxisEventHandler::init(UInput& uinput, int slot, bool extra_devices) +{ + for(int i = 0; m_up_codes[i].is_valid(); ++i) + { + m_up_codes[i].resolve_device_id(slot, extra_devices); + uinput.add_key(m_up_codes[i].get_device_id(), m_up_codes[i].code); + } + + for(int i = 0; m_down_codes[i].is_valid(); ++i) + { + m_down_codes[i].resolve_device_id(slot, extra_devices); + uinput.add_key(m_down_codes[i].get_device_id(), m_down_codes[i].code); + } +} + +void +KeyAxisEventHandler::send(UInput& uinput, int value) +{ + if (::abs(m_old_value) < m_threshold && + ::abs(value) >= m_threshold) + { // entering bigger then threshold zone + if (value < 0) + { + for(int i = 0; m_down_codes[i].is_valid(); ++i) + uinput.send_key(m_down_codes[i].get_device_id(), m_down_codes[i].code, false); + + for(int i = 0; m_up_codes[i].is_valid(); ++i) + uinput.send_key(m_up_codes[i].get_device_id(), m_up_codes[i].code, true); + } + else // (value > 0) + { + for(int i = 0; m_down_codes[i].is_valid(); ++i) + uinput.send_key(m_down_codes[i].get_device_id(), m_down_codes[i].code, true); + + for(int i = 0; m_up_codes[i].is_valid(); ++i) + uinput.send_key(m_up_codes[i].get_device_id(), m_up_codes[i].code, false); + } + } + else if (::abs(m_old_value) >= m_threshold && + ::abs(value) < m_threshold) + { // entering zero zone + for(int i = 0; m_down_codes[i].is_valid(); ++i) + uinput.send_key(m_down_codes[i].get_device_id(), m_down_codes[i].code, false); + + for(int i = 0; m_up_codes[i].is_valid(); ++i) + uinput.send_key(m_up_codes[i].get_device_id(), m_up_codes[i].code, false); + } + + m_old_value = value; +} + +void +KeyAxisEventHandler::update(UInput& uinput, int msec_delta) +{ +} + +std::string +KeyAxisEventHandler::str() const +{ + std::ostringstream out; + for(int i = 0; m_up_codes[i].is_valid();) + { + out << m_up_codes[i].get_device_id() << "-" << m_up_codes[i].code; + + ++i; + if (m_up_codes[i].is_valid()) + out << "+"; + } + + out << ":"; + + for(int i = 0; m_down_codes[i].is_valid();) + { + out << m_down_codes[i].get_device_id() << "-" << m_down_codes[i].code; + + ++i; + if (m_down_codes[i].is_valid()) + out << "+"; + } + + out << ":" << m_threshold; + + return out.str(); +} + +/* EOF */ diff --git a/src/axisevent/key_axis_event_handler.hpp b/src/axisevent/key_axis_event_handler.hpp new file mode 100644 index 0000000..dfa022e --- /dev/null +++ b/src/axisevent/key_axis_event_handler.hpp @@ -0,0 +1,51 @@ +/* +** Xbox360 USB Gamepad Userspace Driver +** Copyright (C) 2011 Ingo Ruhnke +** +** 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 HEADER_XBOXDRV_AXISEVENT_KEY_AXIS_EVENT_HANDLER_HPP +#define HEADER_XBOXDRV_AXISEVENT_KEY_AXIS_EVENT_HANDLER_HPP + +#include "axis_event.hpp" + +class KeyAxisEventHandler : public AxisEventHandler +{ +public: + static KeyAxisEventHandler* from_string(const std::string& str); + +public: + KeyAxisEventHandler(); + + void init(UInput& uinput, int slot, bool extra_devices); + void send(UInput& uinput, int value); + void update(UInput& uinput, int msec_delta); + + std::string str() const; + +private: + static const int MAX_MODIFIER = 4; + + int m_old_value; + + // Array is terminated by -1 + UIEvent m_up_codes[MAX_MODIFIER+1]; + UIEvent m_down_codes[MAX_MODIFIER+1]; + int m_threshold; +}; + +#endif + +/* EOF */ diff --git a/src/axisevent/rel_axis_event_handler.cpp b/src/axisevent/rel_axis_event_handler.cpp new file mode 100644 index 0000000..55e4b5c --- /dev/null +++ b/src/axisevent/rel_axis_event_handler.cpp @@ -0,0 +1,135 @@ +/* +** Xbox360 USB Gamepad Userspace Driver +** Copyright (C) 2011 Ingo Ruhnke +** +** 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 "axisevent/rel_axis_event_handler.hpp" + +#include +#include + +#include "evdev_helper.hpp" +#include "uinput.hpp" + +RelAxisEventHandler* +RelAxisEventHandler::from_string(const std::string& str) +{ + typedef boost::tokenizer > tokenizer; + tokenizer tokens(str, boost::char_separator(":", "", boost::keep_empty_tokens)); + + std::auto_ptr ev(new RelAxisEventHandler); + + int j = 0; + for(tokenizer::iterator i = tokens.begin(); i != tokens.end(); ++i, ++j) + { + switch(j) + { + case 0: + ev->m_code = str2rel_event(*i); + break; + + case 1: + ev->m_value = boost::lexical_cast(*i); + break; + + case 2: + ev->m_repeat = boost::lexical_cast(*i); + break; + + default: + throw std::runtime_error("AxisEvent::rel_from_string(): to many arguments: " + str); + } + } + + if (j == 0) + { + throw std::runtime_error("AxisEvent::rel_from_string(): at least one argument required: " + str); + } + + return ev.release(); +} + +RelAxisEventHandler::RelAxisEventHandler() : + m_code(UIEvent::invalid()), + m_value(5), + m_repeat(10), + m_stick_value(0.0f), + m_rest_value(0.0f) +{ +} + +RelAxisEventHandler::RelAxisEventHandler(int device_id, int code, int repeat, float value) : + m_code(UIEvent::create(device_id, EV_REL, code)), + m_value(value), + m_repeat(repeat), + m_stick_value(0.0f), + m_rest_value(0.0f) +{ +} + +void +RelAxisEventHandler::init(UInput& uinput, int slot, bool extra_devices) +{ + m_code.resolve_device_id(slot, extra_devices); + uinput.add_rel(m_code.get_device_id(), m_code.code); +} + +void +RelAxisEventHandler::send(UInput& uinput, int value) +{ + if (value < 0) + m_stick_value = value / static_cast(-m_min); + else + m_stick_value = value / static_cast(m_max); + + if (m_repeat != -1) + { + // regular old style sending of REL events + float v = m_value * m_stick_value; + + if (v == 0) + uinput.send_rel_repetitive(m_code, v, -1); + else + uinput.send_rel_repetitive(m_code, v, m_repeat); + } +} + +void +RelAxisEventHandler::update(UInput& uinput, int msec_delta) +{ + if (m_repeat == -1 && m_stick_value != 0.0f) + { + // new and improved REL style event sending + + float rel_value = m_stick_value * m_value * static_cast(msec_delta) / 1000.0f; + + // keep track of the rest that we lose when converting to integer + rel_value += m_rest_value; + m_rest_value = rel_value - truncf(rel_value); + + uinput.send_rel(m_code.get_device_id(), m_code.code, static_cast(rel_value)); + } +} + +std::string +RelAxisEventHandler::str() const +{ + std::ostringstream out; + out << m_code.get_device_id() << "-" << m_code.code << ":" << m_value << ":" << m_repeat; + return out.str(); +} + +/* EOF */ diff --git a/src/axisevent/rel_axis_event_handler.hpp b/src/axisevent/rel_axis_event_handler.hpp new file mode 100644 index 0000000..287b635 --- /dev/null +++ b/src/axisevent/rel_axis_event_handler.hpp @@ -0,0 +1,50 @@ +/* +** Xbox360 USB Gamepad Userspace Driver +** Copyright (C) 2011 Ingo Ruhnke +** +** 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 HEADER_XBOXDRV_AXISEVENT_REL_AXIS_EVENT_HANDLER_HPP +#define HEADER_XBOXDRV_AXISEVENT_REL_AXIS_EVENT_HANDLER_HPP + +#include "axis_event.hpp" + +class RelAxisEventHandler : public AxisEventHandler +{ +public: + static RelAxisEventHandler* from_string(const std::string& str); + +public: + RelAxisEventHandler(); + RelAxisEventHandler(int device_id, int code, int repeat = 10, float value = 5); + + void init(UInput& uinput, int slot, bool extra_devices); + void send(UInput& uinput, int value); + void update(UInput& uinput, int msec_delta); + + std::string str() const; + +private: + UIEvent m_code; + float m_value; + int m_repeat; + + float m_stick_value; + float m_rest_value; +}; + +#endif + +/* EOF */ diff --git a/src/axisevent/rel_repeat_axis_event_handler.cpp b/src/axisevent/rel_repeat_axis_event_handler.cpp new file mode 100644 index 0000000..3362829 --- /dev/null +++ b/src/axisevent/rel_repeat_axis_event_handler.cpp @@ -0,0 +1,113 @@ +/* +** Xbox360 USB Gamepad Userspace Driver +** Copyright (C) 2011 Ingo Ruhnke +** +** 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 "axisevent/rel_repeat_axis_event_handler.hpp" + +#include +#include + +#include "evdev_helper.hpp" +#include "raise_exception.hpp" +#include "uinput.hpp" + +RelRepeatAxisEventHandler* +RelRepeatAxisEventHandler::from_string(const std::string& str) +{ + // split string at ':' + boost::tokenizer > + tokens(str, boost::char_separator(":", "", boost::keep_empty_tokens)); + std::vector args; + std::copy(tokens.begin(), tokens.end(), std::back_inserter(args)); + + if (args.size() == 3) + { + return new RelRepeatAxisEventHandler(str2rel_event(args[0]), + boost::lexical_cast(args[1]), + boost::lexical_cast(args[2])); + } + else + { + raise_exception(std::runtime_error, "must have three arguments"); + } +} + +RelRepeatAxisEventHandler::RelRepeatAxisEventHandler(const UIEvent& code, int value, int repeat) : + m_code(code), + m_value(value), + m_repeat(repeat), + m_stick_value(0), + m_timer(0) +{ +} + +void +RelRepeatAxisEventHandler::init(UInput& uinput, int slot, bool extra_devices) +{ + m_code.resolve_device_id(slot, extra_devices); + uinput.add_rel(m_code.get_device_id(), m_code.code); +} + +void +RelRepeatAxisEventHandler::send(UInput& uinput, int value) +{ + if (value < 0) + { + m_stick_value = value / static_cast(-m_min); + } + else + { + m_stick_value = value / static_cast(m_max); + } + + // reset timer when in center position + if (value == 0) + { + m_timer = 0; + } +} + +void +RelRepeatAxisEventHandler::update(UInput& uinput, int msec_delta) +{ + // time ticks slower depending on how fr the stick is moved + m_timer += msec_delta * fabsf(m_stick_value); + + while(m_timer > m_repeat) + { + if (m_stick_value < 0) + { + uinput.send_rel(m_code.get_device_id(), m_code.code, -m_value); + } + else + { + uinput.send_rel(m_code.get_device_id(), m_code.code, m_value); + } + + m_timer -= m_repeat; + } +} + +std::string +RelRepeatAxisEventHandler::str() const +{ + std::ostringstream out; + out << "rel-repeat:" << m_value << ":" << m_repeat; + return out.str(); +} + +/* EOF */ diff --git a/src/axisevent/rel_repeat_axis_event_handler.hpp b/src/axisevent/rel_repeat_axis_event_handler.hpp new file mode 100644 index 0000000..28e614f --- /dev/null +++ b/src/axisevent/rel_repeat_axis_event_handler.hpp @@ -0,0 +1,49 @@ +/* +** Xbox360 USB Gamepad Userspace Driver +** Copyright (C) 2011 Ingo Ruhnke +** +** 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 HEADER_XBOXDRV_AXISEVENT_REL_REPEAT_AXIS_EVENT_HANDLER_HPP +#define HEADER_XBOXDRV_AXISEVENT_REL_REPEAT_AXIS_EVENT_HANDLER_HPP + +#include "axis_event.hpp" + +class RelRepeatAxisEventHandler : public AxisEventHandler +{ +public: + static RelRepeatAxisEventHandler* from_string(const std::string& str); + +public: + RelRepeatAxisEventHandler(const UIEvent& code, int value, int repeat); + + void init(UInput& uinput, int slot, bool extra_devices); + void send(UInput& uinput, int value); + void update(UInput& uinput, int msec_delta); + + std::string str() const; + +private: + UIEvent m_code; + int m_value; + float m_repeat; + + float m_stick_value; + int m_timer; +}; + +#endif + +/* EOF */ diff --git a/src/ui_event.cpp b/src/ui_event.cpp index 4d255a7..ffd7fe6 100644 --- a/src/ui_event.cpp +++ b/src/ui_event.cpp @@ -18,6 +18,7 @@ #include "ui_event.hpp" +#include "evdev_helper.hpp" #include "uinput.hpp" bool @@ -44,6 +45,18 @@ UIEvent::create(int device_id, int type, int code) return ev; } +UIEvent +UIEvent::from_string(const std::string& str) +{ + switch(get_event_type(str)) + { + case EV_REL: return str2rel_event(str); break; + case EV_ABS: return str2abs_event(str); break; + case EV_KEY: return str2key_event(str); break; + default: throw std::runtime_error("unknown event type"); + } +} + UIEvent UIEvent::invalid() { diff --git a/src/ui_event.hpp b/src/ui_event.hpp index 1cd5ab0..7f0e662 100644 --- a/src/ui_event.hpp +++ b/src/ui_event.hpp @@ -39,6 +39,7 @@ class UIEvent { public: static UIEvent create(int device_id, int type, int code); + static UIEvent from_string(const std::string& str); static UIEvent invalid(); public: