From 99b2b4b57cf8ef9a04e5c3b46a5196ad103b8e5d Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Sun, 24 May 2015 19:44:28 +1000 Subject: [PATCH] Update to v094r21 release. byuu says: This updates ruby to return shared_pointer objects instead of HID::Device* objects. It also fixes an ID bug where joypads were starting at ID# 2+, but mice were also set to ID# 2. I also revised nall/hid a lot, with getters and setters instead of stabbing at internal state. I didn't yet patch nall::string to safely consume nullptr const char* values, though. --- emulator/emulator.hpp | 2 +- nall/hid.hpp | 182 +++++++++++++--------------- ruby/implementation.cpp | 26 ++-- ruby/input.hpp | 34 +++--- ruby/input/joypad/sdl.cpp | 39 +++--- ruby/input/keyboard/xlib.cpp | 24 ++-- ruby/input/mouse/xlib.cpp | 44 +++---- ruby/input/sdl.cpp | 28 ++--- ruby/input/xlib.cpp | 26 ++-- ruby/ruby.cpp | 51 ++++---- ruby/ruby.hpp | 45 ++++--- target-tomoko/GNUmakefile | 10 +- target-tomoko/input/input.cpp | 50 ++++---- target-tomoko/input/input.hpp | 14 +-- target-tomoko/settings/hotkeys.cpp | 4 +- target-tomoko/settings/input.cpp | 8 +- target-tomoko/settings/settings.hpp | 4 +- 17 files changed, 289 insertions(+), 302 deletions(-) diff --git a/emulator/emulator.hpp b/emulator/emulator.hpp index 5a36ffb5..954581aa 100644 --- a/emulator/emulator.hpp +++ b/emulator/emulator.hpp @@ -3,7 +3,7 @@ namespace Emulator { static const char Name[] = "higan"; - static const char Version[] = "094.20"; + static const char Version[] = "094.21"; static const char Author[] = "byuu"; static const char License[] = "GPLv3"; static const char Website[] = "http://byuu.org/"; diff --git a/nall/hid.hpp b/nall/hid.hpp index 77e67060..41a73be6 100644 --- a/nall/hid.hpp +++ b/nall/hid.hpp @@ -1,120 +1,110 @@ #ifndef NALL_HID_HPP #define NALL_HID_HPP -namespace nall { +namespace nall { namespace HID { -namespace HID { - struct Input { - string name; - int16_t value = 0; +struct Input { + Input(const string& name) : _name(name) {} - Input() {} - Input(const string& name) : name(name) {} - }; + auto name() const -> string { return _name; } + auto value() const -> int16_t { return _value; } + auto setValue(int16_t value) -> void { _value = value; } - struct Group { - string name; - vector input; +private: + string _name; + int16_t _value = 0; + friend class Group; +}; - Group() {} - Group(const string& name) : name(name) {} +struct Group : vector { + Group(const string& name) : _name(name) {} - void append(const string& name) { - input.append({name}); + auto name() const -> string { return _name; } + auto input(unsigned id) -> Input& { return operator[](id); } + auto append(const string& name) -> void { vector::append({name}); } + + auto find(const string& name) const -> maybe { + for(auto id : range(size())) { + if(operator[](id)._name == name) return id; } + return nothing; + } - maybe find(const string& name) { - for(unsigned id = 0; id < input.size(); id++) { - if(input[id].name == name) return id; - } - return nothing; +private: + string _name; + friend class Device; +}; + +struct Device : vector { + Device(const string& name) : _name(name) {} + + auto pathID() const -> uint32_t { return (uint32_t)(_id >> 32); } + auto deviceID() const -> uint32_t { return (uint32_t)(_id >> 0); } + auto vendorID() const -> uint16_t { return (uint16_t)(_id >> 16); } + auto productID() const -> uint16_t { return (uint16_t)(_id >> 0); } + + virtual auto isNull() const -> bool { return false; } + virtual auto isKeyboard() const -> bool { return false; } + virtual auto isMouse() const -> bool { return false; } + virtual auto isJoypad() const -> bool { return false; } + + auto name() const -> string { return _name; } + auto id() const -> uint64_t { return _id; } + auto setID(uint64_t id) -> void { _id = id; } + auto group(unsigned id) -> Group& { return operator[](id); } + auto append(const string& name) -> void { vector::append({name}); } + + auto find(const string& name) const -> maybe { + for(auto id : range(size())) { + if(operator[](id)._name == name) return id; } - }; + return nothing; + } - struct Device { - uint64_t id = 0; - string name; - vector group; +private: + string _name; + uint64_t _id = 0; +}; - uint32_t pathID() const { return (uint32_t)(id >> 32); } - uint32_t deviceID() const { return (uint32_t)(id >> 0); } - uint16_t vendorID() const { return (uint16_t)(id >> 16); } - uint16_t productID() const { return (uint16_t)(id >> 0); } +struct Null : Device { + Null() : Device("Null") {} + auto isNull() const -> bool { return true; } +}; - virtual bool isNull() const { return false; } - virtual bool isKeyboard() const { return false; } - virtual bool isMouse() const { return false; } - virtual bool isJoypad() const { return false; } +struct Keyboard : Device { + enum GroupID : unsigned { Button }; - void append(const string& name) { - group.append({name}); - } + Keyboard() : Device("Keyboard") { append("Button"); } + auto isKeyboard() const -> bool { return true; } + auto buttons() -> Group& { return group(GroupID::Button); } +}; - maybe find(const string& name) { - for(unsigned id = 0; id < group.size(); id++) { - if(group[id].name == name) return id; - } - return nothing; - } - }; +struct Mouse : Device { + enum GroupID : unsigned { Axis, Button }; - struct Null : Device { - Null() { - name = "Null"; - } + Mouse() : Device("Mouse") { append("Axis"), append("Button"); } + auto isMouse() const -> bool { return true; } + auto axes() -> Group& { return group(GroupID::Axis); } + auto buttons() -> Group& { return group(GroupID::Button); } +}; - bool isNull() const { return true; } - }; +struct Joypad : Device { + enum GroupID : unsigned { Axis, Hat, Trigger, Button }; - struct Keyboard : Device { - enum GroupID : unsigned { Button }; + Joypad() : Device("Joypad") { append("Axis"), append("Hat"), append("Trigger"), append("Button"); } + auto isJoypad() const -> bool { return true; } + auto axes() -> Group& { return group(GroupID::Axis); } + auto hats() -> Group& { return group(GroupID::Hat); } + auto triggers() -> Group& { return group(GroupID::Trigger); } + auto buttons() -> Group& { return group(GroupID::Button); } - Group& button() { return group[GroupID::Button]; } + auto rumble() const -> bool { return _rumble; } + auto setRumble(bool rumble) -> void { _rumble = rumble; } - Keyboard() { - name = "Keyboard"; - append("Button"); - } +private: + bool _rumble = false; +}; - bool isKeyboard() const { return true; } - }; - - struct Mouse : Device { - enum GroupID : unsigned { Axis, Button }; - - Group& axis() { return group[GroupID::Axis]; } - Group& button() { return group[GroupID::Button]; } - - Mouse() { - name = "Mouse"; - append("Axis"); - append("Button"); - } - - bool isMouse() const { return true; } - }; - - struct Joypad : Device { - enum GroupID : unsigned { Axis, Hat, Trigger, Button }; - - Group& axis() { return group[GroupID::Axis]; } - Group& hat() { return group[GroupID::Hat]; } - Group& trigger() { return group[GroupID::Trigger]; } - Group& button() { return group[GroupID::Button]; } - bool rumble = false; - - Joypad() { - name = "Joypad"; - append("Axis"); - append("Hat"); - append("Trigger"); - append("Button"); - } - - bool isJoypad() const { return true; } - }; -} - -} +}} #endif diff --git a/ruby/implementation.cpp b/ruby/implementation.cpp index 4672b936..b4313b9a 100644 --- a/ruby/implementation.cpp +++ b/ruby/implementation.cpp @@ -130,21 +130,21 @@ using namespace nall; #define DeclareInput(Name) \ struct Input##Name : Input { \ - bool cap(const string& name) { return p.cap(name); } \ - any get(const string& name) { return p.get(name); } \ - bool set(const string& name, const any& value) { return p.set(name, value); } \ - \ - bool acquire() { return p.acquire(); } \ - bool unacquire() { return p.unacquire(); } \ - bool acquired() { return p.acquired(); } \ - \ - vector poll() { return p.poll(); } \ - bool rumble(uint64_t id, bool enable) { return p.rumble(id, enable); } \ - bool init() { return p.init(); } \ - void term() { p.term(); } \ - \ Input##Name() : p(*new pInput##Name) {} \ ~Input##Name() { delete &p; } \ + \ + auto cap(const string& name) -> bool { return p.cap(name); } \ + auto get(const string& name) -> any { return p.get(name); } \ + auto set(const string& name, const any& value) -> bool { return p.set(name, value); } \ + \ + auto acquire() -> bool { return p.acquire(); } \ + auto unacquire() -> bool { return p.unacquire(); } \ + auto acquired() -> bool { return p.acquired(); } \ + \ + auto poll() -> vector> { return p.poll(); } \ + auto rumble(uint64_t id, bool enable) -> bool { return p.rumble(id, enable); } \ + auto init() -> bool { return p.init(); } \ + auto term() -> void { p.term(); } \ \ private: \ pInput##Name& p; \ diff --git a/ruby/input.hpp b/ruby/input.hpp index e36043a6..c3d032dd 100644 --- a/ruby/input.hpp +++ b/ruby/input.hpp @@ -1,23 +1,23 @@ struct Input { - static const char* Handle; - static const char* KeyboardSupport; - static const char* MouseSupport; - static const char* JoypadSupport; - static const char* JoypadRumbleSupport; + static const nall::string Handle; + static const nall::string KeyboardSupport; + static const nall::string MouseSupport; + static const nall::string JoypadSupport; + static const nall::string JoypadRumbleSupport; - virtual bool cap(const nall::string& name) { return false; } - virtual nall::any get(const nall::string& name) { return false; } - virtual bool set(const nall::string& name, const nall::any& value) { return false; } + Input() = default; + virtual ~Input() = default; - virtual bool acquire() { return false; } - virtual bool unacquire() { return false; } - virtual bool acquired() { return false; } + virtual auto cap(const nall::string& name) -> bool { return false; } + virtual auto get(const nall::string& name) -> nall::any { return false; } + virtual auto set(const nall::string& name, const nall::any& value) -> bool { return false; } - virtual nall::vector poll() { return {}; } - virtual bool rumble(uint64_t id, bool enable) { return false; } - virtual bool init() { return true; } - virtual void term() {} + virtual auto acquire() -> bool { return false; } + virtual auto unacquire() -> bool { return false; } + virtual auto acquired() -> bool { return false; } - Input() {} - virtual ~Input() {} + virtual auto poll() -> nall::vector> { return {}; } + virtual auto rumble(uint64_t id, bool enable) -> bool { return false; } + virtual auto init() -> bool { return true; } + virtual auto term() -> void {} }; diff --git a/ruby/input/joypad/sdl.cpp b/ruby/input/joypad/sdl.cpp index fbe1d89f..887358de 100644 --- a/ruby/input/joypad/sdl.cpp +++ b/ruby/input/joypad/sdl.cpp @@ -5,48 +5,47 @@ namespace ruby { struct InputJoypadSDL { struct Joypad { - HID::Joypad hid; + shared_pointer hid{new HID::Joypad}; unsigned id = 0; SDL_Joystick* handle = nullptr; }; vector joypads; - void assign(HID::Joypad& hid, unsigned groupID, unsigned inputID, int16_t value) { - auto& group = hid.group[groupID]; - if(group.input[inputID].value == value) return; - if(input.onChange) input.onChange(hid, groupID, inputID, group.input[inputID].value, value); - group.input[inputID].value = value; + auto assign(shared_pointer hid, unsigned groupID, unsigned inputID, int16_t value) -> void { + auto& group = hid->group(groupID); + if(group.input(inputID).value() == value) return; + if(input.onChange) input.onChange(hid, groupID, inputID, group.input(inputID).value(), value); + group.input(inputID).setValue(value); } - void poll(vector& devices) { + auto poll(vector>& devices) -> void { SDL_JoystickUpdate(); for(auto& jp : joypads) { - for(unsigned n = 0; n < jp.hid.axis().input.size(); n++) { + for(auto n : range(jp.hid->axes())) { assign(jp.hid, HID::Joypad::GroupID::Axis, n, (int16_t)SDL_JoystickGetAxis(jp.handle, n)); } - for(signed n = 0; n < (signed)jp.hid.hat().input.size() - 1; n += 2) { + for(signed n = 0; n < (signed)jp.hid->hats().size() - 1; n += 2) { uint8_t state = SDL_JoystickGetHat(jp.handle, n >> 1); assign(jp.hid, HID::Joypad::GroupID::Hat, n + 0, state & SDL_HAT_LEFT ? -32768 : state & SDL_HAT_RIGHT ? +32767 : 0); assign(jp.hid, HID::Joypad::GroupID::Hat, n + 1, state & SDL_HAT_UP ? -32768 : state & SDL_HAT_DOWN ? +32767 : 0); } - for(unsigned n = 0; n < jp.hid.button().input.size(); n++) { + for(auto n : range(jp.hid->buttons())) { assign(jp.hid, HID::Joypad::GroupID::Button, n, (bool)SDL_JoystickGetButton(jp.handle, n)); } - devices.append(&jp.hid); + devices.append(jp.hid); } } - bool init() { + auto init() -> bool { SDL_InitSubSystem(SDL_INIT_JOYSTICK); SDL_JoystickEventState(SDL_IGNORE); - unsigned joypadCount = SDL_NumJoysticks(); - for(unsigned id = 0; id < joypadCount; id++) { + for(auto id : range(SDL_NumJoysticks())) { Joypad jp; jp.id = id; jp.handle = SDL_JoystickOpen(id); @@ -55,11 +54,11 @@ struct InputJoypadSDL { unsigned hats = SDL_JoystickNumHats(jp.handle) * 2; unsigned buttons = 32; //there is no SDL_JoystickNumButtons() - jp.hid.id = 2 + jp.id; - for(unsigned n = 0; n < axes; n++) jp.hid.axis().append({n}); - for(unsigned n = 0; n < hats; n++) jp.hid.hat().append({n}); - for(unsigned n = 0; n < buttons; n++) jp.hid.button().append({n}); - jp.hid.rumble = false; + jp.hid->setID(3 + jp.id); + for(auto n : range(axes)) jp.hid->axes().append(n); + for(auto n : range(hats)) jp.hid->hats().append(n); + for(auto n : range(buttons)) jp.hid->buttons().append(n); + jp.hid->setRumble(false); joypads.append(jp); } @@ -67,7 +66,7 @@ struct InputJoypadSDL { return true; } - void term() { + auto term() -> void { for(auto& jp : joypads) { SDL_JoystickClose(jp.handle); } diff --git a/ruby/input/keyboard/xlib.cpp b/ruby/input/keyboard/xlib.cpp index 002e57ea..9a156d57 100644 --- a/ruby/input/keyboard/xlib.cpp +++ b/ruby/input/keyboard/xlib.cpp @@ -4,7 +4,7 @@ namespace ruby { struct InputKeyboardXlib { - HID::Keyboard hid; + shared_pointer hid{new HID::Keyboard}; Display* display = nullptr; @@ -15,14 +15,14 @@ struct InputKeyboardXlib { }; vector keys; - void assign(unsigned inputID, bool value) { - auto& group = hid.group[HID::Keyboard::GroupID::Button]; - if(group.input[inputID].value == value) return; - if(input.onChange) input.onChange(hid, HID::Keyboard::GroupID::Button, inputID, group.input[inputID].value, value); - group.input[inputID].value = value; + auto assign(unsigned inputID, bool value) -> void { + auto& group = hid->buttons(); + if(group.input(inputID).value() == value) return; + if(input.onChange) input.onChange(hid, HID::Keyboard::GroupID::Button, inputID, group.input(inputID).value(), value); + group.input(inputID).setValue(value); } - void poll(vector& devices) { + auto poll(vector>& devices) -> void { char state[32]; XQueryKeymap(display, state); @@ -31,10 +31,10 @@ struct InputKeyboardXlib { assign(n, value); } - devices.append(&hid); + devices.append(hid); } - bool init() { + auto init() -> bool { display = XOpenDisplay(0); keys.append({"Escape", XK_Escape}); @@ -151,17 +151,17 @@ struct InputKeyboardXlib { keys.append({"RightSuper", XK_Super_R}); keys.append({"Menu", XK_Menu}); - hid.id = 1; + hid->setID(1); for(unsigned n = 0; n < keys.size(); n++) { - hid.button().append(keys[n].name); + hid->buttons().append(keys[n].name); keys[n].keycode = XKeysymToKeycode(display, keys[n].keysym); } return true; } - void term() { + auto term() -> void { if(display) { XCloseDisplay(display); display = nullptr; diff --git a/ruby/input/mouse/xlib.cpp b/ruby/input/mouse/xlib.cpp index 2def3a3f..b4ee12e7 100644 --- a/ruby/input/mouse/xlib.cpp +++ b/ruby/input/mouse/xlib.cpp @@ -4,7 +4,7 @@ namespace ruby { struct InputMouseXlib { - HID::Mouse hid; + shared_pointer hid{new HID::Mouse}; uintptr_t handle = 0; @@ -23,7 +23,7 @@ struct InputMouseXlib { unsigned relativeY = 0; } ms; - bool acquire() { + auto acquire() -> bool { if(acquired()) return true; if(XGrabPointer(display, handle, True, 0, GrabModeAsync, GrabModeAsync, rootWindow, invisibleCursor, CurrentTime) == GrabSuccess) { @@ -42,7 +42,7 @@ struct InputMouseXlib { } } - bool unacquire() { + auto unacquire() -> bool { if(acquired()) { //restore cursor acceleration and release cursor XChangePointerControl(display, True, True, ms.numerator, ms.denominator, ms.threshold); @@ -52,18 +52,18 @@ struct InputMouseXlib { return true; } - bool acquired() { + auto acquired() -> bool { return ms.acquired; } - void assign(unsigned groupID, unsigned inputID, int16_t value) { - auto& group = hid.group[groupID]; - if(group.input[inputID].value == value) return; - if(input.onChange) input.onChange(hid, groupID, inputID, group.input[inputID].value, value); - group.input[inputID].value = value; + auto assign(unsigned groupID, unsigned inputID, int16_t value) -> void { + auto& group = hid->group(groupID); + if(group.input(inputID).value() == value) return; + if(input.onChange) input.onChange(hid, groupID, inputID, group.input(inputID).value(), value); + group.input(inputID).setValue(value); } - void poll(vector& devices) { + auto poll(vector>& devices) -> void { Window rootReturn; Window childReturn; signed rootXReturn = 0; @@ -81,7 +81,7 @@ struct InputMouseXlib { assign(HID::Mouse::GroupID::Axis, 0, (int16_t)(rootXReturn - screenWidth / 2)); assign(HID::Mouse::GroupID::Axis, 1, (int16_t)(rootYReturn - screenHeight / 2)); - if(hid.axis().input[0].value != 0 || hid.axis().input[1].value != 0) { + if(hid->axes().input(0).value() != 0 || hid->axes().input(1).value() != 0) { //if mouse moved, re-center mouse for next poll XWarpPointer(display, None, rootWindow, 0, 0, 0, 0, screenWidth / 2, screenHeight / 2); } @@ -99,10 +99,10 @@ struct InputMouseXlib { assign(HID::Mouse::GroupID::Button, 3, (bool)(maskReturn & Button4Mask)); assign(HID::Mouse::GroupID::Button, 4, (bool)(maskReturn & Button5Mask)); - devices.append(&hid); + devices.append(hid); } - bool init(uintptr_t handle) { + auto init(uintptr_t handle) -> bool { this->handle = handle; display = XOpenDisplay(0); rootWindow = DefaultRootWindow(display); @@ -128,21 +128,21 @@ struct InputMouseXlib { ms.relativeX = 0; ms.relativeY = 0; - hid.id = 2; + hid->setID(2); - hid.axis().append({"X"}); - hid.axis().append({"Y"}); + hid->axes().append("X"); + hid->axes().append("Y"); - hid.button().append({"Left"}); - hid.button().append({"Middle"}); - hid.button().append({"Right"}); - hid.button().append({"Up"}); - hid.button().append({"Down"}); + hid->buttons().append("Left"); + hid->buttons().append("Middle"); + hid->buttons().append("Right"); + hid->buttons().append("Up"); + hid->buttons().append("Down"); return true; } - void term() { + auto term() -> void { unacquire(); XFreeCursor(display, invisibleCursor); XCloseDisplay(display); diff --git a/ruby/input/sdl.cpp b/ruby/input/sdl.cpp index 3a6ff339..fad9af53 100644 --- a/ruby/input/sdl.cpp +++ b/ruby/input/sdl.cpp @@ -17,7 +17,7 @@ struct pInputSDL { uintptr_t handle = 0; } settings; - bool cap(const string& name) { + auto cap(const string& name) -> bool { if(name == Input::Handle) return true; if(name == Input::KeyboardSupport) return true; if(name == Input::MouseSupport) return true; @@ -25,12 +25,12 @@ struct pInputSDL { return false; } - any get(const string& name) { + auto get(const string& name) -> any { if(name == Input::Handle) return (uintptr_t)settings.handle; return false; } - bool set(const string& name, const any &value) { + auto set(const string& name, const any& value) -> bool { if(name == Input::Handle) { settings.handle = any_cast(value); return true; @@ -39,38 +39,38 @@ struct pInputSDL { return false; } - bool acquire() { + auto acquire() -> bool { return xlibMouse.acquire(); } - bool unacquire() { + auto unacquire() -> bool { return xlibMouse.unacquire(); } - bool acquired() { + auto acquired() -> bool { return xlibMouse.acquired(); } - vector poll() { - vector devices; + auto poll() -> vector> { + vector> devices; xlibKeyboard.poll(devices); xlibMouse.poll(devices); sdl.poll(devices); return devices; } - bool rumble(uint64_t id, bool enable) { + auto rumble(uint64_t id, bool enable) -> bool { return false; } - bool init() { - if(xlibKeyboard.init() == false) return false; - if(xlibMouse.init(settings.handle) == false) return false; - if(sdl.init() == false) return false; + auto init() -> bool { + if(!xlibKeyboard.init()) return false; + if(!xlibMouse.init(settings.handle)) return false; + if(!sdl.init()) return false; return true; } - void term() { + auto term() -> void { xlibKeyboard.term(); xlibMouse.term(); sdl.term(); diff --git a/ruby/input/xlib.cpp b/ruby/input/xlib.cpp index 8c37d4a0..607ac351 100644 --- a/ruby/input/xlib.cpp +++ b/ruby/input/xlib.cpp @@ -17,18 +17,18 @@ struct pInputXlib { uintptr_t handle = 0; } settings; - bool cap(const string& name) { + auto cap(const string& name) -> bool { if(name == Input::KeyboardSupport) return true; if(name == Input::MouseSupport) return true; return false; } - any get(const string& name) { + auto get(const string& name) -> any { if(name == Input::Handle) return (uintptr_t)settings.handle; return false; } - bool set(const string& name, const any &value) { + auto set(const string& name, const any& value) -> bool { if(name == Input::Handle) { settings.handle = any_cast(value); return true; @@ -37,36 +37,36 @@ struct pInputXlib { return false; } - bool acquire() { + auto acquire() -> bool { return xlibMouse.acquire(); } - bool unacquire() { + auto unacquire() -> bool { return xlibMouse.unacquire(); } - bool acquired() { + auto acquired() -> bool { return xlibMouse.acquired(); } - vector poll() { - vector devices; + auto poll() -> vector> { + vector> devices; xlibKeyboard.poll(devices); xlibMouse.poll(devices); return devices; } - bool rumble(uint64_t id, bool enable) { + auto rumble(uint64_t id, bool enable) -> bool { return false; } - bool init() { - if(xlibKeyboard.init() == false) return false; - if(xlibMouse.init(settings.handle) == false) return false; + auto init() -> bool { + if(!xlibKeyboard.init()) return false; + if(!xlibMouse.init(settings.handle)) return false; return true; } - void term() { + auto term() -> void { xlibKeyboard.term(); xlibMouse.term(); } diff --git a/ruby/ruby.cpp b/ruby/ruby.cpp index 5e03ebfb..b06a1ddd 100644 --- a/ruby/ruby.cpp +++ b/ruby/ruby.cpp @@ -363,43 +363,43 @@ AudioInterface::~AudioInterface() { term(); } /* InputInterface */ -const char* Input::Handle = "Handle"; -const char* Input::KeyboardSupport = "KeyboardSupport"; -const char* Input::MouseSupport = "MouseSupport"; -const char* Input::JoypadSupport = "JoypadSupport"; -const char* Input::JoypadRumbleSupport = "JoypadRumbleSupport"; +const string Input::Handle = "Handle"; +const string Input::KeyboardSupport = "KeyboardSupport"; +const string Input::MouseSupport = "MouseSupport"; +const string Input::JoypadSupport = "JoypadSupport"; +const string Input::JoypadRumbleSupport = "JoypadRumbleSupport"; -void InputInterface::driver(const char* driver) { +auto InputInterface::driver(string driver) -> void { if(p) term(); - if(!driver || !*driver) driver = optimalDriver(); + if(!driver) driver = optimalDriver(); if(0); #ifdef INPUT_WINDOWS - else if(!strcmp(driver, "Windows")) p = new InputWindows(); + else if(driver == "Windows") p = new InputWindows(); #endif #ifdef INPUT_CARBON - else if(!strcmp(driver, "Carbon")) p = new InputCarbon(); + else if(driver == "Carbon") p = new InputCarbon(); #endif #ifdef INPUT_UDEV - else if(!strcmp(driver, "udev")) p = new InputUdev(); + else if(driver == "udev") p = new InputUdev(); #endif #ifdef INPUT_SDL - else if(!strcmp(driver, "SDL")) p = new InputSDL(); + else if(driver == "SDL") p = new InputSDL(); #endif #ifdef INPUT_XLIB - else if(!strcmp(driver, "Xlib")) p = new InputXlib(); + else if(driver == "Xlib") p = new InputXlib(); #endif else p = new Input(); } -const char* InputInterface::optimalDriver() { +auto InputInterface::optimalDriver() -> string { #if defined(INPUT_WINDOWS) return "Windows"; @@ -418,7 +418,7 @@ const char* InputInterface::optimalDriver() { #endif } -const char* InputInterface::safestDriver() { +auto InputInterface::safestDriver() -> string { #if defined(INPUT_WINDOWS) return "Windows"; @@ -437,7 +437,7 @@ const char* InputInterface::safestDriver() { #endif } -const char* InputInterface::availableDrivers() { +auto InputInterface::availableDrivers() -> string { return //Windows @@ -469,12 +469,12 @@ const char* InputInterface::availableDrivers() { "None"; } -bool InputInterface::init() { +auto InputInterface::init() -> bool { if(!p) driver(); return p->init(); } -void InputInterface::term() { +auto InputInterface::term() -> void { if(p) { p->term(); delete p; @@ -482,15 +482,14 @@ void InputInterface::term() { } } -bool InputInterface::cap(const string& name) { return p ? p->cap(name) : false; } -any InputInterface::get(const string& name) { return p ? p->get(name) : false; } -bool InputInterface::set(const string& name, const any& value) { return p ? p->set(name, value) : false; } -bool InputInterface::acquire() { return p ? p->acquire() : false; } -bool InputInterface::unacquire() { return p ? p->unacquire() : false; } -bool InputInterface::acquired() { return p ? p->acquired() : false; } -vector InputInterface::poll() { return p ? p->poll() : vector(); } -bool InputInterface::rumble(uint64_t id, bool enable) { return p ? p->rumble(id, enable) : false; } -InputInterface::InputInterface() : p(nullptr) {} InputInterface::~InputInterface() { term(); } +auto InputInterface::cap(const string& name) -> bool { return p ? p->cap(name) : false; } +auto InputInterface::get(const string& name) -> any { return p ? p->get(name) : false; } +auto InputInterface::set(const string& name, const any& value) -> bool { return p ? p->set(name, value) : false; } +auto InputInterface::acquire() -> bool { return p ? p->acquire() : false; } +auto InputInterface::unacquire() -> bool { return p ? p->unacquire() : false; } +auto InputInterface::acquired() -> bool { return p ? p->acquired() : false; } +auto InputInterface::poll() -> vector> { return p ? p->poll() : vector>(); } +auto InputInterface::rumble(uint64_t id, bool enable) -> bool { return p ? p->rumble(id, enable) : false; } }; diff --git a/ruby/ruby.hpp b/ruby/ruby.hpp index 692cfe5c..648b795f 100644 --- a/ruby/ruby.hpp +++ b/ruby/ruby.hpp @@ -1,14 +1,14 @@ /* ruby * author: byuu * license: ISC - * version: 0.11 (2013-12-19) + * version: 0.12 (2015-05-24) * * ruby is a cross-platform hardware abstraction layer * it provides a common interface to video, audio and input devices */ -#ifndef RUBY_H -#define RUBY_H +#ifndef RUBY_HPP +#define RUBY_HPP #include @@ -65,29 +65,28 @@ private: }; struct InputInterface { - nall::function onChange; + nall::function device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue)> onChange; - void driver(const char* driver = ""); - const char* optimalDriver(); - const char* safestDriver(); - const char* availableDrivers(); - bool init(); - void term(); - - bool cap(const nall::string& name); - nall::any get(const nall::string& name); - bool set(const nall::string& name, const nall::any& value); - - bool acquire(); - bool unacquire(); - bool acquired(); - - nall::vector poll(); - bool rumble(uint64_t id, bool enable); - - InputInterface(); ~InputInterface(); + auto driver(nall::string driver = "") -> void; + auto optimalDriver() -> nall::string; + auto safestDriver() -> nall::string; + auto availableDrivers() -> nall::string; + auto init() -> bool; + auto term() -> void; + + auto cap(const nall::string& name) -> bool; + auto get(const nall::string& name) -> nall::any; + auto set(const nall::string& name, const nall::any& value) -> bool; + + auto acquire() -> bool; + auto unacquire() -> bool; + auto acquired() -> bool; + + auto poll() -> nall::vector>; + auto rumble(uint64_t id, bool enable) -> bool; + private: Input* p = nullptr; }; diff --git a/target-tomoko/GNUmakefile b/target-tomoko/GNUmakefile index 166e0848..8f8a278d 100644 --- a/target-tomoko/GNUmakefile +++ b/target-tomoko/GNUmakefile @@ -14,19 +14,19 @@ ui_objects += ruby hiro # platform ifeq ($(platform),windows) - ruby := video.direct3d video.wgl video.directdraw video.gdi + ruby += video.direct3d video.wgl video.directdraw video.gdi ruby += audio.xaudio2 audio.directsound ruby += input.windows else ifeq ($(platform),macosx) - ruby := video.cgl + ruby += video.cgl ruby += audio.openal ruby += input.carbon else ifeq ($(platform),linux) - ruby := video.glx video.xv video.xshm video.sdl + ruby += video.glx video.xv video.xshm video.sdl ruby += audio.alsa audio.openal audio.oss audio.pulseaudio audio.pulseaudiosimple audio.ao - ruby += input.udev input.sdl input.xlib + ruby += input.sdl input.xlib #input.udev else ifeq ($(platform),bsd) - ruby := video.glx video.xv video.xshm video.sdl + ruby += video.glx video.xv video.xshm video.sdl ruby += audio.openal audio.oss ruby += input.sdl input.xlib endif diff --git a/target-tomoko/input/input.cpp b/target-tomoko/input/input.cpp index 1382164f..84ee15c0 100644 --- a/target-tomoko/input/input.cpp +++ b/target-tomoko/input/input.cpp @@ -5,13 +5,13 @@ InputManager* inputManager = nullptr; auto InputMapping::bind() -> void { auto token = assignment.split("/"); if(token.size() < 3) return unbind(); - uint64_t id = hex(token[0]); + uint64_t id = token[0].decimal(); unsigned group = token[1].decimal(); unsigned input = token[2].decimal(); string qualifier = token(3, "None"); for(auto& device : inputManager->devices) { - if(id != device->id) continue; + if(id != device->id()) continue; this->device = device; this->group = group; @@ -24,25 +24,25 @@ auto InputMapping::bind() -> void { } } -auto InputMapping::bind(HID::Device& device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> bool { - if(device.isNull() || (device.isKeyboard() && device.group[group].input[input].name == "Escape")) { +auto InputMapping::bind(shared_pointer device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> bool { + if(device->isNull() || (device->isKeyboard() && device->group(group).input(input).name() == "Escape")) { return unbind(), true; } - string encoding = {hex(device.id), "/", group, "/", input}; + string encoding = {"0x", hex(device->id()), "/", group, "/", input}; if(isDigital()) { - if((device.isKeyboard() && group == HID::Keyboard::GroupID::Button) - || (device.isMouse() && group == HID::Mouse::GroupID::Button) - || (device.isJoypad() && group == HID::Joypad::GroupID::Button)) { + if((device->isKeyboard() && group == HID::Keyboard::GroupID::Button) + || (device->isMouse() && group == HID::Mouse::GroupID::Button) + || (device->isJoypad() && group == HID::Joypad::GroupID::Button)) { if(newValue) { this->assignment = encoding; return bind(), true; } } - if((device.isJoypad() && group == HID::Joypad::GroupID::Axis) - || (device.isJoypad() && group == HID::Joypad::GroupID::Hat)) { + if((device->isJoypad() && group == HID::Joypad::GroupID::Axis) + || (device->isJoypad() && group == HID::Joypad::GroupID::Hat)) { if(newValue < -16384) { this->assignment = {encoding, "/Lo"}; return bind(), true; @@ -56,9 +56,9 @@ auto InputMapping::bind(HID::Device& device, unsigned group, unsigned input, int } if(isAnalog()) { - if((device.isMouse() && group == HID::Mouse::GroupID::Axis) - || (device.isJoypad() && group == HID::Joypad::GroupID::Axis) - || (device.isJoypad() && group == HID::Joypad::GroupID::Hat)) { + if((device->isMouse() && group == HID::Mouse::GroupID::Axis) + || (device->isJoypad() && group == HID::Joypad::GroupID::Axis) + || (device->isJoypad() && group == HID::Joypad::GroupID::Hat)) { if(newValue < -16384 || newValue > +16384) { this->assignment = encoding; return bind(), true; @@ -67,7 +67,7 @@ auto InputMapping::bind(HID::Device& device, unsigned group, unsigned input, int } if(isRumble()) { - if(device.isJoypad() && group == HID::Joypad::GroupID::Button) { + if(device->isJoypad() && group == HID::Joypad::GroupID::Button) { if(newValue) { encoding = {this->assignment, "/Rumble"}; return bind(), true; @@ -80,7 +80,7 @@ auto InputMapping::bind(HID::Device& device, unsigned group, unsigned input, int auto InputMapping::poll() -> int16 { if(!device) return 0; - auto value = device->group[group].input[input].value; + auto value = device->group(group).input(input).value(); if(isDigital()) { if(device->isKeyboard() && group == HID::Keyboard::GroupID::Button) return value != 0; @@ -110,21 +110,21 @@ auto InputMapping::unbind() -> void { this->qualifier = Qualifier::None; } -auto InputMapping::assignmentName() const -> string { +auto InputMapping::assignmentName() -> string { if(!device) return "None"; string path; - path.append(device->name); - path.append(".", device->group[group].name); - path.append(".", device->group[group].input[input].name); + path.append(device->name()); + path.append(".", device->group(group).name()); + path.append(".", device->group(group).input(input).name()); if(qualifier == Qualifier::Lo) path.append(".Lo"); if(qualifier == Qualifier::Hi) path.append(".Hi"); if(qualifier == Qualifier::Rumble) path.append(".Rumble"); return path; } -auto InputMapping::deviceName() const -> string { +auto InputMapping::deviceName() -> string { if(!device) return ""; - return device->id; + return hex(device->id()); } // @@ -211,7 +211,7 @@ auto InputManager::poll() -> void { if(presentation && presentation->focused()) pollHotkeys(); } -auto InputManager::onChange(HID::Device& device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> void { +auto InputManager::onChange(shared_pointer device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> void { if(settingsManager->focused()) { settingsManager->input.inputEvent(device, group, input, oldValue, newValue); settingsManager->hotkeys.inputEvent(device, group, input, oldValue, newValue); @@ -224,9 +224,9 @@ auto InputManager::quit() -> void { hotkeys.reset(); } -auto InputManager::findMouse() -> HID::Device* { - for(auto device : devices) { +auto InputManager::findMouse() -> shared_pointer { + for(auto& device : devices) { if(device->isMouse()) return device; } - return nullptr; + return {}; } diff --git a/target-tomoko/input/input.hpp b/target-tomoko/input/input.hpp index 1db119ba..6c92cf69 100644 --- a/target-tomoko/input/input.hpp +++ b/target-tomoko/input/input.hpp @@ -1,6 +1,6 @@ struct InputMapping { auto bind() -> void; - auto bind(HID::Device& device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> bool; + auto bind(shared_pointer device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> bool; auto poll() -> int16; auto unbind() -> void; @@ -8,13 +8,13 @@ struct InputMapping { auto isAnalog() const -> bool { return link && link->type == 1; } auto isRumble() const -> bool { return link && link->type == 2; } - auto assignmentName() const -> string; - auto deviceName() const -> string; + auto assignmentName() -> string; + auto deviceName() -> string; string name; string assignment = "None"; Emulator::Interface::Device::Input* link = nullptr; - HID::Device* device = nullptr; + shared_pointer device; unsigned group = 0; unsigned input = 0; enum class Qualifier : unsigned { None, Lo, Hi, Rumble } qualifier = Qualifier::None; @@ -45,16 +45,16 @@ struct InputManager { InputManager(); auto bind() -> void; auto poll() -> void; - auto onChange(HID::Device& device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> void; + auto onChange(shared_pointer device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> void; auto quit() -> void; - auto findMouse() -> HID::Device*; + auto findMouse() -> shared_pointer; //hotkeys.cpp auto appendHotkeys() -> void; auto pollHotkeys() -> void; - vector devices; + vector> devices; vector emulators; vector hotkeys; Configuration::Document config; diff --git a/target-tomoko/settings/hotkeys.cpp b/target-tomoko/settings/hotkeys.cpp index 9057237a..67f370a7 100644 --- a/target-tomoko/settings/hotkeys.cpp +++ b/target-tomoko/settings/hotkeys.cpp @@ -47,9 +47,9 @@ auto HotkeySettings::assignMapping() -> void { } } -auto HotkeySettings::inputEvent(HID::Device& device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> void { +auto HotkeySettings::inputEvent(shared_pointer device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> void { if(!activeMapping) return; - if(!device.isKeyboard() || oldValue != 0 || newValue != 1) return; + if(!device->isKeyboard() || oldValue != 0 || newValue != 1) return; if(activeMapping->bind(device, group, input, oldValue, newValue)) { activeMapping = nullptr; diff --git a/target-tomoko/settings/input.cpp b/target-tomoko/settings/input.cpp index 8e2679ea..60eded27 100644 --- a/target-tomoko/settings/input.cpp +++ b/target-tomoko/settings/input.cpp @@ -115,17 +115,17 @@ auto InputSettings::assignMouseInput(unsigned id) -> void { activeMapping = activeDevice().mappings[mapping->offset()]; if(activeMapping->isDigital()) { - return inputEvent(*mouse, HID::Mouse::GroupID::Button, id, 0, 1, true); + return inputEvent(mouse, HID::Mouse::GroupID::Button, id, 0, 1, true); } else if(activeMapping->isAnalog()) { - return inputEvent(*mouse, HID::Mouse::GroupID::Axis, id, 0, +32767, true); + return inputEvent(mouse, HID::Mouse::GroupID::Axis, id, 0, +32767, true); } } } } -auto InputSettings::inputEvent(HID::Device& device, unsigned group, unsigned input, int16 oldValue, int16 newValue, bool allowMouseInput) -> void { +auto InputSettings::inputEvent(shared_pointer device, unsigned group, unsigned input, int16 oldValue, int16 newValue, bool allowMouseInput) -> void { if(!activeMapping) return; - if(device.isMouse() && !allowMouseInput) return; + if(device->isMouse() && !allowMouseInput) return; if(activeMapping->bind(device, group, input, oldValue, newValue)) { activeMapping = nullptr; diff --git a/target-tomoko/settings/settings.hpp b/target-tomoko/settings/settings.hpp index 64b183a5..4e7b8ae5 100644 --- a/target-tomoko/settings/settings.hpp +++ b/target-tomoko/settings/settings.hpp @@ -10,7 +10,7 @@ struct InputSettings : TabFrameItem { auto refreshMappings() -> void; auto assignMapping() -> void; auto assignMouseInput(unsigned id) -> void; - auto inputEvent(HID::Device& device, unsigned group, unsigned input, int16 oldValue, int16 newValue, bool allowMouseInput = false) -> void; + auto inputEvent(shared_pointer device, unsigned group, unsigned input, int16 oldValue, int16 newValue, bool allowMouseInput = false) -> void; InputMapping* activeMapping = nullptr; @@ -34,7 +34,7 @@ struct HotkeySettings : TabFrameItem { auto reloadMappings() -> void; auto refreshMappings() -> void; auto assignMapping() -> void; - auto inputEvent(HID::Device& device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> void; + auto inputEvent(shared_pointer device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> void; InputMapping* activeMapping = nullptr;