[gnome-games: 18/20] gamepad: Port Gamepad to C
- From: Adrien Plazas <aplazas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-games: 18/20] gamepad: Port Gamepad to C
- Date: Wed, 3 May 2017 08:22:19 +0000 (UTC)
commit 99d30bda8f7a85e030ad84d638141cff4c8acdb4
Author: Adrien Plazas <kekun plazas laposte net>
Date: Mon May 1 17:24:59 2017 +0200
gamepad: Port Gamepad to C
This will help to port part of the gamepad handling to C to avoid using
the Vala preprocessor.
https://bugzilla.gnome.org/show_bug.cgi?id=781572
src/Makefile.am | 4 +-
src/gamepad/gamepad.c | 329 ++++++++++++++++++++++++++++++++++++++++++++++
src/gamepad/gamepad.h | 20 +++
src/gamepad/gamepad.vala | 127 ------------------
src/gamepad/gamepad.vapi | 9 ++
5 files changed, 361 insertions(+), 128 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 4d5f8a5..4d8de9a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,6 +23,7 @@ BUILT_SOURCES = \
EXTRA_DIST = \
$(gresource_file) \
+ gamepad/gamepad.vapi \
gamepad/gamepad-dpad.vapi \
gamepad/gamepad-input-type.vapi \
gamepad/gamepad-mapped-event.vapi \
@@ -78,7 +79,7 @@ gnome_games_SOURCES = \
gameinfo/gameinfo-disc-id-game-title.vala \
gameinfo/gameinfo-disc-id-input-capabilities.vala \
\
- gamepad/gamepad.vala \
+ gamepad/gamepad.c \
gamepad/gamepad-callbacks.vala \
gamepad/gamepad-dpad.c \
gamepad/gamepad-input-type.c \
@@ -190,6 +191,7 @@ gnome_games_VALAFLAGS = \
--pkg retro-gtk-0.10 \
--pkg linux \
--pkg posix \
+ --pkg gamepad \
--pkg gamepad-dpad \
--pkg gamepad-input-type \
--pkg gamepad-mapped-event \
diff --git a/src/gamepad/gamepad.c b/src/gamepad/gamepad.c
new file mode 100644
index 0000000..6183acb
--- /dev/null
+++ b/src/gamepad/gamepad.c
@@ -0,0 +1,329 @@
+// This file is part of GNOME Games. License: GPL-3.0+.
+
+#include "gamepad.h"
+
+#include <stdlib.h>
+#include "gamepad-mapping.h"
+#include "gamepad-mappings-manager.h"
+
+struct _GamesGamepad {
+ GObject parent_instance;
+
+ GamesRawGamepad *raw_gamepad;
+ GamesGamepadMapping *mapping;
+};
+
+G_DEFINE_TYPE (GamesGamepad, games_gamepad, G_TYPE_OBJECT)
+
+enum {
+ SIGNAL_BUTTON_EVENT,
+ SIGNAL_AXIS_EVENT,
+ SIGNAL_UNPLUGGED,
+ LAST_SIGNAL,
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/* Private */
+
+static void
+on_standard_button_event (GamesRawGamepad *sender,
+ GamesStandardGamepadButton button,
+ gboolean value,
+ gpointer data)
+{
+ GamesGamepad *self;
+
+ self = GAMES_GAMEPAD (data);
+
+ g_return_if_fail (self != NULL);
+
+ if (self->mapping != NULL)
+ return;
+
+ g_signal_emit (self, signals[SIGNAL_BUTTON_EVENT],
+ 0, button, value);
+}
+
+static void
+on_raw_button_event (GamesRawGamepad *sender,
+ gint button,
+ gboolean value,
+ gpointer data)
+{
+ GamesGamepad *self;
+ GamesGamepadMappedEvent event;
+
+ self = GAMES_GAMEPAD (data);
+
+ g_return_if_fail (self != NULL);
+
+ if (self->mapping == NULL)
+ return;
+
+ games_gamepad_mapping_get_button_mapping (self->mapping,
+ button,
+ &event);
+
+ switch (event.type) {
+ case GAMES_GAMEPAD_INPUT_TYPE_AXIS:
+ g_signal_emit (self,
+ signals[SIGNAL_AXIS_EVENT],
+ 0, event.axis, value ? 1 : 0);
+
+ break;
+ case GAMES_GAMEPAD_INPUT_TYPE_BUTTON:
+ g_signal_emit (self,
+ signals[SIGNAL_BUTTON_EVENT],
+ 0, event.button, value);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+on_standard_axis_event (GamesRawGamepad *sender,
+ GamesStandardGamepadAxis axis,
+ gdouble value,
+ gpointer data)
+{
+ GamesGamepad *self;
+
+ self = GAMES_GAMEPAD (data);
+
+ g_return_if_fail (self != NULL);
+
+ if (self->mapping != NULL)
+ return;
+
+ g_signal_emit (self, signals[SIGNAL_AXIS_EVENT],
+ 0, axis, value);
+}
+
+static void
+on_raw_axis_event (GamesRawGamepad *sender,
+ gint axis,
+ gdouble value,
+ gpointer data)
+{
+ GamesGamepad *self;
+ GamesGamepadMappedEvent event;
+
+ self = GAMES_GAMEPAD (data);
+
+ g_return_if_fail (self != NULL);
+
+ if (self->mapping == NULL)
+ return;
+
+ games_gamepad_mapping_get_axis_mapping (self->mapping, axis, &event);
+ switch (event.type) {
+ case GAMES_GAMEPAD_INPUT_TYPE_AXIS:
+ g_signal_emit (self, signals[SIGNAL_AXIS_EVENT],
+ 0, event.axis, value);
+ break;
+ case GAMES_GAMEPAD_INPUT_TYPE_BUTTON:
+ g_signal_emit (self, signals[SIGNAL_BUTTON_EVENT],
+ 0, event.button, value > 0.);
+
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+on_raw_dpad_event (GamesRawGamepad *sender,
+ gint dpad_index,
+ gint axis,
+ gint value,
+ gpointer data)
+{
+ GamesGamepad *self;
+ GamesGamepadMappedEvent event;
+
+ self = GAMES_GAMEPAD (data);
+
+ g_return_if_fail (self != NULL);
+
+ if (self->mapping == NULL) {
+ if (dpad_index != 0)
+ return;
+
+ switch (axis) {
+ case 0:
+ g_signal_emit (self, signals[SIGNAL_BUTTON_EVENT],
+ 0, GAMES_STANDARD_GAMEPAD_BUTTON_DPAD_LEFT, value < 0);
+ g_signal_emit (self, signals[SIGNAL_BUTTON_EVENT],
+ 0, GAMES_STANDARD_GAMEPAD_BUTTON_DPAD_RIGHT, value > 0);
+
+ break;
+ case 1:
+ g_signal_emit (self, signals[SIGNAL_BUTTON_EVENT],
+ 0, GAMES_STANDARD_GAMEPAD_BUTTON_DPAD_UP, value < 0);
+ g_signal_emit (self, signals[SIGNAL_BUTTON_EVENT],
+ 0, GAMES_STANDARD_GAMEPAD_BUTTON_DPAD_DOWN, value > 0);
+
+ break;
+ default:
+ g_debug ("Unexpected axis number: %d.", axis);
+
+ break;
+ }
+
+ return;
+ }
+
+ games_gamepad_mapping_get_dpad_mapping (self->mapping, dpad_index, axis, value, &event);
+ switch (event.type) {
+ case GAMES_GAMEPAD_INPUT_TYPE_AXIS:
+ g_signal_emit (self, signals[SIGNAL_AXIS_EVENT],
+ 0, event.axis, (gdouble) abs (value));
+
+ break;
+ case GAMES_GAMEPAD_INPUT_TYPE_BUTTON:
+ g_signal_emit (self, signals[SIGNAL_BUTTON_EVENT],
+ 0, event.button, (gboolean) abs (value));
+
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+on_unplugged (GamesRawGamepad *sender,
+ gpointer target)
+{
+ g_signal_emit (target, signals[SIGNAL_UNPLUGGED], 0);
+}
+
+/* Public */
+
+// FIXME
+GamesGamepad *
+games_gamepad_new (GamesRawGamepad *raw_gamepad,
+ GError **error)
+{
+ GamesGamepad *self = NULL;
+ const gchar *guid;
+ GamesGamepadMappingsManager *mappings_manager;
+ const gchar *mapping_string;
+ GError *inner_error = NULL;
+
+ g_return_val_if_fail (raw_gamepad != NULL, NULL);
+
+ self = (GamesGamepad*) g_object_new (GAMES_TYPE_GAMEPAD, NULL);
+
+ self->raw_gamepad = g_object_ref (raw_gamepad);
+ guid = games_raw_gamepad_get_guid (raw_gamepad);
+ mappings_manager = games_gamepad_mappings_manager_get_instance ();
+ mapping_string = games_gamepad_mappings_manager_get_mapping (mappings_manager, guid);
+
+ g_object_unref (mappings_manager);
+
+ self->mapping = games_gamepad_mapping_new_from_sdl_string (mapping_string, &inner_error);
+ if (G_UNLIKELY (inner_error != NULL)) {
+ g_debug ("%s", inner_error->message);
+ g_clear_error (&inner_error);
+ }
+
+ g_signal_connect_object (raw_gamepad,
+ "standard-button-event",
+ (GCallback) on_standard_button_event,
+ self,
+ 0);
+ g_signal_connect_object (raw_gamepad,
+ "button-event",
+ (GCallback) on_raw_button_event,
+ self,
+ 0);
+ g_signal_connect_object (raw_gamepad,
+ "standard-axis-event",
+ (GCallback) on_standard_axis_event,
+ self,
+ 0);
+ g_signal_connect_object (raw_gamepad,
+ "axis-event",
+ (GCallback) on_raw_axis_event,
+ self,
+ 0);
+ g_signal_connect_object (raw_gamepad,
+ "dpad-event",
+ (GCallback) on_raw_dpad_event,
+ self,
+ 0);
+ g_signal_connect_object (raw_gamepad,
+ "unplugged",
+ (GCallback) on_unplugged,
+ self,
+ 0);
+
+ return self;
+}
+
+/* Type */
+
+static void finalize (GObject *obj) {
+ GamesGamepad *self;
+ self = G_TYPE_CHECK_INSTANCE_CAST (obj, GAMES_TYPE_GAMEPAD, GamesGamepad);
+ g_object_unref (self->raw_gamepad);
+ g_object_unref (self->mapping);
+ G_OBJECT_CLASS (games_gamepad_parent_class)->finalize (obj);
+}
+
+static void games_gamepad_class_init (GamesGamepadClass *klass) {
+ games_gamepad_parent_class = g_type_class_peek_parent (klass);
+ G_OBJECT_CLASS (klass)->finalize = finalize;
+
+ /**
+ * GamesGamepad::axis-event:
+ * @button: the code representing the button
+ * @value: %TRUE if the button is pressed, %FALSE otherwise
+ *
+ * Emitted when a button is pressed/released.
+ */
+ signals[SIGNAL_BUTTON_EVENT] =
+ g_signal_new ("button-event",
+ GAMES_TYPE_GAMEPAD,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 2,
+ GAMES_TYPE_STANDARD_GAMEPAD_BUTTON,
+ G_TYPE_BOOLEAN);
+
+ /**
+ * GamesGamepad::axis-event:
+ * @axis: the code representing the axis
+ * @value: the value of the axis ranging from -1 to 1
+ *
+ * Emitted when a standard 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,
+ GAMES_TYPE_STANDARD_GAMEPAD_AXIS,
+ G_TYPE_DOUBLE);
+
+ /**
+ * GamesGamepad::unplugged:
+ *
+ * Emitted when the gamepad is unplugged.
+ */
+ signals[SIGNAL_UNPLUGGED] =
+ g_signal_new ("unplugged",
+ GAMES_TYPE_GAMEPAD,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void games_gamepad_init (GamesGamepad *self) {
+}
diff --git a/src/gamepad/gamepad.h b/src/gamepad/gamepad.h
new file mode 100644
index 0000000..cb8c1a0
--- /dev/null
+++ b/src/gamepad/gamepad.h
@@ -0,0 +1,20 @@
+// This file is part of GNOME Games. License: GPL-3.0+.
+
+#ifndef GAMES_GAMEPAD_H
+#define GAMES_GAMEPAD_H
+
+#include <glib-object.h>
+#include "raw-gamepad.h"
+
+G_BEGIN_DECLS
+
+#define GAMES_TYPE_GAMEPAD (games_gamepad_get_type())
+
+G_DECLARE_FINAL_TYPE (GamesGamepad, games_gamepad, GAMES, GAMEPAD, GObject)
+
+GamesGamepad *games_gamepad_new (GamesRawGamepad *raw_gamepad,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* GAMES_GAMEPAD_H */
diff --git a/src/gamepad/gamepad.vapi b/src/gamepad/gamepad.vapi
new file mode 100644
index 0000000..e852525
--- /dev/null
+++ b/src/gamepad/gamepad.vapi
@@ -0,0 +1,9 @@
+// This file is part of GNOME Games. License: GPL-3.0+.
+
+[CCode (cheader_filename = "gamepad.h")]
+private class Games.Gamepad : GLib.Object {
+ public signal void button_event (StandardGamepadButton button, bool value);
+ public signal void axis_event (StandardGamepadAxis axis, double value);
+ public signal void unplugged ();
+ public Gamepad (RawGamepad raw_gamepad) throws Error;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]