From dcdf06ed2b097e17e6eb8ce4b4a88cf1ee268368 Mon Sep 17 00:00:00 2001
From: Ingo Ruhnke <grumbel@gmx.de>
Date: Sat, 25 Dec 2010 13:25:02 +0100
Subject: [PATCH] Converted AxisEvent and ButtonEvent to AxisEventPtr and
 ButtonEventPtr

---
 TODO                         |  28 +++++++--
 VERSION                      |   2 +-
 src/axis_event.cpp           | 114 ++++++++++++++++-------------------
 src/axis_event.hpp           |  32 +++++-----
 src/axis_map.cpp             |   8 +--
 src/axis_map.hpp             |  10 +--
 src/button_event.cpp         |  62 +++++++++----------
 src/button_event.hpp         |  23 ++++---
 src/button_map.cpp           |   8 +--
 src/button_map.hpp           |  10 +--
 src/command_line_options.cpp |  14 ++---
 src/uinput.cpp               |  46 +++++++-------
 12 files changed, 185 insertions(+), 172 deletions(-)

diff --git a/TODO b/TODO
index 27036e0..67d9aed 100644
--- a/TODO
+++ b/TODO
@@ -1,5 +1,5 @@
-angrPre Release Testing:
-====================
+Pre Release Testing:
+=====================
 
 * check the version number
 
@@ -11,16 +11,36 @@ git tag -s  "${TAG}" -m "xboxdrv ${TAG}"
 git archive --format=tar --prefix="xboxdrv-linux-${VERSION}/" ${TAG} | bzip2 -c > /tmp/xboxdrv-linux-${VERSION}.tar.bz2
 
 git push --tags
+
+
+Ubuntu Package:
+===============
+
+$ cd ../debian/
+$ git-import-orig -u 0.6.1 ~/projects/xboxdrv/htdocs/xboxdrv-linux-0.6.1.tar.bz2 
+$ dch -v "0.6.1" "New Ubuntu release"
+$ git-buildpackage --git-tag --git-builder="debuild -S"
+$ sudo pbuilder --build xboxdrv_0.6.1.dsc
+$ dput my-ppa xboxdrv_0.6.1_source.changes
+
 
 Stuff to do before 0.6.1 release:
 =================================
 
+* add an --evdev debug mode that displays events
+
+* support for Playstation button names maybe? cross, triangle, circle, square, R3, L3, ...?
+
+* add more example scripts
+
+
+Stuff to do before 0.7.0 release:
+=================================
+
 * add extra checks to make sure the evdev buttons and axis given exist on the current device
 
 * add support for Xbox1 analog face button
 
-* support for Playstation button names maybe? cross, triangle, circle, square, R3, L3, ...?
-
 * unifiy guitar mappings
 
 * allow separate deadzone for each axis
diff --git a/VERSION b/VERSION
index 7ceb040..b1d7abc 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.6.1
\ No newline at end of file
+0.6.2
\ No newline at end of file
diff --git a/src/axis_event.cpp b/src/axis_event.cpp
index 1458784..b4e70b1 100644
--- a/src/axis_event.cpp
+++ b/src/axis_event.cpp
@@ -28,77 +28,75 @@
 #include "uinput.hpp"
 #include "uinput_deviceid.hpp"
 
-AxisEvent
+AxisEventPtr
 AxisEvent::invalid() 
 { 
-  AxisEvent ev;
-  ev.type = -1;
-  return ev;
+  return AxisEventPtr();
 }
 
-AxisEvent
+AxisEventPtr
 AxisEvent::create_abs(int device_id, int code, int min, int max, int fuzz, int flat)
 {
-  AxisEvent ev;
-  ev.type      = EV_ABS;
-  ev.abs.code  = UIEvent::create(device_id, EV_ABS, code);
-  ev.abs.min   = min;
-  ev.abs.max   = max;
-  ev.abs.fuzz  = fuzz;
-  ev.abs.flat  = flat;
+  AxisEventPtr ev(new AxisEvent);
+  ev->type      = EV_ABS;
+  ev->abs.code  = UIEvent::create(device_id, EV_ABS, code);
+  ev->abs.min   = min;
+  ev->abs.max   = max;
+  ev->abs.fuzz  = fuzz;
+  ev->abs.flat  = flat;
   return ev;
 }
 
-AxisEvent
+AxisEventPtr
 AxisEvent::create_rel(int device_id, int code, int repeat, float value)
 {
-  AxisEvent ev;
-  ev.type       = EV_REL;
-  ev.rel.code   = UIEvent::create(device_id, EV_REL, code);
-  ev.rel.value  = value;
-  ev.rel.repeat = repeat;
+  AxisEventPtr ev(new AxisEvent);
+  ev->type       = EV_REL;
+  ev->rel.code   = UIEvent::create(device_id, EV_REL, code);
+  ev->rel.value  = value;
+  ev->rel.repeat = repeat;
   return ev;  
 }
 
-AxisEvent
+AxisEventPtr
 AxisEvent::create_key()
 {
-  AxisEvent ev;
-  ev.type = EV_KEY;
-  std::fill_n(ev.key.up_codes,   MAX_MODIFIER+1, UIEvent::invalid());
-  std::fill_n(ev.key.down_codes, MAX_MODIFIER+1, UIEvent::invalid());
-  ev.key.threshold = 8000;
+  AxisEventPtr ev(new AxisEvent);
+  ev->type = EV_KEY;
+  std::fill_n(ev->key.up_codes,   MAX_MODIFIER+1, UIEvent::invalid());
+  std::fill_n(ev->key.down_codes, MAX_MODIFIER+1, UIEvent::invalid());
+  ev->key.threshold = 8000;
   return ev;
 }
 
-AxisEvent
+AxisEventPtr
 AxisEvent::create_rel()
 {
-  AxisEvent ev;
-  ev.type = EV_REL;
-  ev.rel.code = UIEvent::invalid();
-  ev.rel.value  = 5;
-  ev.rel.repeat = 10;
+  AxisEventPtr ev(new AxisEvent);
+  ev->type = EV_REL;
+  ev->rel.code = UIEvent::invalid();
+  ev->rel.value  = 5;
+  ev->rel.repeat = 10;
   return ev;
 }
   
-AxisEvent
+AxisEventPtr
 AxisEvent::create_abs()
 {
-  AxisEvent ev;
-  ev.type = EV_ABS;
-  ev.abs.code = UIEvent::invalid();
-  ev.abs.min  = -32768; // FIXME: this must be properly set
-  ev.abs.max  =  32767;
-  ev.abs.fuzz = 0;
-  ev.abs.flat = 0;
+  AxisEventPtr ev(new AxisEvent);
+  ev->type = EV_ABS;
+  ev->abs.code = UIEvent::invalid();
+  ev->abs.min  = -32768; // FIXME: this must be properly set
+  ev->abs.max  =  32767;
+  ev->abs.fuzz = 0;
+  ev->abs.flat = 0;
   return ev;
 }
 
-AxisEvent
+AxisEventPtr
 AxisEvent::from_string(const std::string& str)
 {
-  AxisEvent ev;
+  AxisEventPtr ev(new AxisEvent);
 
   switch (get_event_type(str))
   {
@@ -123,12 +121,12 @@ AxisEvent::from_string(const std::string& str)
       assert(!"AxisEvent::from_string(): should never be reached");
   }
 
-  //std::cout << "AxisEvent::from_string():\n  in:  " << str << "\n  out: " << ev.str() << std::endl;
+  //std::cout << "AxisEvent::from_string():\n  in:  " << str << "\n  out: " << ev->str() << std::endl;
 
   return ev;
 }
 
-AxisEvent
+AxisEventPtr
 AxisEvent::abs_from_string(const std::string& str)
 {
   boost::char_separator<char> sep(":", "", boost::keep_empty_tokens);
@@ -160,19 +158,19 @@ AxisEvent::abs_from_string(const std::string& str)
   }
   else
   {
-    AxisEvent ev = create_abs(DEVICEID_AUTO, code, -1, -1, 0, 0);
+    AxisEventPtr ev = create_abs(DEVICEID_AUTO, code, -1, -1, 0, 0);
     return ev;
   }
 }
 
-AxisEvent
+AxisEventPtr
 AxisEvent::rel_from_string(const std::string& str)
 {
   boost::char_separator<char> sep(":", "", boost::keep_empty_tokens);
   boost::tokenizer<boost::char_separator<char> > tokens(str, sep);
   typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
 
-  AxisEvent ev = create_rel();
+  AxisEventPtr ev = create_rel();
 
   int j = 0;
   for(tokenizer::iterator i = tokens.begin(); i != tokens.end(); ++i, ++j)
@@ -180,15 +178,15 @@ AxisEvent::rel_from_string(const std::string& str)
     switch(j)
     {
       case 0:
-        ev.rel.code = str2rel_event(*i);
+        ev->rel.code = str2rel_event(*i);
         break;
 
       case 1:
-        ev.rel.value = boost::lexical_cast<int>(*i); 
+        ev->rel.value = boost::lexical_cast<int>(*i); 
         break;
 
       case 2:
-        ev.rel.repeat = boost::lexical_cast<int>(*i); 
+        ev->rel.repeat = boost::lexical_cast<int>(*i); 
         break;
 
       default: 
@@ -204,14 +202,14 @@ AxisEvent::rel_from_string(const std::string& str)
   return ev;
 }
 
-AxisEvent
+AxisEventPtr
 AxisEvent::key_from_string(const std::string& str)
 {
   boost::char_separator<char> sep(":", "", boost::keep_empty_tokens);
   boost::tokenizer<boost::char_separator<char> > tokens(str, sep);
   typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
 
-  AxisEvent ev = create_key();
+  AxisEventPtr ev = create_key();
 
   int j = 0;
   for(tokenizer::iterator i = tokens.begin(); i != tokens.end(); ++i, ++j)
@@ -225,7 +223,7 @@ AxisEvent::key_from_string(const std::string& str)
           int k = 0;
           for(tokenizer::iterator m = ev_tokens.begin(); m != ev_tokens.end(); ++m, ++k)
           {
-            ev.key.up_codes[k] = str2key_event(*m);
+            ev->key.up_codes[k] = str2key_event(*m);
           }         
         }
         break;
@@ -237,13 +235,13 @@ AxisEvent::key_from_string(const std::string& str)
           int k = 0;
           for(tokenizer::iterator m = ev_tokens.begin(); m != ev_tokens.end(); ++m, ++k)
           {
-            ev.key.down_codes[k] = str2key_event(*m);
+            ev->key.down_codes[k] = str2key_event(*m);
           }         
         }
         break;
 
       case 2:
-        ev.key.threshold = boost::lexical_cast<int>(*i);
+        ev->key.threshold = boost::lexical_cast<int>(*i);
         break;
         
       default: 
@@ -264,17 +262,9 @@ AxisEvent::AxisEvent() :
 {
 }
 
-bool
-AxisEvent::is_valid() const
-{
-  return type != -1;
-}
-
 void
 AxisEvent::init(uInput& uinput) const
 {
-  assert(is_valid());
-
   switch(type)
   {
     case EV_KEY:
@@ -307,8 +297,6 @@ AxisEvent::init(uInput& uinput) const
 void
 AxisEvent::send(uInput& uinput, int old_value, int value) const
 {
-  assert(is_valid());
-
   switch(type)
   {
     case EV_ABS:
diff --git a/src/axis_event.hpp b/src/axis_event.hpp
index 7137df4..db3bdf6 100644
--- a/src/axis_event.hpp
+++ b/src/axis_event.hpp
@@ -20,44 +20,46 @@
 #define HEADER_XBOXDRV_AXIS_EVENT_HPP
 
 #include <string>
+#include <boost/shared_ptr.hpp>
 
 #include "uinput_deviceid.hpp"
 
 class uInput;
+class AxisEvent;
+
+typedef boost::shared_ptr<AxisEvent> AxisEventPtr;
 
 class AxisEvent
 {
 public:
   static const int MAX_MODIFIER = 4;
 
-  static AxisEvent invalid();
-  static AxisEvent create_abs(int device_id, int code, int min, int max, int fuzz, int flat);
-  static AxisEvent create_rel(int device_id, int code, int repeat = 10, float value = 5);
+  static AxisEventPtr invalid();
+  static AxisEventPtr create_abs(int device_id, int code, int min, int max, int fuzz, int flat);
+  static AxisEventPtr create_rel(int device_id, int code, int repeat = 10, float value = 5);
 
-  static AxisEvent create_key();
-  static AxisEvent create_rel();
-  static AxisEvent create_abs();
+  static AxisEventPtr create_key();
+  static AxisEventPtr create_rel();
+  static AxisEventPtr create_abs();
 
-  /** If an AbsAxisEvent gets created the user has to set min/max! */ 
-  static AxisEvent from_string(const std::string& str);
+  /** If an AxisEvent gets created the user has to set min/max with set_axis_range() */ 
+  static AxisEventPtr from_string(const std::string& str);
 
 private:
-  static AxisEvent abs_from_string(const std::string& str);
-  static AxisEvent rel_from_string(const std::string& str);
-  static AxisEvent key_from_string(const std::string& str);
+  static AxisEventPtr abs_from_string(const std::string& str);
+  static AxisEventPtr rel_from_string(const std::string& str);
+  static AxisEventPtr key_from_string(const std::string& str);
 
 public:
   AxisEvent();
 
+  void set_axis_range(int min, int max);
+
   void init(uInput& uinput) const;
   void send(uInput& uinput, int old_value, int value) const;
 
-  bool is_valid() const;
-
   std::string str() const;
 
-  void set_axis_range(int min, int max);
-
 private:
   /** EV_KEY, EV_ABS, EV_REL */
   int type;
diff --git a/src/axis_map.cpp b/src/axis_map.cpp
index c79fd34..a20a164 100644
--- a/src/axis_map.cpp
+++ b/src/axis_map.cpp
@@ -25,24 +25,24 @@ AxisMap::AxisMap() :
 }
 
 void
-AxisMap::bind(XboxAxis code, const AxisEvent& event)
+AxisMap::bind(XboxAxis code, AxisEventPtr event)
 {
   m_axis_map[XBOX_BTN_UNKNOWN][code] = event;
 }
 
 void
-AxisMap::bind(XboxButton shift_code, XboxAxis code, const AxisEvent& event)
+AxisMap::bind(XboxButton shift_code, XboxAxis code, AxisEventPtr event)
 {
   m_axis_map[shift_code][code] = event;
 }
 
-AxisEvent
+AxisEventPtr
 AxisMap::lookup(XboxAxis code) const
 {
   return m_axis_map[XBOX_BTN_UNKNOWN][code];
 }
 
-AxisEvent
+AxisEventPtr
 AxisMap::lookup(XboxButton shift_code, XboxAxis code) const
 {
   return m_axis_map[shift_code][code];
diff --git a/src/axis_map.hpp b/src/axis_map.hpp
index 2477e51..9f3ad71 100644
--- a/src/axis_map.hpp
+++ b/src/axis_map.hpp
@@ -27,16 +27,16 @@
 class AxisMap
 {
 private:
-  AxisEvent m_axis_map[XBOX_BTN_MAX][XBOX_AXIS_MAX];
+  AxisEventPtr m_axis_map[XBOX_BTN_MAX][XBOX_AXIS_MAX];
   
 public:
   AxisMap();
 
-  void bind(XboxAxis code, const AxisEvent& event);
-  void bind(XboxButton shift_code, XboxAxis code, const AxisEvent& event);
+  void bind(XboxAxis code, AxisEventPtr event);
+  void bind(XboxButton shift_code, XboxAxis code, AxisEventPtr event);
 
-  AxisEvent lookup(XboxAxis code) const;
-  AxisEvent lookup(XboxButton shift_code, XboxAxis code) const;
+  AxisEventPtr lookup(XboxAxis code) const;
+  AxisEventPtr lookup(XboxButton shift_code, XboxAxis code) const;
 
   void clear();
 };
diff --git a/src/button_event.cpp b/src/button_event.cpp
index 095fe61..a271791 100644
--- a/src/button_event.cpp
+++ b/src/button_event.cpp
@@ -28,58 +28,56 @@
 #include "uinput.hpp"
 #include "uinput_deviceid.hpp"
 
-ButtonEvent
+ButtonEventPtr
 ButtonEvent::invalid()
 {
-  ButtonEvent ev;
-  ev.type = -1;
-  return ev;
+  return ButtonEventPtr();
 }
 
-ButtonEvent 
+ButtonEventPtr
 ButtonEvent::create_abs(int code)
 {
-  ButtonEvent ev;
-  ev.type  = EV_ABS;
-  ev.abs.code  = UIEvent::create(DEVICEID_AUTO, EV_ABS, code);
-  ev.abs.value = 1;
+  ButtonEventPtr ev(new ButtonEvent);
+  ev->type  = EV_ABS;
+  ev->abs.code  = UIEvent::create(DEVICEID_AUTO, EV_ABS, code);
+  ev->abs.value = 1;
   return ev;
 }
 
-ButtonEvent
+ButtonEventPtr
 ButtonEvent::create_key(int code)
 {
-  ButtonEvent ev;
-  ev.type = EV_KEY;
-  std::fill_n(ev.key.codes, MAX_MODIFIER + 1, UIEvent::invalid());
-  ev.key.codes[0] = UIEvent::create(DEVICEID_AUTO, EV_KEY, code);
+  ButtonEventPtr ev(new ButtonEvent);
+  ev->type = EV_KEY;
+  std::fill_n(ev->key.codes, MAX_MODIFIER + 1, UIEvent::invalid());
+  ev->key.codes[0] = UIEvent::create(DEVICEID_AUTO, EV_KEY, code);
   return ev;
 }
 
-ButtonEvent
+ButtonEventPtr
 ButtonEvent::create_key()
 {
-  ButtonEvent ev;
-  ev.type = EV_KEY;
-  std::fill_n(ev.key.codes, MAX_MODIFIER + 1, UIEvent::invalid());
+  ButtonEventPtr ev(new ButtonEvent);
+  ev->type = EV_KEY;
+  std::fill_n(ev->key.codes, MAX_MODIFIER + 1, UIEvent::invalid());
   return ev;
 }
 
-ButtonEvent
+ButtonEventPtr
 ButtonEvent::create_rel(int code)
 {
-  ButtonEvent ev;
-  ev.type       = EV_REL;
-  ev.rel.code   = UIEvent::create(DEVICEID_AUTO, EV_REL, code);
-  ev.rel.value  = 3;
-  ev.rel.repeat = 100;
+  ButtonEventPtr ev(new ButtonEvent);
+  ev->type       = EV_REL;
+  ev->rel.code   = UIEvent::create(DEVICEID_AUTO, EV_REL, code);
+  ev->rel.value  = 3;
+  ev->rel.repeat = 100;
   return ev;
 }
 
-ButtonEvent
+ButtonEventPtr
 ButtonEvent::from_string(const std::string& str)
 {
-  ButtonEvent ev;
+  ButtonEventPtr ev;
   boost::char_separator<char> sep(":", "", boost::keep_empty_tokens);
   typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
 
@@ -99,14 +97,14 @@ ButtonEvent::from_string(const std::string& str)
           int k = 0;
           for(tokenizer::iterator m = ev_tokens.begin(); m != ev_tokens.end(); ++m, ++k)
           {
-            ev.key.codes[k] = str2key_event(*m);
+            ev->key.codes[k] = str2key_event(*m);
           }
           break;
         }
 
         case EV_REL:
           ev = ButtonEvent::create_rel(-1); // FIXME: Hack
-          ev.rel.code = str2rel_event(*i);
+          ev->rel.code = str2rel_event(*i);
           break;
 
         case EV_ABS:
@@ -125,12 +123,12 @@ ButtonEvent::from_string(const std::string& str)
     }
     else
     {
-      switch (ev.type)
+      switch (ev->type)
       {
         case EV_REL:
           switch(j) {
-            case 1: ev.rel.value  = boost::lexical_cast<int>(*i); break;
-            case 2: ev.rel.repeat = boost::lexical_cast<int>(*i); break;
+            case 1: ev->rel.value  = boost::lexical_cast<int>(*i); break;
+            case 2: ev->rel.repeat = boost::lexical_cast<int>(*i); break;
           }
           break;
 
@@ -141,7 +139,7 @@ ButtonEvent::from_string(const std::string& str)
   }
 
   if (false)
-    std::cout << "ButtonEvent::from_string():\n  in:  " << str << "\n  out: " << ev.str() << std::endl;
+    std::cout << "ButtonEvent::from_string():\n  in:  " << str << "\n  out: " << ev->str() << std::endl;
 
   return ev;
 }
diff --git a/src/button_event.hpp b/src/button_event.hpp
index 2e5c9ac..dc51df5 100644
--- a/src/button_event.hpp
+++ b/src/button_event.hpp
@@ -20,26 +20,31 @@
 #define HEADER_XBOXDRV_BUTTON_EVENT_HPP
 
 #include <string>
+#include <boost/shared_ptr.hpp>
 
 #include "uinput_deviceid.hpp"
 
 class uInput;
+class ButtonEvent;
 
-struct ButtonEvent
+typedef boost::shared_ptr<ButtonEvent> ButtonEventPtr;
+
+class ButtonEvent
 {
 public:
   static const int MAX_MODIFIER = 4;
 
-  static ButtonEvent invalid();
-  static ButtonEvent create_key(int code);
-  static ButtonEvent create_key();
-  static ButtonEvent create_abs(int code);
-  static ButtonEvent create_rel(int code);
-  static ButtonEvent from_string(const std::string& str);
+  static ButtonEventPtr invalid();
+  static ButtonEventPtr create_key(int code);
+  static ButtonEventPtr create_key();
+  static ButtonEventPtr create_abs(int code);
+  static ButtonEventPtr create_rel(int code);
+  static ButtonEventPtr from_string(const std::string& str);
 
-public:
+private:
   ButtonEvent();
-  
+
+public: 
   void init(uInput& uinput) const;
   void send(uInput& uinput, bool value) const;
 
diff --git a/src/button_map.cpp b/src/button_map.cpp
index 08e8ac7..2c46b30 100644
--- a/src/button_map.cpp
+++ b/src/button_map.cpp
@@ -24,24 +24,24 @@ ButtonMap::ButtonMap()
 }
 
 void
-ButtonMap::bind(XboxButton code, const ButtonEvent& event)
+ButtonMap::bind(XboxButton code, ButtonEventPtr event)
 {
   btn_map[XBOX_BTN_UNKNOWN][code] = event;
 }
 
 void
-ButtonMap::bind(XboxButton shift_code, XboxButton code, const ButtonEvent& event)
+ButtonMap::bind(XboxButton shift_code, XboxButton code, ButtonEventPtr event)
 {
   btn_map[shift_code][code] = event;
 }
 
-ButtonEvent
+ButtonEventPtr
 ButtonMap::lookup(XboxButton code) const
 {
   return btn_map[XBOX_BTN_UNKNOWN][code];
 }
 
-ButtonEvent
+ButtonEventPtr
 ButtonMap::lookup(XboxButton shift_code, XboxButton code) const
 {
   return btn_map[shift_code][code];
diff --git a/src/button_map.hpp b/src/button_map.hpp
index cd4eceb..5c894f0 100644
--- a/src/button_map.hpp
+++ b/src/button_map.hpp
@@ -27,16 +27,16 @@
 class ButtonMap
 {
 private:
-  ButtonEvent btn_map[XBOX_BTN_MAX][XBOX_BTN_MAX];
+  ButtonEventPtr btn_map[XBOX_BTN_MAX][XBOX_BTN_MAX];
   
 public:
   ButtonMap();
 
-  void bind(XboxButton code, const ButtonEvent& event);
-  void bind(XboxButton shift_code, XboxButton code, const ButtonEvent& event);
+  void bind(XboxButton code, ButtonEventPtr event);
+  void bind(XboxButton shift_code, XboxButton code, ButtonEventPtr event);
 
-  ButtonEvent lookup(XboxButton code) const;
-  ButtonEvent lookup(XboxButton shift_code, XboxButton code) const;
+  ButtonEventPtr lookup(XboxButton code) const;
+  ButtonEventPtr lookup(XboxButton shift_code, XboxButton code) const;
 
   void clear();
 };
diff --git a/src/command_line_options.cpp b/src/command_line_options.cpp
index 589ee48..b560320 100644
--- a/src/command_line_options.cpp
+++ b/src/command_line_options.cpp
@@ -252,7 +252,7 @@ void set_ui_button_map(ButtonMap& ui_button_map, const std::string& str)
   else
   {
     std::string btn_str = str.substr(0, i);
-    ButtonEvent event = ButtonEvent::from_string(str.substr(i+1, str.size()-i));
+    ButtonEventPtr event = ButtonEvent::from_string(str.substr(i+1, str.size()-i));
 
     std::string::size_type j = btn_str.find('+');
     if (j == std::string::npos)
@@ -753,7 +753,7 @@ CommandLineParser::print_version() const
 void
 CommandLineParser::set_ui_axismap(const std::string& name, const std::string& value)
 {
-  AxisEvent event = AxisEvent::from_string(value);
+  AxisEventPtr event = AxisEvent::from_string(value);
 
   std::string::size_type j = name.find('+');
   if (j == std::string::npos)
@@ -762,8 +762,8 @@ CommandLineParser::set_ui_axismap(const std::string& name, const std::string& va
 
     if (axis != XBOX_AXIS_UNKNOWN)
     {
-      event.set_axis_range(get_axis_min(axis),
-                           get_axis_max(axis));
+      event->set_axis_range(get_axis_min(axis),
+                            get_axis_max(axis));
 
       //std::cout << "set_ui_axismap: " << name << " = " << value << std::endl;
 
@@ -781,8 +781,8 @@ CommandLineParser::set_ui_axismap(const std::string& name, const std::string& va
 
     if (axis != XBOX_AXIS_UNKNOWN)
     {
-      event.set_axis_range(get_axis_min(axis),
-                           get_axis_max(axis));
+      event->set_axis_range(get_axis_min(axis),
+                            get_axis_max(axis));
 
       //std::cout << "set_ui_axismap: " << name << " = " << value << std::endl;
 
@@ -799,7 +799,7 @@ void
 CommandLineParser::set_ui_buttonmap(const std::string& name, const std::string& value)
 {
   std::string btn_str = name;
-  ButtonEvent event = ButtonEvent::from_string(value);
+  ButtonEventPtr event = ButtonEvent::from_string(value);
 
   std::string::size_type j = btn_str.find('+');
   if (j == std::string::npos)
diff --git a/src/uinput.cpp b/src/uinput.cpp
index 8240867..62ff64a 100644
--- a/src/uinput.cpp
+++ b/src/uinput.cpp
@@ -458,15 +458,15 @@ uInput::send_button(XboxButton code, bool value)
       {
         if (button_state[i])
         {
-          const ButtonEvent& event = cfg.get_btn_map().lookup(code, static_cast<XboxButton>(i));
-          if (event.is_valid())
+          const ButtonEventPtr& event = cfg.get_btn_map().lookup(code, static_cast<XboxButton>(i));
+          if (event->is_valid())
           {
             for(int j = 0; j < XBOX_BTN_MAX; ++j) // iterate over all shift buttons
             {
-              const ButtonEvent& event2 = cfg.get_btn_map().lookup(static_cast<XboxButton>(j),
+              const ButtonEventPtr& event2 = cfg.get_btn_map().lookup(static_cast<XboxButton>(j),
                                                                    static_cast<XboxButton>(i));
-              if (event2.is_valid())
-                event2.send(*this, false);
+              if (event2->is_valid())
+                event2->send(*this, false);
             }
           }
         }
@@ -477,10 +477,10 @@ uInput::send_button(XboxButton code, bool value)
       {
         if (button_state[i]) // shift button is pressed
         {
-          const ButtonEvent& event = cfg.get_btn_map().lookup(static_cast<XboxButton>(i), code);
-          if (event.is_valid())
+          const ButtonEventPtr& event = cfg.get_btn_map().lookup(static_cast<XboxButton>(i), code);
+          if (event->is_valid())
           {
-            event.send(*this, value);
+            event->send(*this, value);
             // exit after the first successful event, so we don't send
             // multiple events for the same button
             return;
@@ -489,9 +489,9 @@ uInput::send_button(XboxButton code, bool value)
       }
 
       // Non shifted button events
-      const ButtonEvent& event = cfg.get_btn_map().lookup(code);
-      if (event.is_valid())
-        event.send(*this, value);
+      const ButtonEventPtr& event = cfg.get_btn_map().lookup(code);
+      if (event->is_valid())
+        event->send(*this, value);
     }
   }
 }
@@ -587,10 +587,10 @@ uInput::send_axis(XboxAxis code, int32_t value)
     {    
       if (button_state[shift])
       {
-        const AxisEvent& event = cfg.get_axis_map().lookup(static_cast<XboxButton>(shift), code);
-        if (event.is_valid())
+        const AxisEventPtr& event = cfg.get_axis_map().lookup(static_cast<XboxButton>(shift), code);
+        if (event)
         {
-          event.send(*this, old_value, value);
+          event->send(*this, old_value, value);
           event_send = true;
         }
       }
@@ -599,10 +599,10 @@ uInput::send_axis(XboxAxis code, int32_t value)
     // sending regular axis, if no shifted events where send
     if (!event_send)
     {
-      const AxisEvent& event = cfg.get_axis_map().lookup(code);
-      if (event.is_valid())
+      const AxisEventPtr& event = cfg.get_axis_map().lookup(code);
+      if (event)
       {
-        event.send(*this, old_value, value);
+        event->send(*this, old_value, value);
       }
     }
   }
@@ -615,9 +615,9 @@ uInput::add_axis(XboxAxis code)
   {
     for(int shift = 0; shift < XBOX_BTN_MAX; ++shift)
     {
-      const AxisEvent& event = cfg.get_axis_map(n).lookup(static_cast<XboxButton>(shift), code);
-      if (event.is_valid())
-        event.init(*this);
+      const AxisEventPtr& event = cfg.get_axis_map(n).lookup(static_cast<XboxButton>(shift), code);
+      if (event)
+        event->init(*this);
     }
   }
 }
@@ -629,9 +629,9 @@ uInput::add_button(XboxButton code)
   {
     for(int i = 0; i < XBOX_BTN_MAX; ++i)
     {
-      const ButtonEvent& event = cfg.get_btn_map(n).lookup(static_cast<XboxButton>(i), code);
-      if (event.is_valid())
-        event.init(*this);
+      const ButtonEventPtr& event = cfg.get_btn_map(n).lookup(static_cast<XboxButton>(i), code);
+      if (event->is_valid())
+        event->init(*this);
     }
   }
 }