Split AxisEvent into separate files
This commit is contained in:
parent
590574e832
commit
69e24b891c
13 changed files with 760 additions and 529 deletions
|
@ -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)
|
||||
|
||||
|
|
|
@ -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<boost::char_separator<char> > tokenizer;
|
||||
tokenizer tokens(str, boost::char_separator<char>(":", "", boost::keep_empty_tokens));
|
||||
|
||||
std::auto_ptr<RelAxisEventHandler> 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<float>(*i);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ev->m_repeat = boost::lexical_cast<int>(*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<float>(-m_min);
|
||||
else
|
||||
m_stick_value = value / static_cast<float>(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<float>(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<int>(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<boost::char_separator<char> >
|
||||
tokens(str, boost::char_separator<char>(":", "", boost::keep_empty_tokens));
|
||||
std::vector<std::string> 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<int>(args[1]),
|
||||
boost::lexical_cast<float>(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<float>(-m_min);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_stick_value = value / static_cast<float>(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<boost::char_separator<char> > tokenizer;
|
||||
tokenizer tokens(str, boost::char_separator<char>(":", "", 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<boost::char_separator<char> > tokenizer;
|
||||
tokenizer tokens(str, boost::char_separator<char>(":", "", boost::keep_empty_tokens));
|
||||
|
||||
std::auto_ptr<KeyAxisEventHandler> 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<char>("+", "", 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<int>(*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<char>("+", "", 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<int>(*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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
105
src/axisevent/abs_axis_event_handler.cpp
Normal file
105
src/axisevent/abs_axis_event_handler.cpp
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
** Xbox360 USB Gamepad Userspace Driver
|
||||
** Copyright (C) 2011 Ingo Ruhnke <grumbel@gmx.de>
|
||||
**
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "abs_axis_event_handler.hpp"
|
||||
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
||||
#include "evdev_helper.hpp"
|
||||
#include "uinput.hpp"
|
||||
|
||||
AbsAxisEventHandler*
|
||||
AbsAxisEventHandler::from_string(const std::string& str)
|
||||
{
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
tokenizer tokens(str, boost::char_separator<char>(":", "", 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 */
|
47
src/axisevent/abs_axis_event_handler.hpp
Normal file
47
src/axisevent/abs_axis_event_handler.hpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
** Xbox360 USB Gamepad Userspace Driver
|
||||
** Copyright (C) 2011 Ingo Ruhnke <grumbel@gmx.de>
|
||||
**
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 */
|
189
src/axisevent/key_axis_event_handler.cpp
Normal file
189
src/axisevent/key_axis_event_handler.cpp
Normal file
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
** Xbox360 USB Gamepad Userspace Driver
|
||||
** Copyright (C) 2011 Ingo Ruhnke <grumbel@gmx.de>
|
||||
**
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "key_axis_event_handler.hpp"
|
||||
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
||||
#include "evdev_helper.hpp"
|
||||
#include "helper.hpp"
|
||||
#include "uinput.hpp"
|
||||
|
||||
KeyAxisEventHandler*
|
||||
KeyAxisEventHandler::from_string(const std::string& str)
|
||||
{
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
tokenizer tokens(str, boost::char_separator<char>(":", "", boost::keep_empty_tokens));
|
||||
|
||||
std::auto_ptr<KeyAxisEventHandler> 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<char>("+", "", 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<int>(*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<char>("+", "", 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<int>(*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 */
|
51
src/axisevent/key_axis_event_handler.hpp
Normal file
51
src/axisevent/key_axis_event_handler.hpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
** Xbox360 USB Gamepad Userspace Driver
|
||||
** Copyright (C) 2011 Ingo Ruhnke <grumbel@gmx.de>
|
||||
**
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 */
|
135
src/axisevent/rel_axis_event_handler.cpp
Normal file
135
src/axisevent/rel_axis_event_handler.cpp
Normal file
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
** Xbox360 USB Gamepad Userspace Driver
|
||||
** Copyright (C) 2011 Ingo Ruhnke <grumbel@gmx.de>
|
||||
**
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "axisevent/rel_axis_event_handler.hpp"
|
||||
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <math.h>
|
||||
|
||||
#include "evdev_helper.hpp"
|
||||
#include "uinput.hpp"
|
||||
|
||||
RelAxisEventHandler*
|
||||
RelAxisEventHandler::from_string(const std::string& str)
|
||||
{
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
tokenizer tokens(str, boost::char_separator<char>(":", "", boost::keep_empty_tokens));
|
||||
|
||||
std::auto_ptr<RelAxisEventHandler> 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<float>(*i);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ev->m_repeat = boost::lexical_cast<int>(*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<float>(-m_min);
|
||||
else
|
||||
m_stick_value = value / static_cast<float>(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<float>(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<int>(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 */
|
50
src/axisevent/rel_axis_event_handler.hpp
Normal file
50
src/axisevent/rel_axis_event_handler.hpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
** Xbox360 USB Gamepad Userspace Driver
|
||||
** Copyright (C) 2011 Ingo Ruhnke <grumbel@gmx.de>
|
||||
**
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 */
|
113
src/axisevent/rel_repeat_axis_event_handler.cpp
Normal file
113
src/axisevent/rel_repeat_axis_event_handler.cpp
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
** Xbox360 USB Gamepad Userspace Driver
|
||||
** Copyright (C) 2011 Ingo Ruhnke <grumbel@gmx.de>
|
||||
**
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "axisevent/rel_repeat_axis_event_handler.hpp"
|
||||
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <math.h>
|
||||
|
||||
#include "evdev_helper.hpp"
|
||||
#include "raise_exception.hpp"
|
||||
#include "uinput.hpp"
|
||||
|
||||
RelRepeatAxisEventHandler*
|
||||
RelRepeatAxisEventHandler::from_string(const std::string& str)
|
||||
{
|
||||
// split string at ':'
|
||||
boost::tokenizer<boost::char_separator<char> >
|
||||
tokens(str, boost::char_separator<char>(":", "", boost::keep_empty_tokens));
|
||||
std::vector<std::string> 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<int>(args[1]),
|
||||
boost::lexical_cast<float>(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<float>(-m_min);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_stick_value = value / static_cast<float>(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 */
|
49
src/axisevent/rel_repeat_axis_event_handler.hpp
Normal file
49
src/axisevent/rel_repeat_axis_event_handler.hpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
** Xbox360 USB Gamepad Userspace Driver
|
||||
** Copyright (C) 2011 Ingo Ruhnke <grumbel@gmx.de>
|
||||
**
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 */
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue