[gnome-games] gamepad: Make gamepad emit Event objects



commit d942798ba376b48146e93becd490b83f53948773
Author: Adrien Plazas <kekun plazas laposte net>
Date:   Sat May 13 23:35:43 2017 +0200

    gamepad: Make gamepad emit Event objects
    
    Replace the 'button-event' and 'axis-event' signals from Gamepad by the
    'button-press-event', 'button-release-event', 'axis-event' and
    'hat-event' ones sending Event objects after mapping them is the Gamepad
    object has a mapping, or directly if it doesn't.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=782611

 src/gamepad/gamepad.c        |  288 +++++++++++++++++++++++++-----------------
 src/gamepad/gamepad.vapi     |    6 +-
 src/retro/retro-gamepad.vala |    5 +-
 3 files changed, 176 insertions(+), 123 deletions(-)
---
diff --git a/src/gamepad/gamepad.c b/src/gamepad/gamepad.c
index 196be99..178c16a 100644
--- a/src/gamepad/gamepad.c
+++ b/src/gamepad/gamepad.c
@@ -19,8 +19,10 @@ G_DEFINE_TYPE (GamesGamepad, games_gamepad, G_TYPE_OBJECT)
 
 enum {
   SIGNAL_EVENT,
-  SIGNAL_BUTTON_EVENT,
+  SIGNAL_BUTTON_PRESS_EVENT,
+  SIGNAL_BUTTON_RELEASE_EVENT,
   SIGNAL_AXIS_EVENT,
+  SIGNAL_HAT_EVENT,
   SIGNAL_UNPLUGGED,
   LAST_SIGNAL,
 };
@@ -30,137 +32,175 @@ static guint signals[LAST_SIGNAL] = { 0 };
 /* Private */
 
 static void
-on_button_event (GamesRawGamepad         *sender,
-                 GamesEventGamepadButton *games_event,
-                 gpointer                 data)
+forward_event (GamesGamepad *self,
+               GamesEvent   *event)
 {
-  GamesGamepad *self;
-  GamesGamepadInput event;
-  gboolean value;
-
-  self = GAMES_GAMEPAD (data);
-
-  g_return_if_fail (self != NULL);
+  switch (event->type) {
+  case GAMES_EVENT_GAMEPAD_BUTTON_PRESS:
+    g_signal_emit (self, signals[SIGNAL_BUTTON_PRESS_EVENT], 0, event);
 
-  if (self->mapping == NULL)
     return;
+  case GAMES_EVENT_GAMEPAD_BUTTON_RELEASE:
+    g_signal_emit (self, signals[SIGNAL_BUTTON_RELEASE_EVENT], 0, event);
 
-  switch (games_event->type) {
-  case GAMES_EVENT_GAMEPAD_BUTTON_PRESS:
-    value = TRUE;
+    return;
+  case GAMES_EVENT_GAMEPAD_AXIS:
+    g_signal_emit (self, signals[SIGNAL_AXIS_EVENT], 0, event);
 
-    break;
-  case GAMES_EVENT_GAMEPAD_BUTTON_RELEASE:
-    value = FALSE;
+    return;
+  case GAMES_EVENT_GAMEPAD_HAT:
+    g_signal_emit (self, signals[SIGNAL_HAT_EVENT], 0, event);
 
-    break;
+    return;
   default:
-    g_assert_not_reached ();
-
-    break;
+    return;
   }
+}
+
+static void
+map_button_event (GamesGamepad            *self,
+                  GamesEventGamepadButton *games_event)
+{
+  GamesGamepadInput destination;
+  GamesEvent *mapped_event;
+  guint signal;
+  gboolean pressed;
+
+  mapped_event = games_event_copy ((GamesEvent *) games_event);
   games_gamepad_mapping_get_button_mapping (self->mapping,
                                             games_event->index,
-                                            &event);
+                                            &destination);
 
-  switch (event.type) {
+  pressed = games_event->type == GAMES_EVENT_GAMEPAD_BUTTON_PRESS;
+
+  mapped_event->any.send_event = TRUE;
+  mapped_event->gamepad.hardware_type = destination.type;
+  mapped_event->gamepad.hardware_code = destination.code;
+
+  switch (destination.type) {
   case EV_ABS:
-    g_signal_emit (self,
-                   signals[SIGNAL_AXIS_EVENT],
-                   0, event.code, value ? 1 : 0);
+    signal = SIGNAL_AXIS_EVENT;
+    mapped_event->gamepad_axis.index = 0; // FIXME How to set it properly?
+    mapped_event->gamepad_axis.value = pressed ? 1 : 0;
 
     break;
   case EV_KEY:
-    g_signal_emit (self,
-                   signals[SIGNAL_BUTTON_EVENT],
-                   0, event.code, value);
+    signal = pressed ? SIGNAL_BUTTON_PRESS_EVENT : SIGNAL_BUTTON_RELEASE_EVENT;
+    mapped_event->gamepad_button.index = 0; // FIXME How to set it properly?
+
     break;
   default:
-    break;
+    games_event_free (mapped_event);
+
+    return;
   }
+
+  g_signal_emit (self, signals[signal], 0, mapped_event);
+
+  games_event_free (mapped_event);
 }
 
 static void
-on_axis_event (GamesRawGamepad       *sender,
-               GamesEventGamepadAxis *games_event,
-               gpointer               data)
+map_axis_event (GamesGamepad          *self,
+                GamesEventGamepadAxis *games_event)
 {
-  GamesGamepad *self;
-  GamesGamepadInput event;
+  GamesGamepadInput destination;
+  GamesEvent *mapped_event;
+  guint signal;
+  gboolean pressed;
 
-  self = GAMES_GAMEPAD (data);
+  mapped_event = games_event_copy ((GamesEvent *) games_event);
+  games_gamepad_mapping_get_axis_mapping (self->mapping, games_event->index, &destination);
 
-  g_return_if_fail (self != NULL);
+  pressed = games_event->value > 0.;
 
-  if (self->mapping == NULL)
-    return;
+  mapped_event->any.send_event = TRUE;
+  mapped_event->gamepad.hardware_type = destination.type;
+  mapped_event->gamepad.hardware_code = destination.code;
 
-  games_gamepad_mapping_get_axis_mapping (self->mapping, games_event->index, &event);
-  switch (event.type) {
+  switch (destination.type) {
   case EV_ABS:
-    g_signal_emit (self, signals[SIGNAL_AXIS_EVENT],
-                   0, event.code, games_event->value);
+    signal = SIGNAL_AXIS_EVENT;
+    mapped_event->gamepad_axis.index = 0; // FIXME How to set it properly?
+
     break;
   case EV_KEY:
-    g_signal_emit (self, signals[SIGNAL_BUTTON_EVENT],
-                   0, event.code, games_event->value > 0.);
+    signal = pressed ? SIGNAL_BUTTON_PRESS_EVENT : SIGNAL_BUTTON_RELEASE_EVENT;
+    mapped_event->gamepad_button.index = 0; // FIXME How to set it properly?
 
     break;
   default:
-    break;
+    games_event_free (mapped_event);
+
+    return;
   }
+
+  g_signal_emit (self, signals[signal], 0, mapped_event);
+
+  games_event_free (mapped_event);
 }
 
 static void
-on_hat_event (GamesRawGamepad      *sender,
-              GamesEventGamepadHat *games_event,
-              gpointer              data)
+map_hat_event (GamesGamepad         *self,
+               GamesEventGamepadHat *games_event)
 {
-  GamesGamepad *self;
-  GamesGamepadInput event;
+  GamesGamepadInput destination;
+  GamesEvent *mapped_event;
+  guint signal;
+  gboolean pressed;
 
-  self = GAMES_GAMEPAD (data);
+  mapped_event = games_event_copy ((GamesEvent *) games_event);
+  games_gamepad_mapping_get_dpad_mapping (self->mapping,
+                                          games_event->index,
+                                          games_event->axis,
+                                          games_event->value,
+                                          &destination);
 
-  g_return_if_fail (self != NULL);
+  pressed = abs (games_event->value);
 
-  if (self->mapping == NULL) {
-    if (games_event->index != 0)
-      return;
+  mapped_event->any.send_event = TRUE;
+  mapped_event->gamepad.hardware_type = destination.type;
+  mapped_event->gamepad.hardware_code = destination.code;
 
-    switch (games_event->axis) {
-    case 0:
-      g_signal_emit (self, signals[SIGNAL_BUTTON_EVENT],
-                     0, BTN_DPAD_LEFT, games_event->value < 0);
-      g_signal_emit (self, signals[SIGNAL_BUTTON_EVENT],
-                     0, BTN_DPAD_RIGHT, games_event->value > 0);
-
-      break;
-    case 1:
-      g_signal_emit (self, signals[SIGNAL_BUTTON_EVENT],
-                     0, BTN_DPAD_UP, games_event->value < 0);
-      g_signal_emit (self, signals[SIGNAL_BUTTON_EVENT],
-                     0, BTN_DPAD_DOWN, games_event->value > 0);
+  switch (destination.type) {
+  case EV_ABS:
+    signal = SIGNAL_AXIS_EVENT;
+    mapped_event->gamepad_axis.index = 0; // FIXME How to set it properly?
+    mapped_event->gamepad_axis.value = abs (games_event->value);
 
-      break;
-    default:
-      g_debug ("Unexpected axis number: %d.", games_event->axis);
+    break;
+  case EV_KEY:
+    signal = pressed ? SIGNAL_BUTTON_PRESS_EVENT : SIGNAL_BUTTON_RELEASE_EVENT;
+    mapped_event->gamepad_button.index = 0; // FIXME How to set it properly?
 
-      break;
-    }
+    break;
+  default:
+    games_event_free (mapped_event);
 
     return;
   }
 
-  games_gamepad_mapping_get_dpad_mapping (self->mapping, games_event->index, games_event->axis, 
games_event->value, &event);
-  switch (event.type) {
-  case EV_ABS:
-    g_signal_emit (self, signals[SIGNAL_AXIS_EVENT],
-                   0, event.code, (gdouble) abs (games_event->value));
+  g_signal_emit (self, signals[signal], 0, mapped_event);
+
+  games_event_free (mapped_event);
+}
+
+static void
+map_event (GamesGamepad *self,
+           GamesEvent   *event)
+{
+  switch (event->type) {
+  case GAMES_EVENT_GAMEPAD_BUTTON_PRESS:
+  case GAMES_EVENT_GAMEPAD_BUTTON_RELEASE:
+    map_button_event (self, &event->gamepad_button);
 
     break;
-  case EV_KEY:
-    g_signal_emit (self, signals[SIGNAL_BUTTON_EVENT],
-                   0, event.code, (gboolean) abs (games_event->value));
+  case GAMES_EVENT_GAMEPAD_AXIS:
+    map_axis_event (self, &event->gamepad_axis);
+
+    break;
+  case GAMES_EVENT_GAMEPAD_HAT:
+    map_hat_event (self, &event->gamepad_hat);
 
     break;
   default:
@@ -182,25 +222,9 @@ on_event (GamesRawGamepad *sender,
   g_signal_emit (self, signals[SIGNAL_EVENT], 0, event);
 
   if (self->mapping == NULL)
-    return;
-
-  switch (event->type) {
-  case GAMES_EVENT_GAMEPAD_BUTTON_PRESS:
-  case GAMES_EVENT_GAMEPAD_BUTTON_RELEASE:
-    on_button_event (sender, &event->gamepad_button, data);
-
-    break;
-  case GAMES_EVENT_GAMEPAD_AXIS:
-    on_axis_event (sender, &event->gamepad_axis, data);
-
-    break;
-  case GAMES_EVENT_GAMEPAD_HAT:
-    on_hat_event (sender, &event->gamepad_hat, data);
-
-    break;
-  default:
-    break;
-  }
+    forward_event (self, event);
+  else
+    map_event (self, event);
 }
 
 static void
@@ -282,38 +306,64 @@ static void games_gamepad_class_init (GamesGamepadClass *klass) {
                   GAMES_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
 
   /**
-   * GamesGamepad::axis-event:
-   * @button: the code representing the button
-   * @value: %TRUE if the button is pressed, %FALSE otherwise
+   * GamesGamepad::button-press-event:
+   * @event: the event emitted by the gamepad
    *
-   * Emitted when a button is pressed/released.
+   * Emitted when a button is pressed.
    */
-  signals[SIGNAL_BUTTON_EVENT] =
-    g_signal_new ("button-event",
+  signals[SIGNAL_BUTTON_PRESS_EVENT] =
+    g_signal_new ("button-press-event",
                   GAMES_TYPE_GAMEPAD,
                   G_SIGNAL_RUN_LAST,
                   0, NULL, NULL,
-                  NULL,
-                  G_TYPE_NONE, 2,
-                  G_TYPE_UINT,
-                  G_TYPE_BOOLEAN);
+                  g_cclosure_marshal_VOID__BOXED,
+                  G_TYPE_NONE, 1,
+                  GAMES_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
+
+  /**
+   * GamesGamepad::button-release-event:
+   * @event: the event emitted by the gamepad
+   *
+   * Emitted when a button is released.
+   */
+  signals[SIGNAL_BUTTON_RELEASE_EVENT] =
+    g_signal_new ("button-release-event",
+                  GAMES_TYPE_GAMEPAD,
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL,
+                  g_cclosure_marshal_VOID__BOXED,
+                  G_TYPE_NONE, 1,
+                  GAMES_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
 
   /**
    * GamesGamepad::axis-event:
-   * @axis: the code representing the axis
-   * @value: the value of the axis ranging from -1 to 1
+   * @event: the event emitted by the gamepad
    *
-   * Emitted when a standard axis' value changes.
+   * Emitted when a axis' value changes.
    */
   signals[SIGNAL_AXIS_EVENT] =
     g_signal_new ("axis-event",
                   GAMES_TYPE_GAMEPAD,
                   G_SIGNAL_RUN_LAST,
                   0, NULL, NULL,
-                  NULL,
-                  G_TYPE_NONE, 2,
-                  G_TYPE_UINT,
-                  G_TYPE_DOUBLE);
+                  g_cclosure_marshal_VOID__BOXED,
+                  G_TYPE_NONE, 1,
+                  GAMES_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
+
+  /**
+   * GamesGamepad::hat-event:
+   * @event: the event emitted by the gamepad
+   *
+   * Emitted when a axis from a hat's value changes.
+   */
+  signals[SIGNAL_HAT_EVENT] =
+    g_signal_new ("hat-event",
+                  GAMES_TYPE_GAMEPAD,
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL,
+                  g_cclosure_marshal_VOID__BOXED,
+                  G_TYPE_NONE, 1,
+                  GAMES_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
 
   /**
    * GamesGamepad::unplugged:
diff --git a/src/gamepad/gamepad.vapi b/src/gamepad/gamepad.vapi
index 1e2fd2a..e52b030 100644
--- a/src/gamepad/gamepad.vapi
+++ b/src/gamepad/gamepad.vapi
@@ -3,8 +3,10 @@
 [CCode (cheader_filename = "gamepad.h")]
 private class Games.Gamepad : GLib.Object {
        public signal void event (Event event);
-       public signal void button_event (uint button, bool value);
-       public signal void axis_event (uint axis, double value);
+       public signal void button_press_event (Event event);
+       public signal void button_release_event (Event event);
+       public signal void axis_event (Event event);
+       public signal void hat_event (Event event);
        public signal void unplugged ();
        public Gamepad (RawGamepad raw_gamepad) throws GLib.Error;
 }
diff --git a/src/retro/retro-gamepad.vala b/src/retro/retro-gamepad.vala
index abb9f15..537cc4e 100644
--- a/src/retro/retro-gamepad.vala
+++ b/src/retro/retro-gamepad.vala
@@ -15,8 +15,9 @@ private class Games.RetroGamepad: Object, Retro.InputDevice {
                buttons = new bool[EventCode.KEY_MAX + 1];
                axes = new int16[EventCode.ABS_MAX + 1];
 
-               gamepad.button_event.connect ((button, value) => buttons[button] = value);
-               gamepad.axis_event.connect ((axis, value) => axes[axis] = (int16) (value * int16.MAX));
+               gamepad.button_press_event.connect ((event) => buttons[event.gamepad.hardware_code] = true);
+               gamepad.button_release_event.connect ((event) => buttons[event.gamepad.hardware_code] = 
false);
+               gamepad.axis_event.connect ((event) => axes[event.gamepad.hardware_code] = (int16) 
(event.gamepad_axis.value * int16.MAX));
        }
 
        public void poll () {}


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