Implemented CycleKeyButtonEvent, allows to send different event on each button press

This commit is contained in:
Ingo Ruhnke 2011-07-07 03:54:30 +02:00
parent e9714abc4d
commit 302a518aea
9 changed files with 578 additions and 4 deletions

9
TODO
View file

@ -64,12 +64,13 @@ $ git-buildpackage --git-no-create-orig --git-debian-branch=stable-lts --git-tag
$ sudo pbuilder --build --basetgz /var/cache/pbuilder/base-lucid.tgz ../xboxdrv-stable_0.6.6-1~lucid2.dsc
Stuff to do before 0.8.0 release:
Stuff to do before 0.8.1 release:
=================================
Checklist
=========
* cycle-key is incomplete, should have additional mode that allows
next/prev without sending events, also has issues with stuck buttons
when multiple keys are pressed
* don't compile tests by default
* use FIXME for random code improvements, use BUG for actual problems

14
examples/cyclekey.xboxdrv Normal file
View file

@ -0,0 +1,14 @@
[xboxdrv]
ui-clear=true
extra-events=false
extra-devices=false
[ui-axismap]
X1=ABS_X
Y1=ABS_Y
[ui-buttonmap]
RB=cycle-key-named:foo:JS_1:JS_2:JS_3:JS_4
LB=cycle-key-ref:foo:backward
# EOF #

View file

@ -28,6 +28,8 @@
#include "uinput.hpp"
#include "buttonevent/abs_button_event_handler.hpp"
#include "buttonevent/cycle_key_button_event_handler.hpp"
#include "buttonevent/cycle_key_ref_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"
@ -97,6 +99,18 @@ ButtonEvent::from_string(const std::string& str, const std::string& directory)
{
return ButtonEvent::create(KeyButtonEventHandler::from_string(rest));
}
else if (token == "cycle-key")
{
return ButtonEvent::create(CycleKeyButtonEventHandler::from_string(rest));
}
else if (token == "cycle-key-named")
{
return ButtonEvent::create(CycleKeyButtonEventHandler::from_string_named(rest));
}
else if (token == "cycle-key-ref")
{
return ButtonEvent::create(CycleKeyRefButtonEventHandler::from_string(rest));
}
else if (token == "exec")
{
return ButtonEvent::create(ExecButtonEventHandler::from_string(rest));

View file

@ -0,0 +1,161 @@
/*
** 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/cycle_key_button_event_handler.hpp"
#include <boost/tokenizer.hpp>
#include <stdexcept>
#include <memory>
#include "ui_event_sequence.hpp"
#include "raise_exception.hpp"
std::map<std::string, CycleKeyButtonEventHandler*> CycleKeyButtonEventHandler::s_lookup_table;
CycleKeyButtonEventHandler*
CycleKeyButtonEventHandler::from_string(const std::string& value)
{
return from_string_named(":" + value);
}
CycleKeyButtonEventHandler*
CycleKeyButtonEventHandler::from_string_named(const std::string& value)
{
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
tokenizer tokens(value, boost::char_separator<char>(":", "", boost::keep_empty_tokens));
std::vector<std::string> args(tokens.begin(), tokens.end());
if (args.size() < 2)
{
raise_exception(std::runtime_error, "need at least two arguments");
}
else
{
Keys keys;
std::string name = args[0];
for(std::vector<std::string>::const_iterator i = args.begin()+1; i != args.end(); ++i)
{
keys.push_back(UIEventSequence::from_string(*i));
}
std::auto_ptr<CycleKeyButtonEventHandler> cycle(new CycleKeyButtonEventHandler(keys));
// if name is empty, don't put it in the lookup table
if (!name.empty())
{
if (lookup(name) != 0)
{
raise_exception(std::runtime_error, "duplicate name entry");
}
s_lookup_table.insert(std::pair<std::string, CycleKeyButtonEventHandler*>(name, cycle.get()));
}
return cycle.release();
}
}
CycleKeyButtonEventHandler*
CycleKeyButtonEventHandler::lookup(const std::string& name)
{
std::map<std::string, CycleKeyButtonEventHandler*>::iterator it = s_lookup_table.find(name);
if (it == s_lookup_table.end())
{
return 0;
}
else
{
return it->second;
}
}
CycleKeyButtonEventHandler::CycleKeyButtonEventHandler(const Keys& keys) :
m_keys(keys),
m_current_key(keys.size()-1)
{
assert(!keys.empty());
}
void
CycleKeyButtonEventHandler::init(UInput& uinput, int slot, bool extra_devices)
{
for(Keys::iterator i = m_keys.begin(); i != m_keys.end(); ++i)
{
i->init(uinput, slot, extra_devices);
}
}
void
CycleKeyButtonEventHandler::send(UInput& uinput, bool value)
{
if (value)
{
next_key();
send_only(uinput, value);
}
else
{
send_only(uinput, value);
}
}
void
CycleKeyButtonEventHandler::send_only(UInput& uinput, bool value)
{
m_keys[m_current_key].send(uinput, value);
}
void
CycleKeyButtonEventHandler::update(UInput& uinput, int msec_delta)
{
}
void
CycleKeyButtonEventHandler::next_key()
{
if (m_current_key >= static_cast<int>(m_keys.size())-1)
{
m_current_key = 0;
}
else
{
m_current_key += 1;
}
}
void
CycleKeyButtonEventHandler::prev_key()
{
if (m_current_key <= 0)
{
m_current_key = m_keys.size()-1;
}
else
{
m_current_key -= 1;
}
}
std::string
CycleKeyButtonEventHandler::str() const
{
return "cycle-key";
}
/* EOF */

View file

@ -0,0 +1,63 @@
/*
** 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_CYCLE_KEY_BUTTON_EVENT_HANDLER_HPP
#define HEADER_XBOXDRV_BUTTONEVENT_CYCLE_KEY_BUTTON_EVENT_HANDLER_HPP
#include <map>
#include "button_event.hpp"
#include "ui_event_sequence.hpp"
class CycleKeyButtonEventHandler : public ButtonEventHandler
{
private:
static std::map<std::string, CycleKeyButtonEventHandler*> s_lookup_table;
public:
static CycleKeyButtonEventHandler* from_string(const std::string& str);
static CycleKeyButtonEventHandler* from_string_named(const std::string& str);
static CycleKeyButtonEventHandler* lookup(const std::string& name);
private:
typedef std::vector<UIEventSequence> Keys;
Keys m_keys;
int m_current_key;
private:
CycleKeyButtonEventHandler(const Keys& keys);
public:
void init(UInput& uinput, int slot, bool extra_devices);
void send(UInput& uinput, bool value);
void send_only(UInput& uinput, bool value);
void update(UInput& uinput, int msec_delta);
void next_key();
void prev_key();
std::string str() const;
private:
CycleKeyButtonEventHandler(const CycleKeyButtonEventHandler&);
CycleKeyButtonEventHandler& operator=(const CycleKeyButtonEventHandler&);
};
#endif
/* EOF */

View file

@ -0,0 +1,142 @@
/*
** 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/cycle_key_ref_button_event_handler.hpp"
#include <boost/tokenizer.hpp>
#include "buttonevent/cycle_key_button_event_handler.hpp"
#include "raise_exception.hpp"
namespace {
CycleKeyRefButtonEventHandler::Direction
direction_from_string(const std::string& value)
{
if (value == "forward")
{
return CycleKeyRefButtonEventHandler::kForward;
}
else if (value == "backward")
{
return CycleKeyRefButtonEventHandler::kBackward;
}
else if (value == "none")
{
return CycleKeyRefButtonEventHandler::kNone;
}
else
{
raise_exception(std::runtime_error, "allowed values are 'forward', 'backward' and 'none'");
}
}
} // namespace
CycleKeyRefButtonEventHandler*
CycleKeyRefButtonEventHandler::from_string(const std::string& value)
{
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
tokenizer tokens(value, boost::char_separator<char>(":", "", boost::keep_empty_tokens));
std::vector<std::string> args(tokens.begin(), tokens.end());
if (args.size() > 0)
{
std::string name = args[0];
Direction direction = (args.size() > 1) ? direction_from_string(args[1]) : kBackward;
bool press = (args.size() > 2) ? boost::lexical_cast<bool>(args[2]) : true;
CycleKeyButtonEventHandler* cycle = CycleKeyButtonEventHandler::lookup(name);
if (!cycle)
{
raise_exception(std::runtime_error, "need at least one arguments");
}
else
{
return new CycleKeyRefButtonEventHandler(cycle, direction, press);
}
}
else
{
raise_exception(std::runtime_error, "need at least one arguments");
}
}
CycleKeyRefButtonEventHandler::CycleKeyRefButtonEventHandler(CycleKeyButtonEventHandler* button_handler,
Direction direction,
bool press) :
m_button_handler(button_handler),
m_direction(direction),
m_send_press(press)
{
// FIXME: m_button_handler is just a raw pointer without a well
// defined scope, bad idea, should use a boost::weak_ref<> instead
// or something like that
}
void
CycleKeyRefButtonEventHandler::init(UInput& uinput, int slot, bool extra_devices)
{
// nothing to do, as m_button_handler is doing all the work
}
void
CycleKeyRefButtonEventHandler::send(UInput& uinput, bool value)
{
if (value)
{
switch(m_direction)
{
case kBackward:
m_button_handler->prev_key();
break;
case kForward:
m_button_handler->next_key();
break;
case kNone:
break;
}
if (m_send_press)
{
m_button_handler->send_only(uinput, value);
}
}
else
{
if (m_send_press)
{
m_button_handler->send_only(uinput, value);
}
}
}
void
CycleKeyRefButtonEventHandler::update(UInput& uinput, int msec_delta)
{
}
std::string
CycleKeyRefButtonEventHandler::str() const
{
return "cycle-key-ref";
}
/* EOF */

View file

@ -0,0 +1,66 @@
/*
** 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_CYCLE_KEY_REF_BUTTON_EVENT_HANDLER_HPP
#define HEADER_XBOXDRV_BUTTONEVENT_CYCLE_KEY_REF_BUTTON_EVENT_HANDLER_HPP
#include "button_event.hpp"
class CycleKeyButtonEventHandler;
class CycleKeyRefButtonEventHandler : public ButtonEventHandler
{
public:
/**
Syntax: "{direction}:{press}"
direction: can either be 'forward', 'backward', 'none' or an
integer, in the case of an integer, the pointer is moved to that key
press: a bool, true if a keypress is send,
false when only the current key should change
*/
static CycleKeyRefButtonEventHandler* from_string(const std::string& value);
public:
enum Direction { kForward, kBackward, kNone };
public:
CycleKeyRefButtonEventHandler(CycleKeyButtonEventHandler* button_handler,
Direction direction,
bool press);
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:
CycleKeyButtonEventHandler* m_button_handler;
Direction m_direction;
bool m_send_press;
private:
CycleKeyRefButtonEventHandler(const CycleKeyRefButtonEventHandler&);
CycleKeyRefButtonEventHandler& operator=(const CycleKeyRefButtonEventHandler&);
};
#endif
/* EOF */

67
src/ui_event_sequence.cpp Normal file
View 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/>.
*/
#include "ui_event_sequence.hpp"
#include <boost/tokenizer.hpp>
#include "evdev_helper.hpp"
#include "ui_event.hpp"
#include "uinput.hpp"
UIEventSequence
UIEventSequence::from_string(const std::string& value)
{
UIEvents sequence;
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
tokenizer ev_tokens(value, boost::char_separator<char>("+", "", boost::keep_empty_tokens));
int k = 0;
for(tokenizer::iterator m = ev_tokens.begin(); m != ev_tokens.end(); ++m, ++k)
{
sequence.push_back(str2key_event(*m));
}
return sequence;
}
UIEventSequence::UIEventSequence(const UIEvents& sequence) :
m_sequence(sequence)
{
}
void
UIEventSequence::init(UInput& uinput, int slot, bool extra_devices)
{
for(UIEvents::iterator i = m_sequence.begin(); i != m_sequence.end(); ++i)
{
i->resolve_device_id(slot, extra_devices);
uinput.add_key(i->get_device_id(), i->code);
}
}
void
UIEventSequence::send(UInput& uinput, int value)
{
for(UIEvents::iterator i = m_sequence.begin(); i != m_sequence.end(); ++i)
{
uinput.send_key(i->get_device_id(), i->code, value);
}
}
/* EOF */

46
src/ui_event_sequence.hpp Normal file
View file

@ -0,0 +1,46 @@
/*
** 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_UI_EVENT_SEQUENCE_HPP
#define HEADER_XBOXDRV_UI_EVENT_SEQUENCE_HPP
#include <vector>
#include "ui_event.hpp"
class UInput;
class UIEventSequence
{
public:
static UIEventSequence from_string(const std::string& value);
private:
typedef std::vector<UIEvent> UIEvents;
UIEvents m_sequence;
public:
UIEventSequence(const UIEvents& sequence);
void init(UInput& uinput, int slot, bool extra_devices);
void send(UInput& uinput, int value);
};
#endif
/* EOF */