Split AxisEvent into separate files

This commit is contained in:
Ingo Ruhnke 2011-04-12 12:16:21 +02:00
parent 590574e832
commit 69e24b891c
13 changed files with 760 additions and 529 deletions

View file

@ -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)

View file

@ -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 */

View file

@ -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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View file

@ -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()
{

View file

@ -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: