[retro-gtk/gamepad: 3/3] inpupt: Add Gamepad



commit 1c7df68bbe06fb12d4d4407577186f2e9055af95
Author: Adrien Plazas <kekun plazas laposte net>
Date:   Tue Jul 25 12:02:49 2017 +0200

    inpupt: Add Gamepad
    
    This will help frontends to use gamepads with the library. The gamepad
    object expects Linux event codes rather than Libretro inputs.

 retro-gtk/Makefile.am           |    2 +
 retro-gtk/input/device.vala     |    6 +-
 retro-gtk/input/gamepad.vala    |   35 +++++++
 retro-gtk/input/retro-gamepad.c |  202 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 243 insertions(+), 2 deletions(-)
---
diff --git a/retro-gtk/Makefile.am b/retro-gtk/Makefile.am
index 344b4f9..42ba049 100644
--- a/retro-gtk/Makefile.am
+++ b/retro-gtk/Makefile.am
@@ -31,12 +31,14 @@ libretro_gtk_la_SOURCES = \
        \
        input/controller.vala \
        input/device.vala \
+       input/gamepad.vala \
        input/gamepad-configuration.vala \
        input/input.vala \
        input/input-device.vala \
        input/input-device-manager.vala \
        input/keyboard-state.vala \
        input/mouse.vala \
+       input/retro-gamepad.c \
        input/retro-keyboard-key.c \
        input/virtual-gamepad.vala \
        \
diff --git a/retro-gtk/input/device.vala b/retro-gtk/input/device.vala
index ce8a5bf..e9ff6da 100644
--- a/retro-gtk/input/device.vala
+++ b/retro-gtk/input/device.vala
@@ -62,7 +62,8 @@ public enum JoypadId {
  */
 public enum AnalogIndex {
        LEFT,
-       RIGHT
+       RIGHT,
+       COUNT,
 }
 
 /**
@@ -70,7 +71,8 @@ public enum AnalogIndex {
  */
 public enum AnalogId {
        X,
-       Y
+       Y,
+       COUNT,
 }
 
 /**
diff --git a/retro-gtk/input/gamepad.vala b/retro-gtk/input/gamepad.vala
new file mode 100644
index 0000000..6f7b117
--- /dev/null
+++ b/retro-gtk/input/gamepad.vala
@@ -0,0 +1,35 @@
+// This file is part of retro-gtk. License: GPL-3.0+.
+
+public class Retro.Gamepad: Object, InputDevice {
+       internal void *internal;
+
+       public Gamepad (bool analog) {
+               internal_init (analog);
+       }
+
+       ~Gamepad () {
+               internal_finalize ();
+       }
+
+       public void poll () {}
+
+       public int16 get_input_state (DeviceType device, uint index, uint id) {
+               return internal_get_input_state (device, index, id);
+       }
+
+       public DeviceType get_device_type () {
+               return internal_get_device_type ();
+       }
+       public uint64 get_device_capabilities () {
+               return internal_get_device_capabilities ();
+       }
+
+       public extern void button_press_event (uint16 button);
+       public extern void button_release_event (uint16 button);
+       public extern void axis_event (uint16 axis, double value);
+       private extern int16 internal_get_input_state (DeviceType device, uint index, uint id);
+       private extern DeviceType internal_get_device_type ();
+       private extern uint64 internal_get_device_capabilities ();
+       private extern void internal_init (bool analog);
+       private extern void internal_finalize ();
+}
diff --git a/retro-gtk/input/retro-gamepad.c b/retro-gtk/input/retro-gamepad.c
new file mode 100644
index 0000000..eec4c7a
--- /dev/null
+++ b/retro-gtk/input/retro-gamepad.c
@@ -0,0 +1,202 @@
+// This file is part of retro-gtk. License: GPL-3.0+.
+
+#include <linux/input-event-codes.h>
+#include "retro-gtk-internal.h"
+
+typedef struct {
+  gboolean analog;
+  gint16 buttons[RETRO_JOYPAD_ID_COUNT];
+  gint16 axes[RETRO_ANALOG_INDEX_COUNT][RETRO_ANALOG_ID_COUNT];
+} RetroGamepadInternal;
+
+#define RETRO_GAMEPAD_INTERNAL(self) ((RetroGamepadInternal *) ((self)->internal))
+
+/* Private */
+
+static RetroJoypadId
+button_to_retro_button (guint16 button)
+{
+  switch (button) {
+  case BTN_A:
+    return RETRO_JOYPAD_ID_B;
+  case BTN_Y:
+    return RETRO_JOYPAD_ID_Y;
+  case BTN_SELECT:
+    return RETRO_JOYPAD_ID_SELECT;
+  case BTN_START:
+    return RETRO_JOYPAD_ID_START;
+  case BTN_DPAD_UP:
+    return RETRO_JOYPAD_ID_UP;
+  case BTN_DPAD_DOWN:
+    return RETRO_JOYPAD_ID_DOWN;
+  case BTN_DPAD_LEFT:
+    return RETRO_JOYPAD_ID_LEFT;
+  case BTN_DPAD_RIGHT:
+    return RETRO_JOYPAD_ID_RIGHT;
+  case BTN_B:
+    return RETRO_JOYPAD_ID_A;
+  case BTN_X:
+    return RETRO_JOYPAD_ID_X;
+  case BTN_TL:
+    return RETRO_JOYPAD_ID_L;
+  case BTN_TR:
+    return RETRO_JOYPAD_ID_R;
+  case BTN_TL2:
+    return RETRO_JOYPAD_ID_L2;
+  case BTN_TR2:
+    return RETRO_JOYPAD_ID_R2;
+  case BTN_THUMBL:
+    return RETRO_JOYPAD_ID_L3;
+  case BTN_THUMBR:
+    return RETRO_JOYPAD_ID_R3;
+  default:
+    return RETRO_JOYPAD_ID_COUNT;
+  }
+
+  return RETRO_JOYPAD_ID_COUNT;
+}
+
+static gboolean
+axis_to_retro_axis (guint16           axis,
+                    RetroAnalogIndex *index,
+                    RetroAnalogId    *id)
+{
+  switch (axis) {
+  case ABS_X:
+    *index = RETRO_ANALOG_INDEX_LEFT;
+    *id = RETRO_ANALOG_ID_X;
+
+    return TRUE;
+  case ABS_Y:
+    *index = RETRO_ANALOG_INDEX_LEFT;
+    *id = RETRO_ANALOG_ID_Y;
+
+    return TRUE;
+  case ABS_RX:
+    *index = RETRO_ANALOG_INDEX_RIGHT;
+    *id = RETRO_ANALOG_ID_X;
+
+    return TRUE;
+  case ABS_RY:
+    *index = RETRO_ANALOG_INDEX_RIGHT;
+    *id = RETRO_ANALOG_ID_Y;
+
+    return TRUE;
+  default:
+    return FALSE;
+  }
+
+  return FALSE;
+}
+
+/* Public */
+
+void
+retro_gamepad_button_press_event (RetroGamepad *self,
+                                  guint16       button)
+{
+  RetroJoypadId retro_button;
+
+  g_return_if_fail (self != NULL);
+
+  retro_button = button_to_retro_button (button);
+
+  if (retro_button == RETRO_JOYPAD_ID_COUNT)
+    return;
+
+  RETRO_GAMEPAD_INTERNAL (self)->buttons[button] = G_MAXINT16;
+}
+
+void
+retro_gamepad_button_release_event (RetroGamepad *self,
+                                    guint16       button)
+{
+  RetroJoypadId retro_button;
+
+  g_return_if_fail (self != NULL);
+
+  retro_button = button_to_retro_button (button);
+
+  if (retro_button == RETRO_JOYPAD_ID_COUNT)
+    return;
+
+  RETRO_GAMEPAD_INTERNAL (self)->buttons[button] = 0;
+}
+
+void
+retro_gamepad_axis_event (RetroGamepad *self,
+                          guint16       axis,
+                          gdouble       value)
+{
+  RetroAnalogIndex retro_index;
+  RetroAnalogId retro_id;
+
+  g_return_if_fail (self != NULL);
+
+  if (!axis_to_retro_axis (axis, &retro_index, &retro_id))
+    return;
+
+  RETRO_GAMEPAD_INTERNAL (self)->axes[retro_index][retro_id] = value * G_MAXINT16;
+}
+
+gint16
+retro_gamepad_internal_get_input_state (RetroInputDevice *base,
+                                        RetroDeviceType   device,
+                                        guint             index,
+                                        guint             id)
+{
+  RetroGamepad *self = RETRO_GAMEPAD (base);
+
+    g_return_val_if_fail (self != NULL, 0);
+
+  switch (device) {
+  case RETRO_DEVICE_TYPE_JOYPAD:
+    g_return_val_if_fail (id < RETRO_JOYPAD_ID_COUNT, 0);
+
+    return RETRO_GAMEPAD_INTERNAL (self)->buttons[id];
+  case RETRO_DEVICE_TYPE_ANALOG:
+    g_return_val_if_fail (index < RETRO_ANALOG_INDEX_COUNT, 0);
+    g_return_val_if_fail (id < RETRO_ANALOG_ID_COUNT, 0);
+
+    return RETRO_GAMEPAD_INTERNAL (self)->axes[index][id];
+  default:
+    return 0;
+  }
+
+  return 0;
+}
+
+RetroDeviceType
+retro_gamepad_internal_get_device_type (RetroInputDevice *base)
+{
+  RetroGamepad *self = RETRO_GAMEPAD (base);
+
+  g_return_val_if_fail (self != NULL, RETRO_DEVICE_TYPE_NONE);
+
+  if (RETRO_GAMEPAD_INTERNAL (self)->analog)
+    return RETRO_DEVICE_TYPE_ANALOG;
+
+  return RETRO_DEVICE_TYPE_JOYPAD;
+}
+
+guint64
+retro_gamepad_internal_get_device_capabilities (RetroInputDevice *base) {
+  return (1 << RETRO_DEVICE_TYPE_JOYPAD) | (1 << RETRO_DEVICE_TYPE_ANALOG);
+}
+
+void
+retro_gamepad_internal_init (RetroGamepad *self, gboolean analog) {
+  g_return_if_fail (self != NULL);
+
+  self->internal = g_new0 (RetroGamepadInternal, 1);
+
+  RETRO_GAMEPAD_INTERNAL (self)->analog = analog;
+}
+
+void
+retro_gamepad_internal_finalize (RetroGamepad *self)
+{
+  g_return_if_fail (self != NULL);
+
+  g_free (self->internal);
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]