[retro-gtk/wip/aplazas/c-port: 4/15] Merge InputDeviceManager into Core
- From: Adrien Plazas <aplazas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [retro-gtk/wip/aplazas/c-port: 4/15] Merge InputDeviceManager into Core
- Date: Tue, 10 Oct 2017 17:05:06 +0000 (UTC)
commit 50dc2a983928ccabad0564ba72093b64525abeb5
Author: Adrien Plazas <kekun plazas laposte net>
Date: Sat Sep 23 15:42:47 2017 +0200
Merge InputDeviceManager into Core
Implement most of it in C.
Also drop the now useless Input interface.
demos/retro-demo.c | 11 +-
retro-gtk/Makefile.am | 6 +-
retro-gtk/core.vala | 53 ++----
retro-gtk/input/input-device-manager.vala | 70 -------
retro-gtk/input/input.vala | 51 -----
retro-gtk/retro-controller-iterator-private.h | 19 ++
retro-gtk/retro-controller-iterator.c | 77 +++++++
retro-gtk/retro-controller-iterator.h | 26 +++
retro-gtk/retro-core-private.h | 1 +
retro-gtk/retro-core.c | 269 +++++++++++++++++++++----
retro-gtk/retro-environment.c | 33 +---
retro-gtk/vapi/retro-gtk-c.vapi | 5 +
12 files changed, 381 insertions(+), 240 deletions(-)
---
diff --git a/demos/retro-demo.c b/demos/retro-demo.c
index 85be684..39078e9 100644
--- a/demos/retro-demo.c
+++ b/demos/retro-demo.c
@@ -14,7 +14,6 @@ struct _RetroDemoApplication
GtkApplicationWindow *window;
RetroCore *core;
- RetroInputDeviceManager *input;
RetroMainLoop *loop;
RetroCoreView *view;
};
@@ -54,9 +53,6 @@ retro_demo_open (GApplication *application,
return;
}
- self->input = retro_input_device_manager_new ();
- retro_core_set_input_interface (self->core, RETRO_INPUT (self->input));
-
g_application_activate (application);
}
@@ -74,9 +70,6 @@ retro_demo_application_finalize (GObject *object)
if (self->core != NULL)
g_object_unref (self->core);
- if (self->input != NULL)
- g_object_unref (self->input);
-
if (self->loop != NULL)
g_object_unref (self->loop);
@@ -98,9 +91,9 @@ retro_demo_activate (GApplication *application)
self->view = retro_core_view_new ();
retro_core_view_set_core (self->view, self->core);
- retro_input_device_manager_set_keyboard (self->input, GTK_WIDGET (self->view));
+ retro_core_set_keyboard (self->core, GTK_WIDGET (self->view));
input_device = retro_core_view_as_input_device (self->view, RETRO_DEVICE_TYPE_POINTER);
- retro_input_device_manager_set_controller_device (self->input, 0, input_device);
+ retro_core_set_controller (self->core, 0, input_device);
g_object_unref (input_device);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
diff --git a/retro-gtk/Makefile.am b/retro-gtk/Makefile.am
index e510d90..80010ed 100644
--- a/retro-gtk/Makefile.am
+++ b/retro-gtk/Makefile.am
@@ -32,6 +32,8 @@ BUILT_SOURCES = retro-gtk-internal.h
retro_gtk_public_h_sources = \
retro-analog-id.h \
retro-analog-index.h \
+ retro-controller-iterator.h \
+ retro-core-descriptor.h \
retro-core-view.h \
retro-device-type.h \
retro-gtk.h \
@@ -54,6 +56,7 @@ retro_gtk_private_h_sources = \
input/retro-keyboard-key.h \
libretro-environment.h \
retro-cairo-display.h \
+ retro-controller-iterator-private.h \
retro-core-private.h \
retro-core-view-input-device.h \
retro-disk-control-callback.h \
@@ -71,8 +74,6 @@ retro_gtk_private_h_sources = \
libretro_gtk_la_SOURCES = \
input/controller.vala \
- input/input.vala \
- input/input-device-manager.vala \
input/retro-keyboard-key.c \
\
core.vala \
@@ -81,6 +82,7 @@ libretro_gtk_la_SOURCES = \
retro-analog-id.c \
retro-analog-index.c \
retro-cairo-display.c \
+ retro-controller-iterator.c \
retro-core-descriptor.c \
retro-core-view.c \
retro-core-view-input-device.c \
diff --git a/retro-gtk/core.vala b/retro-gtk/core.vala
index 3778337..9dae0cc 100644
--- a/retro-gtk/core.vala
+++ b/retro-gtk/core.vala
@@ -85,41 +85,6 @@ public class Core : Object {
get { return _frames_per_second; }
}
- private weak Input _input_interface;
- private ulong input_controller_connected_id;
- private ulong input_controller_disconnected_id;
- private ulong input_key_event_id;
- /**
- * The input interface.
- *
- * It must be set before {@link init} is called.
- */
- public Input input_interface {
- get { return _input_interface; }
- construct set {
- if (value == input_interface)
- return;
-
- if (input_interface != null) {
- input_interface.disconnect (input_controller_connected_id);
- input_interface.disconnect (input_controller_disconnected_id);
- input_interface.disconnect (input_key_event_id);
- }
-
- _input_interface = value;
-
- if (input_interface == null)
- return;
-
- input_interface.controller_connected.connect (on_input_controller_connected);
- input_interface.controller_disconnected.connect (on_input_controller_disconnected);
- input_interface.key_event.connect (on_key_event);
-
- if (is_initiated)
- init_input ();
- }
- }
-
/**
* The rumble interface.
*
@@ -139,6 +104,9 @@ public class Core : Object {
public signal bool message (string message, uint frames);
internal void *environment_internal;
+ internal Gtk.Widget keyboard_widget;
+ internal ulong key_press_event_id;
+ internal ulong key_release_event_id;
/**
* Creates a Core from the file name of a Libretro implementation.
@@ -224,10 +192,17 @@ public class Core : Object {
*/
public extern void set_memory (MemoryType id, uint8[] data);
- private extern void init_input ();
- private extern void on_input_controller_connected (uint port, InputDevice device);
- private extern void on_input_controller_disconnected (uint port);
- private extern bool on_key_event (Gdk.EventKey event);
+ public extern void poll_controllers ();
+ public extern int16 get_controller_input_state (uint port, DeviceType device, uint index, uint id);
+ public extern void set_controller_descriptors ([CCode (array_length_type = "gsize")]
InputDescriptor[] input_descriptors);
+ public extern uint64 get_controller_capabilities ();
+ public extern void set_controller (uint port, InputDevice device);
+ public extern void set_keyboard (Gtk.Widget widget);
+ public extern void remove_controller (uint port);
+ public extern ControllerIterator iterate_controllers ();
+ private extern void controller_connected (uint port, InputDevice device);
+ private extern void controller_disconnected (uint port);
+ private extern bool key_event (Gdk.EventKey event);
}
}
diff --git a/retro-gtk/retro-controller-iterator-private.h b/retro-gtk/retro-controller-iterator-private.h
new file mode 100644
index 0000000..d787a02
--- /dev/null
+++ b/retro-gtk/retro-controller-iterator-private.h
@@ -0,0 +1,19 @@
+// This file is part of retro-gtk. License: GPL-3.0+.
+
+#ifndef RETRO_CONTROLLER_ITERATOR_PRIVATE_H
+#define RETRO_CONTROLLER_ITERATOR_PRIVATE_H
+
+#if !defined(__RETRO_GTK_INSIDE__) && !defined(RETRO_GTK_COMPILATION)
+# error "Only <retro-gtk.h> can be included directly."
+#endif
+
+#include "retro-controller-iterator.h"
+
+G_BEGIN_DECLS
+
+RetroControllerIterator *retro_controller_iterator_new (GHashTable *controllers);
+
+G_END_DECLS
+
+#endif /* RETRO_CONTROLLER_ITERATOR_PRIVATE_H */
+
diff --git a/retro-gtk/retro-controller-iterator.c b/retro-gtk/retro-controller-iterator.c
new file mode 100644
index 0000000..69e9413
--- /dev/null
+++ b/retro-gtk/retro-controller-iterator.c
@@ -0,0 +1,77 @@
+// This file is part of retro-gtk. License: GPL-3.0+.
+
+#include "retro-controller-iterator.h"
+
+struct _RetroControllerIterator
+{
+ GObject parent_instance;
+ GHashTableIter iterator;
+};
+
+G_DEFINE_TYPE (RetroControllerIterator, retro_controller_iterator, G_TYPE_OBJECT)
+
+/* Private */
+
+static void
+retro_controller_iterator_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (retro_controller_iterator_parent_class)->finalize (object);
+}
+
+static void
+retro_controller_iterator_class_init (RetroControllerIteratorClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = retro_controller_iterator_finalize;
+}
+
+static void
+retro_controller_iterator_init (RetroControllerIterator *self)
+{
+}
+
+/* Public */
+
+/**
+ * retro_controller_iterator_next:
+ * @self: a #RetroControllerIterator
+ * @port: (out) (optional): return location for the port
+ * @controller: (out) (optional) (nullable): return location for the controller
+ *
+ * Fetch the next #RetroInputDevice and the port number it is plugged into.
+ *
+ * Returns: %FALSE if it reached the end, %TRUE otherwise
+ */
+gboolean
+retro_controller_iterator_next (RetroControllerIterator *self,
+ guint **port,
+ RetroInputDevice **controller)
+{
+ g_return_val_if_fail (RETRO_IS_CONTROLLER_ITERATOR (self), FALSE);
+ g_return_val_if_fail (port != NULL, FALSE);
+ g_return_val_if_fail (controller != NULL, FALSE);
+
+ return g_hash_table_iter_next (&self->iterator, (gpointer *) port, (gpointer *) controller);
+}
+
+/**
+ * retro_controller_iterator_new:
+ * @controllers: (element-type guint RetroInputDevice): A #GHashTable
+ *
+ * Creates a new #RetroControllerIterator.
+ *
+ * Returns: (transfer full): a new #RetroControllerIterator
+ */
+RetroControllerIterator *
+retro_controller_iterator_new (GHashTable *controllers)
+{
+ RetroControllerIterator *self;
+
+ g_return_val_if_fail (controllers != NULL, NULL);
+
+ self = g_object_new (RETRO_TYPE_CONTROLLER_ITERATOR, NULL);
+ g_hash_table_iter_init (&self->iterator, controllers);
+
+ return self;
+}
diff --git a/retro-gtk/retro-controller-iterator.h b/retro-gtk/retro-controller-iterator.h
new file mode 100644
index 0000000..aad2505
--- /dev/null
+++ b/retro-gtk/retro-controller-iterator.h
@@ -0,0 +1,26 @@
+// This file is part of retro-gtk. License: GPL-3.0+.
+
+#ifndef RETRO_CONTROLLER_ITERATOR_H
+#define RETRO_CONTROLLER_ITERATOR_H
+
+#if !defined(__RETRO_GTK_INSIDE__) && !defined(RETRO_GTK_COMPILATION)
+# error "Only <retro-gtk.h> can be included directly."
+#endif
+
+#include <glib-object.h>
+#include "retro-input-device.h"
+
+G_BEGIN_DECLS
+
+#define RETRO_TYPE_CONTROLLER_ITERATOR (retro_controller_iterator_get_type())
+
+G_DECLARE_FINAL_TYPE (RetroControllerIterator, retro_controller_iterator, RETRO, CONTROLLER_ITERATOR,
GObject)
+
+gboolean retro_controller_iterator_next (RetroControllerIterator *self,
+ guint **port,
+ RetroInputDevice **controller);
+
+G_END_DECLS
+
+#endif /* RETRO_CONTROLLER_ITERATOR_H */
+
diff --git a/retro-gtk/retro-core-private.h b/retro-gtk/retro-core-private.h
index aedb5e0..31d260b 100644
--- a/retro-gtk/retro-core-private.h
+++ b/retro-gtk/retro-core-private.h
@@ -36,6 +36,7 @@ struct _RetroCoreEnvironmentInternal {
gdouble sample_rate;
RetroKeyboardCallback keyboard_callback;
+ GHashTable *controllers;
RetroOptions *options;
};
diff --git a/retro-gtk/retro-core.c b/retro-gtk/retro-core.c
index ef9432b..b055732 100644
--- a/retro-gtk/retro-core.c
+++ b/retro-gtk/retro-core.c
@@ -2,6 +2,7 @@
#include "retro-core-private.h"
+#include "retro-controller-iterator-private.h"
#include "retro-gtk-internal.h"
#include "input/retro-keyboard-key.h"
@@ -130,43 +131,11 @@ retro_core_get_name (RetroCore *self)
return system_info.library_name;
}
-static void
-init_controller_device (guint port,
- RetroInputDevice *device,
- gpointer data)
-{
- RetroCore *self;
- RetroDeviceType device_type;
-
- self = RETRO_CORE (data);
-
- g_return_if_fail (self != NULL);
- g_return_if_fail (device != NULL);
-
- device_type = retro_input_device_get_device_type (device);
- retro_core_set_controller_port_device (self, port, device_type);
-}
-
// FIXME Make static as soon as possible.
void
-retro_core_init_input (RetroCore* self)
-{
- RetroInput* input_interface;
-
- g_return_if_fail (self != NULL);
-
- input_interface = retro_core_get_input_interface (self);
- if (input_interface == NULL)
- return;
-
- retro_input_foreach_controller (input_interface, init_controller_device, self);
-}
-
-// FIXME Make static as soon as possible.
-void
-retro_core_on_input_controller_connected (RetroCore *self,
- guint port,
- RetroInputDevice *device)
+retro_core_controller_connected (RetroCore *self,
+ guint port,
+ RetroInputDevice *device)
{
RetroDeviceType device_type;
@@ -182,8 +151,8 @@ retro_core_on_input_controller_connected (RetroCore *self,
// FIXME Make static as soon as possible.
void
-retro_core_on_input_controller_disconnected (RetroCore *self,
- guint port)
+retro_core_controller_disconnected (RetroCore *self,
+ guint port)
{
g_return_if_fail (self != NULL);
@@ -214,8 +183,8 @@ retro_core_send_input_key_event (RetroCore *self,
// FIXME Make static as soon as possible.
gboolean
-retro_core_on_key_event (RetroCore *self,
- GdkEventKey *event)
+retro_core_key_event (RetroCore *self,
+ GdkEventKey *event)
{
gboolean pressed;
RetroKeyboardKey retro_key;
@@ -668,6 +637,8 @@ retro_core_constructor (RetroCore *self,
g_free (libretro_path);
retro_core_set_callbacks (self);
+ internal->controllers = g_hash_table_new_full (g_int_hash, g_int_equal,
+ g_free, g_object_unref);
internal->options = retro_options_new ();
}
@@ -696,11 +667,24 @@ retro_core_destructor (RetroCore *self)
g_strfreev (internal->media_uris);
g_object_unref (internal->module);
+ g_hash_table_unref (internal->controllers);
g_object_unref (internal->options);
g_free (self->environment_internal);
}
+static gboolean
+on_key_event (GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer self)
+{
+ g_return_val_if_fail (RETRO_IS_CORE (self), FALSE);
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ return retro_core_key_event (RETRO_CORE (self), event);
+}
+
/* Public */
void
@@ -709,6 +693,10 @@ retro_core_init (RetroCore *self,
{
RetroCoreEnvironmentInternal *internal;
RetroInit init;
+ RetroControllerIterator *controller_iterator;
+ guint *port;
+ RetroInputDevice *controller;
+ RetroDeviceType device_type;
GError *tmp_error = NULL;
g_return_if_fail (self != NULL);
@@ -722,7 +710,14 @@ retro_core_init (RetroCore *self,
init ();
retro_core_pop_cb_data ();
- retro_core_init_input (self);
+ controller_iterator = retro_core_iterate_controllers (self);
+ while (retro_controller_iterator_next (controller_iterator,
+ &port,
+ &controller)) {
+ device_type = retro_input_device_get_device_type (controller);
+ retro_core_set_controller_port_device (self, *port, device_type);
+ }
+ g_object_unref (controller_iterator);
retro_core_set_is_initiated (self, TRUE);
@@ -1060,3 +1055,197 @@ retro_core_set_memory (RetroCore *self,
memcpy (memory_region, data, length);
memset (memory_region + length, 0, memory_region_size - length);
}
+
+/**
+ * retro_core_poll_controllers:
+ * @self: a #RetroCore
+ *
+ * Polls the pending input events for the controllers plugged into @self.
+ */
+void
+retro_core_poll_controllers (RetroCore *self)
+{
+ RetroControllerIterator *iterator;
+ guint *port;
+ RetroInputDevice *controller;
+
+ g_return_if_fail (RETRO_IS_CORE (self));
+
+ iterator = retro_core_iterate_controllers (self);
+ while (retro_controller_iterator_next (iterator, &port, &controller))
+ if (controller != NULL)
+ retro_input_device_poll (controller);
+ g_object_unref (iterator);
+}
+
+/**
+ * retro_core_get_controller_input_state:
+ * @self: a #RetroCore
+ * @port: the port number
+ * @controller_type: a #RetroDeviceType to query @self
+ * @index: an input index to interpret depending on @controller_type
+ * @id: an input id to interpret depending on @controller_type
+ *
+ * Gets the state of an input of the controller plugged into the given port of
+ * @self.
+ *
+ * Returns: the input's state
+ */
+gint16
+retro_core_get_controller_input_state (RetroCore *self,
+ guint port,
+ RetroDeviceType controller_type,
+ guint index,
+ guint id)
+{
+ RetroCoreEnvironmentInternal *internal;
+ RetroInputDevice *controller;
+
+ g_return_val_if_fail (RETRO_IS_CORE (self), 0);
+
+ internal = RETRO_CORE_ENVIRONMENT_INTERNAL (self);
+
+ if (!g_hash_table_contains (internal->controllers, &port))
+ return 0;
+
+ controller = g_hash_table_lookup (internal->controllers, &port);
+
+ if (controller == NULL)
+ return 0;
+
+ if ((retro_input_device_get_device_capabilities (controller) & (1 << controller_type)) == 0)
+ return 0;
+
+ return retro_input_device_get_input_state (controller,
+ controller_type,
+ index,
+ id);
+}
+
+void
+retro_core_set_controller_descriptors (RetroCore *self,
+ RetroInputDescriptor *input_descriptors,
+ gsize input_descriptors_length)
+{
+ g_return_if_fail (RETRO_IS_CORE (self));
+
+ // TODO
+}
+
+guint64
+retro_core_get_controller_capabilities (RetroCore *self)
+{
+ g_return_val_if_fail (RETRO_IS_CORE (self), 0);
+
+ // TODO
+
+ return 0;
+}
+
+/**
+ * retro_core_set_controller:
+ * @self: a #RetroCore
+ * @port: the port number
+ * @controller: (nullable): a #RetroInputDevice
+ *
+ * Plugs @controller into the specified port number of @self.
+ */
+void
+retro_core_set_controller (RetroCore *self,
+ guint port,
+ RetroInputDevice *controller)
+{
+ RetroCoreEnvironmentInternal *internal;
+ guint *port_copy;
+
+ g_return_if_fail (RETRO_IS_CORE (self));
+ g_return_if_fail (RETRO_IS_INPUT_DEVICE (controller));
+
+ internal = RETRO_CORE_ENVIRONMENT_INTERNAL (self);
+
+ port_copy = g_new (guint, 1);
+ *port_copy = port;
+ g_hash_table_insert (internal->controllers,
+ port_copy,
+ g_object_ref (controller));
+ retro_core_controller_connected (self, port, controller);
+}
+
+/**
+ * retro_core_set_keyboard:
+ * @self: a #RetroCore
+ * @widget: (nullable): a #GtkWidget, or %NULL
+ *
+ * Sets the widget whose key events will be forwarded to @self.
+ */
+void
+retro_core_set_keyboard (RetroCore *self,
+ GtkWidget *widget)
+{
+ g_return_if_fail (self != NULL);
+
+ if (self->keyboard_widget != NULL) {
+ g_signal_handler_disconnect (G_OBJECT (self->keyboard_widget), self->key_press_event_id);
+ g_signal_handler_disconnect (G_OBJECT (self->keyboard_widget), self->key_release_event_id);
+ g_clear_object (&self->keyboard_widget);
+ }
+
+ if (widget != NULL) {
+ self->key_press_event_id =
+ g_signal_connect_object (widget,
+ "key-press-event",
+ G_CALLBACK (on_key_event),
+ self,
+ 0);
+ self->key_release_event_id =
+ g_signal_connect_object (widget,
+ "key-release-event",
+ G_CALLBACK (on_key_event),
+ self,
+ 0);
+ self->keyboard_widget = g_object_ref (widget);
+ }
+}
+
+/**
+ * retro_core_remove_controller:
+ * @self: a #RetroCore
+ * @port: the port number
+ *
+ * Removes the controller plugged into @self at port @port, if any.
+ */
+void
+retro_core_remove_controller (RetroCore *self,
+ guint port)
+{
+ RetroCoreEnvironmentInternal *internal;
+
+ g_return_if_fail (RETRO_IS_CORE (self));
+
+ internal = RETRO_CORE_ENVIRONMENT_INTERNAL (self);
+
+ // FIXME Do that only if a controller is plugged into that port.
+ g_hash_table_remove (internal->controllers, &port);
+ retro_core_controller_disconnected (self, port);
+}
+
+/**
+ * retro_core_iterate_controllers:
+ * @self: a #RetroCore
+ *
+ * Creates a new #RetroControllerIterator which can be used to iterate through
+ * the controllers plugged into @self.
+ *
+ * Returns: (transfer full): a new #RetroControllerIterator
+ */
+RetroControllerIterator *
+retro_core_iterate_controllers (RetroCore *self)
+{
+ RetroCoreEnvironmentInternal *internal;
+
+ g_return_val_if_fail (RETRO_IS_CORE (self), NULL);
+
+ internal = RETRO_CORE_ENVIRONMENT_INTERNAL (self);
+
+ return retro_controller_iterator_new (internal->controllers);
+}
diff --git a/retro-gtk/retro-environment.c b/retro-gtk/retro-environment.c
index 32d8c93..7346db8 100644
--- a/retro-gtk/retro-environment.c
+++ b/retro-gtk/retro-environment.c
@@ -121,14 +121,7 @@ static gboolean
get_input_device_capabilities (RetroCore *self,
guint64 *capabilities)
{
- RetroInput *input;
-
- input = retro_core_get_input_interface (self);
-
- if (input == NULL)
- return FALSE;
-
- *capabilities = retro_input_get_device_capabilities (input);
+ *capabilities = retro_core_get_controller_capabilities (self);
return TRUE;
}
@@ -235,16 +228,10 @@ static gboolean
set_input_descriptors (RetroCore *self,
RetroInputDescriptor *descriptors)
{
- RetroInput *input;
int length;
- input = retro_core_get_input_interface (self);
-
- if (input == NULL)
- return FALSE;
-
for (length = 0 ; descriptors[length].description ; length++);
- retro_input_set_descriptors (input, descriptors, length);
+ retro_core_set_controller_descriptors (self, descriptors, length);
return TRUE;
}
@@ -515,19 +502,13 @@ static void
on_input_poll ()
{
RetroCore *self;
- RetroInput *input;
self = retro_core_get_cb_data ();
if (self == NULL)
g_return_if_reached ();
- input = retro_core_get_input_interface (self);
-
- if (input == NULL)
- return;
-
- retro_input_poll (input);
+ retro_core_poll_controllers (self);
}
static gint16
@@ -537,19 +518,13 @@ on_input_state (guint port,
guint id)
{
RetroCore *self;
- RetroInput *input;
self = retro_core_get_cb_data ();
if (self == NULL)
g_return_val_if_reached (0);
- input = retro_core_get_input_interface (self);
-
- if (input == NULL)
- return 0;
-
- return retro_input_get_state (input, port, device, index, id);
+ return retro_core_get_controller_input_state (self, port, device, index, id);
}
// TODO This is internal, make it private as soon as possible.
diff --git a/retro-gtk/vapi/retro-gtk-c.vapi b/retro-gtk/vapi/retro-gtk-c.vapi
index bf0ea78..a0ab6a8 100644
--- a/retro-gtk/vapi/retro-gtk-c.vapi
+++ b/retro-gtk/vapi/retro-gtk-c.vapi
@@ -52,3 +52,8 @@ public struct Retro.InputDescriptor {
uint id;
string description;
}
+
+[CCode (cheader_filename = "retro-controller-iterator.h")]
+public class Retro.ControllerIterator : GLib.Object {
+ public extern bool next (out unowned uint? port, out unowned InputDevice controller);
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]