]> git.tdb.fi Git - libs/gui.git/commitdiff
Add a game controller input device
authorMikko Rasa <tdb@tdb.fi>
Thu, 11 Sep 2014 09:37:22 +0000 (12:37 +0300)
committerMikko Rasa <tdb@tdb.fi>
Thu, 11 Sep 2014 09:37:22 +0000 (12:37 +0300)
Currently only implemented for Linux.

Build
source/input/gamecontroller.h [new file with mode: 0644]
source/input/linux/gamecontroller.cpp [new file with mode: 0644]
source/input/linux/gamecontroller_platform.h [new file with mode: 0644]

diff --git a/Build b/Build
index 7972020fb1fd0471b8ea771eeaa6c566cef3025f..5ff4f7844ad9a6221db355ebefe59a02bb947fdc 100644 (file)
--- a/Build
+++ b/Build
@@ -104,6 +104,10 @@ package "mspgui"
                {
                        source "source/graphics/devil";
                };
+               if_arch "linux"
+               {
+                       overlay "linux";
+               };
                if_arch "windows"
                {
                        overlay "windows";
diff --git a/source/input/gamecontroller.h b/source/input/gamecontroller.h
new file mode 100644 (file)
index 0000000..9ebacee
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef GAMECONTROLLER_H_
+#define GAMECONTROLLER_H_
+
+#include "device.h"
+
+namespace Msp {
+namespace Input {
+
+class GameController: public Device
+{
+private:
+       struct Private;
+
+       Private *priv;
+
+public:
+       GameController(unsigned);
+       virtual ~GameController();
+
+       void tick();
+};
+
+} // namespace Input
+} // namespace Msp
+
+#endif
diff --git a/source/input/linux/gamecontroller.cpp b/source/input/linux/gamecontroller.cpp
new file mode 100644 (file)
index 0000000..bf69049
--- /dev/null
@@ -0,0 +1,80 @@
+#include <fcntl.h>
+#include <linux/joystick.h>
+#include <msp/core/systemerror.h>
+#include <msp/io/handle_private.h>
+#include <msp/strings/format.h>
+#include "gamecontroller.h"
+#include "gamecontroller_platform.h"
+
+using namespace std;
+
+namespace Msp {
+namespace Input {
+
+GameController::GameController(unsigned index):
+       priv(new Private)
+{
+       priv->dev = new JsDevice(format("/dev/input/js%d", index));
+       name = priv->dev->get_name();
+       tick();
+}
+
+GameController::~GameController()
+{
+       delete priv->dev;
+       delete priv;
+}
+
+void GameController::tick()
+{
+       js_event events[16];
+       while(1)
+       {
+               unsigned len = priv->dev->read(reinterpret_cast<char *>(events), sizeof(events));
+
+               unsigned count = len/sizeof(js_event);
+               for(unsigned i=0; i<count; ++i)
+               {
+                       unsigned type = events[i].type&0x7F;
+                       bool init = events[i].type&JS_EVENT_INIT;
+                       if(type==JS_EVENT_AXIS)
+                               set_axis_value(events[i].number, events[i].value/32768.0f, !init);
+                       else if(type==JS_EVENT_BUTTON)
+                               set_button_state(events[i].number, events[i].value, !init);
+               }
+
+               if(len<sizeof(events))
+                       break;
+       }
+}
+
+
+JsDevice::JsDevice(const string &fn)
+{
+       mode = IO::M_READ;
+       *handle = open(fn.c_str(), O_RDONLY|O_NONBLOCK);
+       if(!handle)
+               throw system_error(format("open(%s)", fn));
+}
+
+string JsDevice::get_name() const
+{
+       char buf[128];
+       int ret = ioctl(*handle, JSIOCGNAME(sizeof(buf)), buf);
+       if(ret<0)
+               throw system_error("ioctl(JSIOCGNAME)");
+       return buf;
+}
+
+unsigned JsDevice::do_read(char *buf, unsigned size)
+{
+       return IO::sys_read(handle, buf, size);
+}
+
+unsigned JsDevice::do_write(const char *, unsigned)
+{
+       throw IO::invalid_access(IO::M_WRITE);
+}
+
+} // namespace Input
+} // namespace Msp
diff --git a/source/input/linux/gamecontroller_platform.h b/source/input/linux/gamecontroller_platform.h
new file mode 100644 (file)
index 0000000..61bcdb5
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef GAMECONTROLLER_PRIVATE_H_
+#define GAMECONTROLLER_PRIVATE_H_
+
+#include <msp/io/eventobject.h>
+#include <msp/io/handle.h>
+
+namespace Msp {
+namespace Input {
+
+class JsDevice: public IO::EventObject
+{
+private:
+       IO::Handle handle;
+
+public:
+       JsDevice(const std::string &);
+
+       std::string get_name() const;
+
+protected:
+       virtual unsigned do_read(char *, unsigned);
+       virtual unsigned do_write(const char *, unsigned);
+
+public:
+       virtual const IO::Handle &get_event_handle() { return handle; }
+};
+
+
+struct GameController::Private
+{
+       JsDevice *dev;
+};
+
+} // namespace Input
+} // namespace Msp
+
+#endif