Split ButtonEvent classes into separate files
This commit is contained in:
parent
1de36a5664
commit
0fe69b98a9
13 changed files with 956 additions and 682 deletions
|
@ -149,6 +149,7 @@ libxboxdrv = env.StaticLibrary('xboxdrv',
|
|||
Glob('src/*.cpp') +
|
||||
Glob('src/axisfilter/*.cpp') +
|
||||
Glob('src/buttonfilter/*.cpp') +
|
||||
Glob('src/buttonevent/*.cpp') +
|
||||
Glob('src/modifier/*.cpp'))
|
||||
env.Append(LIBS = libxboxdrv)
|
||||
|
||||
|
|
|
@ -25,6 +25,12 @@
|
|||
#include "evdev_helper.hpp"
|
||||
#include "log.hpp"
|
||||
#include "uinput.hpp"
|
||||
|
||||
#include "buttonevent/abs_button_event_handler.hpp"
|
||||
#include "buttonevent/exec_button_event_handler.hpp"
|
||||
#include "buttonevent/key_button_event_handler.hpp"
|
||||
#include "buttonevent/macro_button_event_handler.hpp"
|
||||
#include "buttonevent/rel_button_event_handler.hpp"
|
||||
|
||||
ButtonEventPtr
|
||||
ButtonEvent::invalid()
|
||||
|
@ -180,560 +186,4 @@ ButtonEvent::str() const
|
|||
return m_handler->str();
|
||||
}
|
||||
|
||||
KeyButtonEventHandler*
|
||||
KeyButtonEventHandler::from_string(const std::string& str)
|
||||
{
|
||||
//std::cout << " KeyButtonEventHandler::from_string: " << str << std::endl;
|
||||
|
||||
std::auto_ptr<KeyButtonEventHandler> ev;
|
||||
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
tokenizer tokens(str, boost::char_separator<char>(":", "", boost::keep_empty_tokens));
|
||||
int idx = 0;
|
||||
for(tokenizer::iterator i = tokens.begin(); i != tokens.end(); ++i, ++idx)
|
||||
{
|
||||
switch(idx)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
ev.reset(new KeyButtonEventHandler());
|
||||
|
||||
boost::char_separator<char> plus_sep("+", "", boost::keep_empty_tokens);
|
||||
tokenizer ev_tokens(*i, plus_sep);
|
||||
int k = 0;
|
||||
for(tokenizer::iterator m = ev_tokens.begin(); m != ev_tokens.end() && k < MAX_MODIFIER; ++m, ++k)
|
||||
{
|
||||
ev->m_codes[k] = str2key_event(*m);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
{
|
||||
boost::char_separator<char> plus_sep("+", "", boost::keep_empty_tokens);
|
||||
tokenizer ev_tokens(*i, plus_sep);
|
||||
int k = 0;
|
||||
for(tokenizer::iterator m = ev_tokens.begin(); m != ev_tokens.end() && k < MAX_MODIFIER; ++m, ++k)
|
||||
{
|
||||
ev->m_secondary_codes[k] = str2key_event(*m);
|
||||
}
|
||||
|
||||
ev->m_hold_threshold = 250;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
ev->m_hold_threshold = boost::lexical_cast<int>(*i);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "to many arguments in '" << str << "'";
|
||||
throw std::runtime_error(out.str());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ev.release();
|
||||
}
|
||||
|
||||
KeyButtonEventHandler::KeyButtonEventHandler() :
|
||||
m_state(false),
|
||||
m_codes(),
|
||||
m_secondary_codes(),
|
||||
m_hold_threshold(0),
|
||||
m_hold_counter(0)
|
||||
{
|
||||
std::fill_n(m_codes, MAX_MODIFIER + 1, UIEvent::invalid());
|
||||
std::fill_n(m_secondary_codes, MAX_MODIFIER + 1, UIEvent::invalid());
|
||||
}
|
||||
|
||||
KeyButtonEventHandler::KeyButtonEventHandler(int device_id, int code) :
|
||||
m_state(false),
|
||||
m_codes(),
|
||||
m_secondary_codes(),
|
||||
m_hold_threshold(0),
|
||||
m_hold_counter(0)
|
||||
{
|
||||
std::fill_n(m_codes, MAX_MODIFIER + 1, UIEvent::invalid());
|
||||
std::fill_n(m_secondary_codes, MAX_MODIFIER + 1, UIEvent::invalid());
|
||||
m_codes[0] = UIEvent::create(device_id, EV_KEY, code);
|
||||
}
|
||||
|
||||
void
|
||||
KeyButtonEventHandler::init(UInput& uinput, int slot, bool extra_devices)
|
||||
{
|
||||
for(int i = 0; m_codes[i].is_valid(); ++i)
|
||||
{
|
||||
m_codes[i].resolve_device_id(slot, extra_devices);
|
||||
uinput.add_key(m_codes[i].get_device_id(), m_codes[i].code);
|
||||
}
|
||||
|
||||
if (m_hold_threshold)
|
||||
{
|
||||
for(int i = 0; m_secondary_codes[i].is_valid(); ++i)
|
||||
{
|
||||
m_secondary_codes[i].resolve_device_id(slot, extra_devices);
|
||||
uinput.add_key(m_secondary_codes[i].get_device_id(), m_secondary_codes[i].code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
KeyButtonEventHandler::send(UInput& uinput, bool value)
|
||||
{
|
||||
if (m_state != value)
|
||||
{
|
||||
m_state = value;
|
||||
|
||||
if (m_hold_threshold == 0)
|
||||
{
|
||||
// FIXME: should handle key releases in reverse order
|
||||
for(int i = 0; m_codes[i].is_valid(); ++i)
|
||||
{
|
||||
uinput.send_key(m_codes[i].get_device_id(), m_codes[i].code, m_state);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_hold_counter < m_hold_threshold)
|
||||
{
|
||||
if (m_state)
|
||||
{
|
||||
// we are only sending events after release or when
|
||||
// hold_threshold is passed
|
||||
}
|
||||
else
|
||||
{
|
||||
// send both a press and release event after another, aka a "click"
|
||||
for(int i = 0; m_codes[i].is_valid(); ++i)
|
||||
{
|
||||
uinput.send_key(m_codes[i].get_device_id(), m_codes[i].code, true);
|
||||
}
|
||||
// FIXME: should do this in reverse order
|
||||
for(int i = 0; m_codes[i].is_valid(); ++i)
|
||||
{
|
||||
uinput.send_key(m_codes[i].get_device_id(), m_codes[i].code, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_state)
|
||||
{
|
||||
// should never happen
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: should do in reverse
|
||||
for(int i = 0; m_secondary_codes[i].is_valid(); ++i)
|
||||
{
|
||||
uinput.send_key(m_secondary_codes[i].get_device_id(), m_secondary_codes[i].code, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_state)
|
||||
{
|
||||
m_hold_counter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
KeyButtonEventHandler::update(UInput& uinput, int msec_delta)
|
||||
{
|
||||
if (m_state && m_hold_threshold)
|
||||
{
|
||||
if (m_hold_counter < m_hold_threshold &&
|
||||
m_hold_counter + msec_delta >= m_hold_threshold)
|
||||
{
|
||||
// start sending the secondary events
|
||||
for(int i = 0; m_secondary_codes[i].is_valid(); ++i)
|
||||
{
|
||||
uinput.send_key(m_secondary_codes[i].get_device_id(), m_secondary_codes[i].code, true);
|
||||
}
|
||||
uinput.sync();
|
||||
}
|
||||
|
||||
if (m_hold_counter < m_hold_threshold)
|
||||
{
|
||||
m_hold_counter += msec_delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
KeyButtonEventHandler::str() const
|
||||
{
|
||||
std::ostringstream out;
|
||||
for(int i = 0; m_codes[i].is_valid();)
|
||||
{
|
||||
out << m_codes[i].get_device_id() << "-" << m_codes[i].code;
|
||||
|
||||
++i;
|
||||
if (m_codes[i].is_valid())
|
||||
out << "+";
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
||||
AbsButtonEventHandler*
|
||||
AbsButtonEventHandler::from_string(const std::string& str)
|
||||
{
|
||||
// FIXME: Need magic to detect min/max of the axis
|
||||
assert(!"not implemented");
|
||||
}
|
||||
|
||||
AbsButtonEventHandler::AbsButtonEventHandler(int code) :
|
||||
m_code(UIEvent::invalid()),
|
||||
m_value()
|
||||
{
|
||||
assert(!"Not implemented");
|
||||
// FIXME: Need magic to detect min/max of the axis
|
||||
}
|
||||
|
||||
void
|
||||
AbsButtonEventHandler::init(UInput& uinput, int slot, bool extra_devices)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
AbsButtonEventHandler::send(UInput& uinput, bool value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
uinput.send_abs(m_code.get_device_id(), m_code.code, m_value);
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
AbsButtonEventHandler::str() const
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "abs: " << m_code.get_device_id() << "-" << m_code.code << ":" << m_value;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
RelButtonEventHandler*
|
||||
RelButtonEventHandler::from_string(const std::string& str)
|
||||
{
|
||||
std::auto_ptr<RelButtonEventHandler> ev;
|
||||
|
||||
int idx = 0;
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
tokenizer tokens(str, boost::char_separator<char>(":", "", boost::keep_empty_tokens));
|
||||
|
||||
for(tokenizer::iterator i = tokens.begin(); i != tokens.end(); ++i, ++idx)
|
||||
{
|
||||
switch(idx)
|
||||
{
|
||||
case 0:
|
||||
ev.reset(new RelButtonEventHandler(str2rel_event(*i)));
|
||||
break;
|
||||
|
||||
case 1:
|
||||
ev->m_value = boost::lexical_cast<int>(*i);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ev->m_repeat = boost::lexical_cast<int>(*i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ev.release();
|
||||
}
|
||||
|
||||
RelButtonEventHandler::RelButtonEventHandler(const UIEvent& code) :
|
||||
m_code(code),
|
||||
m_value(3),
|
||||
m_repeat(100)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
RelButtonEventHandler::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
|
||||
RelButtonEventHandler::send(UInput& uinput, bool value)
|
||||
{
|
||||
if (m_repeat == -1)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
uinput.send_rel(m_code.get_device_id(), m_code.code, m_value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
uinput.send_rel_repetitive(m_code, m_value, m_repeat);
|
||||
}
|
||||
else
|
||||
{
|
||||
uinput.send_rel_repetitive(m_code, m_value, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
RelButtonEventHandler::str() const
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "rel:" << m_code.get_device_id() << "-" << m_code.code << ":" << m_value << ":" << m_repeat;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
ExecButtonEventHandler*
|
||||
ExecButtonEventHandler::from_string(const std::string& str)
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
tokenizer tokens(str, boost::char_separator<char>(":", "", boost::keep_empty_tokens));
|
||||
|
||||
std::copy(tokens.begin(), tokens.end(), std::back_inserter(args));
|
||||
|
||||
return new ExecButtonEventHandler(args);
|
||||
}
|
||||
|
||||
ExecButtonEventHandler::ExecButtonEventHandler(const std::vector<std::string>& args) :
|
||||
m_args(args)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ExecButtonEventHandler::init(UInput& uinput, int slot, bool extra_devices)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
void
|
||||
ExecButtonEventHandler::send(UInput& uinput, bool value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
pid_t pid = fork();
|
||||
if (pid == 0)
|
||||
{
|
||||
char** argv = static_cast<char**>(malloc(sizeof(char*) * (m_args.size() + 1)));
|
||||
for(size_t i = 0; i < m_args.size(); ++i)
|
||||
{
|
||||
argv[i] = strdup(m_args[i].c_str());
|
||||
}
|
||||
argv[m_args.size()] = NULL;
|
||||
|
||||
if (execvp(m_args[0].c_str(), argv) == -1)
|
||||
{
|
||||
log_error("exec failed: " << strerror(errno));
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
ExecButtonEventHandler::str() const
|
||||
{
|
||||
return "exec";
|
||||
}
|
||||
|
||||
MacroButtonEventHandler*
|
||||
MacroButtonEventHandler::from_string(const std::string& str)
|
||||
{
|
||||
std::vector<MacroEvent> events;
|
||||
|
||||
std::ifstream in(str.c_str());
|
||||
std::string line;
|
||||
while(std::getline(in, line))
|
||||
{
|
||||
MacroEvent ev = macro_event_from_string(line);
|
||||
if (ev.type != MacroEvent::kNull)
|
||||
{
|
||||
events.push_back(ev);
|
||||
}
|
||||
}
|
||||
return new MacroButtonEventHandler(events);
|
||||
}
|
||||
|
||||
MacroButtonEventHandler::MacroEvent
|
||||
MacroButtonEventHandler::macro_event_from_string(const std::string& str)
|
||||
{
|
||||
MacroEvent event;
|
||||
event.type = MacroEvent::kNull;
|
||||
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
tokenizer tokens(str, boost::char_separator<char>(" "));
|
||||
int idx = 0;
|
||||
for(tokenizer::iterator t = tokens.begin(); t != tokens.end(); ++t, ++idx)
|
||||
{
|
||||
switch(idx)
|
||||
{
|
||||
case 0:
|
||||
if (*t == "send")
|
||||
{
|
||||
event.type = MacroEvent::kSendOp;
|
||||
event.send.event = UIEvent::invalid();
|
||||
event.send.value = 0;
|
||||
}
|
||||
else if (*t == "wait")
|
||||
{
|
||||
event.type = MacroEvent::kWaitOp;
|
||||
event.wait.msec = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
{
|
||||
if (event.type == MacroEvent::kSendOp)
|
||||
{
|
||||
switch(get_event_type(*t))
|
||||
{
|
||||
case EV_REL: event.send.event = str2rel_event(*t); break;
|
||||
case EV_ABS: event.send.event = str2abs_event(*t); break;
|
||||
case EV_KEY: event.send.event = str2key_event(*t); break;
|
||||
default: throw std::runtime_error("unknown event type");
|
||||
}
|
||||
}
|
||||
else if (event.type == MacroEvent::kWaitOp)
|
||||
{
|
||||
event.wait.msec = boost::lexical_cast<int>(*t);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
if (event.type == MacroEvent::kSendOp)
|
||||
{
|
||||
event.send.value = boost::lexical_cast<int>(*t);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("to many arguments for 'wait'");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
MacroButtonEventHandler::MacroButtonEventHandler(const std::vector<MacroEvent>& events) :
|
||||
m_events(events),
|
||||
m_send_in_progress(false),
|
||||
m_countdown(0),
|
||||
m_event_counter()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
MacroButtonEventHandler::init(UInput& uinput, int slot, bool extra_devices)
|
||||
{
|
||||
for(std::vector<MacroEvent>::iterator i = m_events.begin(); i != m_events.end(); ++i)
|
||||
{
|
||||
switch(i->type)
|
||||
{
|
||||
case MacroEvent::kSendOp:
|
||||
switch(i->send.event.type)
|
||||
{
|
||||
case EV_REL:
|
||||
i->send.event.resolve_device_id(slot, extra_devices),
|
||||
uinput.add_rel(i->send.event.get_device_id(), i->send.event.code);
|
||||
break;
|
||||
|
||||
case EV_KEY:
|
||||
i->send.event.resolve_device_id(slot, extra_devices),
|
||||
uinput.add_key(i->send.event.get_device_id(), i->send.event.code);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(!"not implemented");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// nothing to do
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroButtonEventHandler::send(UInput& uinput, bool value)
|
||||
{
|
||||
if (value && !m_send_in_progress)
|
||||
{
|
||||
m_send_in_progress = true;
|
||||
m_event_counter = 0;
|
||||
m_countdown = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroButtonEventHandler::update(UInput& uinput, int msec_delta)
|
||||
{
|
||||
if (m_send_in_progress)
|
||||
{
|
||||
m_countdown -= msec_delta;
|
||||
if (m_countdown <= 0)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
switch(m_events[m_event_counter].type)
|
||||
{
|
||||
case MacroEvent::kSendOp:
|
||||
uinput.send(m_events[m_event_counter].send.event.get_device_id(),
|
||||
m_events[m_event_counter].send.event.type,
|
||||
m_events[m_event_counter].send.event.code,
|
||||
m_events[m_event_counter].send.value);
|
||||
break;
|
||||
|
||||
case MacroEvent::kWaitOp:
|
||||
m_countdown = m_events[m_event_counter].wait.msec;
|
||||
if (m_countdown > 0)
|
||||
{
|
||||
m_event_counter += 1;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(!"never reached");
|
||||
break;
|
||||
}
|
||||
|
||||
m_event_counter += 1;
|
||||
|
||||
if (m_event_counter == m_events.size())
|
||||
{
|
||||
m_send_in_progress = false;
|
||||
m_event_counter = 0;
|
||||
m_countdown = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
MacroButtonEventHandler::str() const
|
||||
{
|
||||
return "macro";
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
/* EOF */
|
||||
|
|
|
@ -73,131 +73,6 @@ public:
|
|||
virtual std::string str() const =0;
|
||||
};
|
||||
|
||||
class KeyButtonEventHandler : public ButtonEventHandler
|
||||
{
|
||||
public:
|
||||
static KeyButtonEventHandler* from_string(const std::string& str);
|
||||
|
||||
public:
|
||||
KeyButtonEventHandler();
|
||||
KeyButtonEventHandler(int deviceid, int code);
|
||||
|
||||
void init(UInput& uinput, int slot, bool extra_devices);
|
||||
void send(UInput& uinput, bool value);
|
||||
void update(UInput& uinput, int msec_delta);
|
||||
|
||||
std::string str() const;
|
||||
|
||||
private:
|
||||
static const int MAX_MODIFIER = 4;
|
||||
|
||||
bool m_state;
|
||||
// Array is terminated by !is_valid()
|
||||
UIEvent m_codes[MAX_MODIFIER+1];
|
||||
UIEvent m_secondary_codes[MAX_MODIFIER+1];
|
||||
int m_hold_threshold;
|
||||
int m_hold_counter;
|
||||
};
|
||||
|
||||
class AbsButtonEventHandler : public ButtonEventHandler
|
||||
{
|
||||
public:
|
||||
static AbsButtonEventHandler* from_string(const std::string& str);
|
||||
|
||||
public:
|
||||
AbsButtonEventHandler(int code);
|
||||
|
||||
void init(UInput& uinput, int slot, bool extra_devices);
|
||||
void send(UInput& uinput, bool value);
|
||||
void update(UInput& uinput, int msec_delta) {}
|
||||
|
||||
std::string str() const;
|
||||
|
||||
private:
|
||||
UIEvent m_code;
|
||||
int m_value;
|
||||
};
|
||||
|
||||
class RelButtonEventHandler : public ButtonEventHandler
|
||||
{
|
||||
public:
|
||||
static RelButtonEventHandler* from_string(const std::string& str);
|
||||
|
||||
public:
|
||||
RelButtonEventHandler(const UIEvent& code);
|
||||
|
||||
void init(UInput& uinput, int slot, bool extra_devices);
|
||||
void send(UInput& uinput, bool value);
|
||||
void update(UInput& uinput, int msec_delta) {}
|
||||
|
||||
std::string str() const;
|
||||
|
||||
private:
|
||||
UIEvent m_code;
|
||||
|
||||
int m_value;
|
||||
int m_repeat;
|
||||
};
|
||||
|
||||
class ExecButtonEventHandler : public ButtonEventHandler
|
||||
{
|
||||
public:
|
||||
static ExecButtonEventHandler* from_string(const std::string& str);
|
||||
|
||||
public:
|
||||
ExecButtonEventHandler(const std::vector<std::string>& args);
|
||||
|
||||
void init(UInput& uinput, int slot, bool extra_devices);
|
||||
void send(UInput& uinput, bool value);
|
||||
void update(UInput& uinput, int msec_delta) {}
|
||||
|
||||
std::string str() const;
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_args;
|
||||
};
|
||||
|
||||
class MacroButtonEventHandler : public ButtonEventHandler
|
||||
{
|
||||
public:
|
||||
private:
|
||||
struct MacroEvent {
|
||||
enum { kSendOp, kWaitOp, kNull } type;
|
||||
|
||||
union {
|
||||
struct {
|
||||
UIEvent event;
|
||||
int value;
|
||||
} send;
|
||||
|
||||
struct {
|
||||
int msec;
|
||||
} wait;
|
||||
};
|
||||
};
|
||||
|
||||
public:
|
||||
static MacroButtonEventHandler* from_string(const std::string& str);
|
||||
|
||||
public:
|
||||
MacroButtonEventHandler(const std::vector<MacroEvent>& events);
|
||||
|
||||
void init(UInput& uinput, int slot, bool extra_devices);
|
||||
void send(UInput& uinput, bool value);
|
||||
void update(UInput& uinput, int msec_delta);
|
||||
|
||||
std::string str() const;
|
||||
|
||||
private:
|
||||
static MacroEvent macro_event_from_string(const std::string& str);
|
||||
|
||||
private:
|
||||
std::vector<MacroEvent> m_events;
|
||||
bool m_send_in_progress;
|
||||
int m_countdown;
|
||||
std::vector<MacroEvent>::size_type m_event_counter;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
||||
|
|
60
src/buttonevent/abs_button_event_handler.cpp
Normal file
60
src/buttonevent/abs_button_event_handler.cpp
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
** 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_button_event_handler.hpp"
|
||||
|
||||
#include "uinput.hpp"
|
||||
|
||||
AbsButtonEventHandler*
|
||||
AbsButtonEventHandler::from_string(const std::string& str)
|
||||
{
|
||||
// FIXME: Need magic to detect min/max of the axis
|
||||
assert(!"not implemented");
|
||||
}
|
||||
|
||||
AbsButtonEventHandler::AbsButtonEventHandler(int code) :
|
||||
m_code(UIEvent::invalid()),
|
||||
m_value()
|
||||
{
|
||||
assert(!"Not implemented");
|
||||
// FIXME: Need magic to detect min/max of the axis
|
||||
}
|
||||
|
||||
void
|
||||
AbsButtonEventHandler::init(UInput& uinput, int slot, bool extra_devices)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
AbsButtonEventHandler::send(UInput& uinput, bool value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
uinput.send_abs(m_code.get_device_id(), m_code.code, m_value);
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
AbsButtonEventHandler::str() const
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "abs: " << m_code.get_device_id() << "-" << m_code.code << ":" << m_value;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
/* EOF */
|
45
src/buttonevent/abs_button_event_handler.hpp
Normal file
45
src/buttonevent/abs_button_event_handler.hpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
** 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_BUTTONEVENT_ABS_BUTTON_EVENT_HANDLER_HPP
|
||||
#define HEADER_XBOXDRV_BUTTONEVENT_ABS_BUTTON_EVENT_HANDLER_HPP
|
||||
|
||||
#include "button_event.hpp"
|
||||
|
||||
class AbsButtonEventHandler : public ButtonEventHandler
|
||||
{
|
||||
public:
|
||||
static AbsButtonEventHandler* from_string(const std::string& str);
|
||||
|
||||
public:
|
||||
AbsButtonEventHandler(int code);
|
||||
|
||||
void init(UInput& uinput, int slot, bool extra_devices);
|
||||
void send(UInput& uinput, bool value);
|
||||
void update(UInput& uinput, int msec_delta) {}
|
||||
|
||||
std::string str() const;
|
||||
|
||||
private:
|
||||
UIEvent m_code;
|
||||
int m_value;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
81
src/buttonevent/exec_button_event_handler.cpp
Normal file
81
src/buttonevent/exec_button_event_handler.cpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
** 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 "exec_button_event_handler.hpp"
|
||||
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "log.hpp"
|
||||
|
||||
ExecButtonEventHandler*
|
||||
ExecButtonEventHandler::from_string(const std::string& str)
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
tokenizer tokens(str, boost::char_separator<char>(":", "", boost::keep_empty_tokens));
|
||||
|
||||
std::copy(tokens.begin(), tokens.end(), std::back_inserter(args));
|
||||
|
||||
return new ExecButtonEventHandler(args);
|
||||
}
|
||||
|
||||
ExecButtonEventHandler::ExecButtonEventHandler(const std::vector<std::string>& args) :
|
||||
m_args(args)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ExecButtonEventHandler::init(UInput& uinput, int slot, bool extra_devices)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
void
|
||||
ExecButtonEventHandler::send(UInput& uinput, bool value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
pid_t pid = fork();
|
||||
if (pid == 0)
|
||||
{
|
||||
char** argv = static_cast<char**>(malloc(sizeof(char*) * (m_args.size() + 1)));
|
||||
for(size_t i = 0; i < m_args.size(); ++i)
|
||||
{
|
||||
argv[i] = strdup(m_args[i].c_str());
|
||||
}
|
||||
argv[m_args.size()] = NULL;
|
||||
|
||||
if (execvp(m_args[0].c_str(), argv) == -1)
|
||||
{
|
||||
log_error("exec failed: " << strerror(errno));
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
ExecButtonEventHandler::str() const
|
||||
{
|
||||
return "exec";
|
||||
}
|
||||
|
||||
/* EOF */
|
44
src/buttonevent/exec_button_event_handler.hpp
Normal file
44
src/buttonevent/exec_button_event_handler.hpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
** 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_BUTTONEVENT_EXEC_BUTTON_EVENT_HANDLER_HPP
|
||||
#define HEADER_XBOXDRV_BUTTONEVENT_EXEC_BUTTON_EVENT_HANDLER_HPP
|
||||
|
||||
#include "button_event.hpp"
|
||||
|
||||
class ExecButtonEventHandler : public ButtonEventHandler
|
||||
{
|
||||
public:
|
||||
static ExecButtonEventHandler* from_string(const std::string& str);
|
||||
|
||||
public:
|
||||
ExecButtonEventHandler(const std::vector<std::string>& args);
|
||||
|
||||
void init(UInput& uinput, int slot, bool extra_devices);
|
||||
void send(UInput& uinput, bool value);
|
||||
void update(UInput& uinput, int msec_delta) {}
|
||||
|
||||
std::string str() const;
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_args;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
230
src/buttonevent/key_button_event_handler.cpp
Normal file
230
src/buttonevent/key_button_event_handler.cpp
Normal file
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
** 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 "buttonevent/key_button_event_handler.hpp"
|
||||
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <linux/input.h>
|
||||
|
||||
#include "evdev_helper.hpp"
|
||||
#include "uinput.hpp"
|
||||
|
||||
KeyButtonEventHandler*
|
||||
KeyButtonEventHandler::from_string(const std::string& str)
|
||||
{
|
||||
//std::cout << " KeyButtonEventHandler::from_string: " << str << std::endl;
|
||||
|
||||
std::auto_ptr<KeyButtonEventHandler> ev;
|
||||
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
tokenizer tokens(str, boost::char_separator<char>(":", "", boost::keep_empty_tokens));
|
||||
int idx = 0;
|
||||
for(tokenizer::iterator i = tokens.begin(); i != tokens.end(); ++i, ++idx)
|
||||
{
|
||||
switch(idx)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
ev.reset(new KeyButtonEventHandler());
|
||||
|
||||
boost::char_separator<char> plus_sep("+", "", boost::keep_empty_tokens);
|
||||
tokenizer ev_tokens(*i, plus_sep);
|
||||
int k = 0;
|
||||
for(tokenizer::iterator m = ev_tokens.begin(); m != ev_tokens.end() && k < MAX_MODIFIER; ++m, ++k)
|
||||
{
|
||||
ev->m_codes[k] = str2key_event(*m);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
{
|
||||
boost::char_separator<char> plus_sep("+", "", boost::keep_empty_tokens);
|
||||
tokenizer ev_tokens(*i, plus_sep);
|
||||
int k = 0;
|
||||
for(tokenizer::iterator m = ev_tokens.begin(); m != ev_tokens.end() && k < MAX_MODIFIER; ++m, ++k)
|
||||
{
|
||||
ev->m_secondary_codes[k] = str2key_event(*m);
|
||||
}
|
||||
|
||||
ev->m_hold_threshold = 250;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
ev->m_hold_threshold = boost::lexical_cast<int>(*i);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "to many arguments in '" << str << "'";
|
||||
throw std::runtime_error(out.str());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ev.release();
|
||||
}
|
||||
|
||||
KeyButtonEventHandler::KeyButtonEventHandler() :
|
||||
m_state(false),
|
||||
m_codes(),
|
||||
m_secondary_codes(),
|
||||
m_hold_threshold(0),
|
||||
m_hold_counter(0)
|
||||
{
|
||||
std::fill_n(m_codes, MAX_MODIFIER + 1, UIEvent::invalid());
|
||||
std::fill_n(m_secondary_codes, MAX_MODIFIER + 1, UIEvent::invalid());
|
||||
}
|
||||
|
||||
KeyButtonEventHandler::KeyButtonEventHandler(int device_id, int code) :
|
||||
m_state(false),
|
||||
m_codes(),
|
||||
m_secondary_codes(),
|
||||
m_hold_threshold(0),
|
||||
m_hold_counter(0)
|
||||
{
|
||||
std::fill_n(m_codes, MAX_MODIFIER + 1, UIEvent::invalid());
|
||||
std::fill_n(m_secondary_codes, MAX_MODIFIER + 1, UIEvent::invalid());
|
||||
m_codes[0] = UIEvent::create(device_id, EV_KEY, code);
|
||||
}
|
||||
|
||||
void
|
||||
KeyButtonEventHandler::init(UInput& uinput, int slot, bool extra_devices)
|
||||
{
|
||||
for(int i = 0; m_codes[i].is_valid(); ++i)
|
||||
{
|
||||
m_codes[i].resolve_device_id(slot, extra_devices);
|
||||
uinput.add_key(m_codes[i].get_device_id(), m_codes[i].code);
|
||||
}
|
||||
|
||||
if (m_hold_threshold)
|
||||
{
|
||||
for(int i = 0; m_secondary_codes[i].is_valid(); ++i)
|
||||
{
|
||||
m_secondary_codes[i].resolve_device_id(slot, extra_devices);
|
||||
uinput.add_key(m_secondary_codes[i].get_device_id(), m_secondary_codes[i].code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
KeyButtonEventHandler::send(UInput& uinput, bool value)
|
||||
{
|
||||
if (m_state != value)
|
||||
{
|
||||
m_state = value;
|
||||
|
||||
if (m_hold_threshold == 0)
|
||||
{
|
||||
// FIXME: should handle key releases in reverse order
|
||||
for(int i = 0; m_codes[i].is_valid(); ++i)
|
||||
{
|
||||
uinput.send_key(m_codes[i].get_device_id(), m_codes[i].code, m_state);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_hold_counter < m_hold_threshold)
|
||||
{
|
||||
if (m_state)
|
||||
{
|
||||
// we are only sending events after release or when
|
||||
// hold_threshold is passed
|
||||
}
|
||||
else
|
||||
{
|
||||
// send both a press and release event after another, aka a "click"
|
||||
for(int i = 0; m_codes[i].is_valid(); ++i)
|
||||
{
|
||||
uinput.send_key(m_codes[i].get_device_id(), m_codes[i].code, true);
|
||||
}
|
||||
// FIXME: should do this in reverse order
|
||||
for(int i = 0; m_codes[i].is_valid(); ++i)
|
||||
{
|
||||
uinput.send_key(m_codes[i].get_device_id(), m_codes[i].code, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_state)
|
||||
{
|
||||
// should never happen
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: should do in reverse
|
||||
for(int i = 0; m_secondary_codes[i].is_valid(); ++i)
|
||||
{
|
||||
uinput.send_key(m_secondary_codes[i].get_device_id(), m_secondary_codes[i].code, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_state)
|
||||
{
|
||||
m_hold_counter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
KeyButtonEventHandler::update(UInput& uinput, int msec_delta)
|
||||
{
|
||||
if (m_state && m_hold_threshold)
|
||||
{
|
||||
if (m_hold_counter < m_hold_threshold &&
|
||||
m_hold_counter + msec_delta >= m_hold_threshold)
|
||||
{
|
||||
// start sending the secondary events
|
||||
for(int i = 0; m_secondary_codes[i].is_valid(); ++i)
|
||||
{
|
||||
uinput.send_key(m_secondary_codes[i].get_device_id(), m_secondary_codes[i].code, true);
|
||||
}
|
||||
uinput.sync();
|
||||
}
|
||||
|
||||
if (m_hold_counter < m_hold_threshold)
|
||||
{
|
||||
m_hold_counter += msec_delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
KeyButtonEventHandler::str() const
|
||||
{
|
||||
std::ostringstream out;
|
||||
for(int i = 0; m_codes[i].is_valid();)
|
||||
{
|
||||
out << m_codes[i].get_device_id() << "-" << m_codes[i].code;
|
||||
|
||||
++i;
|
||||
if (m_codes[i].is_valid())
|
||||
out << "+";
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
||||
/* EOF */
|
52
src/buttonevent/key_button_event_handler.hpp
Normal file
52
src/buttonevent/key_button_event_handler.hpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
** 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_BUTTONEVENT_KEY_BUTTON_EVENT_HANDLER_HPP
|
||||
#define HEADER_XBOXDRV_BUTTONEVENT_KEY_BUTTON_EVENT_HANDLER_HPP
|
||||
|
||||
#include "button_event.hpp"
|
||||
|
||||
class KeyButtonEventHandler : public ButtonEventHandler
|
||||
{
|
||||
public:
|
||||
static KeyButtonEventHandler* from_string(const std::string& str);
|
||||
|
||||
public:
|
||||
KeyButtonEventHandler();
|
||||
KeyButtonEventHandler(int deviceid, int code);
|
||||
|
||||
void init(UInput& uinput, int slot, bool extra_devices);
|
||||
void send(UInput& uinput, bool value);
|
||||
void update(UInput& uinput, int msec_delta);
|
||||
|
||||
std::string str() const;
|
||||
|
||||
private:
|
||||
static const int MAX_MODIFIER = 4;
|
||||
|
||||
bool m_state;
|
||||
// Array is terminated by !is_valid()
|
||||
UIEvent m_codes[MAX_MODIFIER+1];
|
||||
UIEvent m_secondary_codes[MAX_MODIFIER+1];
|
||||
int m_hold_threshold;
|
||||
int m_hold_counter;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
221
src/buttonevent/macro_button_event_handler.cpp
Normal file
221
src/buttonevent/macro_button_event_handler.cpp
Normal file
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
** 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 "buttonevent/macro_button_event_handler.hpp"
|
||||
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <fstream>
|
||||
#include <linux/input.h>
|
||||
#include <vector>
|
||||
|
||||
#include "evdev_helper.hpp"
|
||||
#include "uinput.hpp"
|
||||
|
||||
MacroButtonEventHandler*
|
||||
MacroButtonEventHandler::from_string(const std::string& str)
|
||||
{
|
||||
std::vector<MacroEvent> events;
|
||||
|
||||
std::ifstream in(str.c_str());
|
||||
std::string line;
|
||||
while(std::getline(in, line))
|
||||
{
|
||||
MacroEvent ev = macro_event_from_string(line);
|
||||
if (ev.type != MacroEvent::kNull)
|
||||
{
|
||||
events.push_back(ev);
|
||||
}
|
||||
}
|
||||
return new MacroButtonEventHandler(events);
|
||||
}
|
||||
|
||||
MacroButtonEventHandler::MacroEvent
|
||||
MacroButtonEventHandler::macro_event_from_string(const std::string& str)
|
||||
{
|
||||
MacroEvent event;
|
||||
event.type = MacroEvent::kNull;
|
||||
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
tokenizer tokens(str, boost::char_separator<char>(" "));
|
||||
int idx = 0;
|
||||
for(tokenizer::iterator t = tokens.begin(); t != tokens.end(); ++t, ++idx)
|
||||
{
|
||||
switch(idx)
|
||||
{
|
||||
case 0:
|
||||
if (*t == "send")
|
||||
{
|
||||
event.type = MacroEvent::kSendOp;
|
||||
event.send.event = UIEvent::invalid();
|
||||
event.send.value = 0;
|
||||
}
|
||||
else if (*t == "wait")
|
||||
{
|
||||
event.type = MacroEvent::kWaitOp;
|
||||
event.wait.msec = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
{
|
||||
if (event.type == MacroEvent::kSendOp)
|
||||
{
|
||||
switch(get_event_type(*t))
|
||||
{
|
||||
case EV_REL: event.send.event = str2rel_event(*t); break;
|
||||
case EV_ABS: event.send.event = str2abs_event(*t); break;
|
||||
case EV_KEY: event.send.event = str2key_event(*t); break;
|
||||
default: throw std::runtime_error("unknown event type");
|
||||
}
|
||||
}
|
||||
else if (event.type == MacroEvent::kWaitOp)
|
||||
{
|
||||
event.wait.msec = boost::lexical_cast<int>(*t);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
if (event.type == MacroEvent::kSendOp)
|
||||
{
|
||||
event.send.value = boost::lexical_cast<int>(*t);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("to many arguments for 'wait'");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
MacroButtonEventHandler::MacroButtonEventHandler(const std::vector<MacroEvent>& events) :
|
||||
m_events(events),
|
||||
m_send_in_progress(false),
|
||||
m_countdown(0),
|
||||
m_event_counter()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
MacroButtonEventHandler::init(UInput& uinput, int slot, bool extra_devices)
|
||||
{
|
||||
for(std::vector<MacroEvent>::iterator i = m_events.begin(); i != m_events.end(); ++i)
|
||||
{
|
||||
switch(i->type)
|
||||
{
|
||||
case MacroEvent::kSendOp:
|
||||
switch(i->send.event.type)
|
||||
{
|
||||
case EV_REL:
|
||||
i->send.event.resolve_device_id(slot, extra_devices),
|
||||
uinput.add_rel(i->send.event.get_device_id(), i->send.event.code);
|
||||
break;
|
||||
|
||||
case EV_KEY:
|
||||
i->send.event.resolve_device_id(slot, extra_devices),
|
||||
uinput.add_key(i->send.event.get_device_id(), i->send.event.code);
|
||||
break;
|
||||
|
||||
case EV_ABS:
|
||||
//i->send.event.resolve_device_id(slot, extra_devices);
|
||||
// uinput.add_abs(i->send.event.get_device_id(), i->send.event.code);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(!"not implemented");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// nothing to do
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroButtonEventHandler::send(UInput& uinput, bool value)
|
||||
{
|
||||
if (value && !m_send_in_progress)
|
||||
{
|
||||
m_send_in_progress = true;
|
||||
m_event_counter = 0;
|
||||
m_countdown = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroButtonEventHandler::update(UInput& uinput, int msec_delta)
|
||||
{
|
||||
if (m_send_in_progress)
|
||||
{
|
||||
m_countdown -= msec_delta;
|
||||
if (m_countdown <= 0)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
switch(m_events[m_event_counter].type)
|
||||
{
|
||||
case MacroEvent::kSendOp:
|
||||
uinput.send(m_events[m_event_counter].send.event.get_device_id(),
|
||||
m_events[m_event_counter].send.event.type,
|
||||
m_events[m_event_counter].send.event.code,
|
||||
m_events[m_event_counter].send.value);
|
||||
break;
|
||||
|
||||
case MacroEvent::kWaitOp:
|
||||
m_countdown = m_events[m_event_counter].wait.msec;
|
||||
if (m_countdown > 0)
|
||||
{
|
||||
m_event_counter += 1;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(!"never reached");
|
||||
break;
|
||||
}
|
||||
|
||||
m_event_counter += 1;
|
||||
|
||||
if (m_event_counter == m_events.size())
|
||||
{
|
||||
m_send_in_progress = false;
|
||||
m_event_counter = 0;
|
||||
m_countdown = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
MacroButtonEventHandler::str() const
|
||||
{
|
||||
return "macro";
|
||||
}
|
||||
|
||||
/* EOF */
|
67
src/buttonevent/macro_button_event_handler.hpp
Normal file
67
src/buttonevent/macro_button_event_handler.hpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
** 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_BUTTONEVENT_MACRO_BUTTON_EVENT_HANDLER_HPP
|
||||
#define HEADER_XBOXDRV_BUTTONEVENT_MACRO_BUTTON_EVENT_HANDLER_HPP
|
||||
|
||||
#include "button_event.hpp"
|
||||
|
||||
class MacroButtonEventHandler : public ButtonEventHandler
|
||||
{
|
||||
public:
|
||||
private:
|
||||
struct MacroEvent {
|
||||
enum { kSendOp, kWaitOp, kNull } type;
|
||||
|
||||
union {
|
||||
struct {
|
||||
UIEvent event;
|
||||
int value;
|
||||
} send;
|
||||
|
||||
struct {
|
||||
int msec;
|
||||
} wait;
|
||||
};
|
||||
};
|
||||
|
||||
public:
|
||||
static MacroButtonEventHandler* from_string(const std::string& str);
|
||||
|
||||
public:
|
||||
MacroButtonEventHandler(const std::vector<MacroEvent>& events);
|
||||
|
||||
void init(UInput& uinput, int slot, bool extra_devices);
|
||||
void send(UInput& uinput, bool value);
|
||||
void update(UInput& uinput, int msec_delta);
|
||||
|
||||
std::string str() const;
|
||||
|
||||
private:
|
||||
static MacroEvent macro_event_from_string(const std::string& str);
|
||||
|
||||
private:
|
||||
std::vector<MacroEvent> m_events;
|
||||
bool m_send_in_progress;
|
||||
int m_countdown;
|
||||
std::vector<MacroEvent>::size_type m_event_counter;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
101
src/buttonevent/rel_button_event_handler.cpp
Normal file
101
src/buttonevent/rel_button_event_handler.cpp
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
** 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 "buttonevent/rel_button_event_handler.hpp"
|
||||
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
||||
#include "evdev_helper.hpp"
|
||||
#include "uinput.hpp"
|
||||
|
||||
RelButtonEventHandler*
|
||||
RelButtonEventHandler::from_string(const std::string& str)
|
||||
{
|
||||
std::auto_ptr<RelButtonEventHandler> ev;
|
||||
|
||||
int idx = 0;
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
tokenizer tokens(str, boost::char_separator<char>(":", "", boost::keep_empty_tokens));
|
||||
|
||||
for(tokenizer::iterator i = tokens.begin(); i != tokens.end(); ++i, ++idx)
|
||||
{
|
||||
switch(idx)
|
||||
{
|
||||
case 0:
|
||||
ev.reset(new RelButtonEventHandler(str2rel_event(*i)));
|
||||
break;
|
||||
|
||||
case 1:
|
||||
ev->m_value = boost::lexical_cast<int>(*i);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ev->m_repeat = boost::lexical_cast<int>(*i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ev.release();
|
||||
}
|
||||
|
||||
RelButtonEventHandler::RelButtonEventHandler(const UIEvent& code) :
|
||||
m_code(code),
|
||||
m_value(3),
|
||||
m_repeat(100)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
RelButtonEventHandler::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
|
||||
RelButtonEventHandler::send(UInput& uinput, bool value)
|
||||
{
|
||||
if (m_repeat == -1)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
uinput.send_rel(m_code.get_device_id(), m_code.code, m_value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
uinput.send_rel_repetitive(m_code, m_value, m_repeat);
|
||||
}
|
||||
else
|
||||
{
|
||||
uinput.send_rel_repetitive(m_code, m_value, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
RelButtonEventHandler::str() const
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "rel:" << m_code.get_device_id() << "-" << m_code.code << ":" << m_value << ":" << m_repeat;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
/* EOF */
|
47
src/buttonevent/rel_button_event_handler.hpp
Normal file
47
src/buttonevent/rel_button_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_BUTTONEVENT_REL_BUTTON_EVENT_HANDLER_HPP
|
||||
#define HEADER_XBOXDRV_BUTTONEVENT_REL_BUTTON_EVENT_HANDLER_HPP
|
||||
|
||||
#include "button_event.hpp"
|
||||
|
||||
class RelButtonEventHandler : public ButtonEventHandler
|
||||
{
|
||||
public:
|
||||
static RelButtonEventHandler* from_string(const std::string& str);
|
||||
|
||||
public:
|
||||
RelButtonEventHandler(const UIEvent& code);
|
||||
|
||||
void init(UInput& uinput, int slot, bool extra_devices);
|
||||
void send(UInput& uinput, bool value);
|
||||
void update(UInput& uinput, int msec_delta) {}
|
||||
|
||||
std::string str() const;
|
||||
|
||||
private:
|
||||
UIEvent m_code;
|
||||
|
||||
int m_value;
|
||||
int m_repeat;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
Loading…
Add table
Reference in a new issue