[retro-gtk/wip/aplazas/c-port: 23/36] Merge InputDeviceManager into Core



commit 96001432c198f45fc7a5e32103c20c1167ef34c2
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                         |    5 +-
 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         |   57 +++++++
 retro-gtk/retro-controller-iterator.h         |   25 +++
 retro-gtk/retro-core-private.h                |    1 +
 retro-gtk/retro-core.c                        |  218 ++++++++++++++++++++-----
 retro-gtk/retro-environment.c                 |   33 +----
 retro-gtk/vapi/retro-gtk-c.vapi               |    5 +
 12 files changed, 308 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 1364453..b566b58 100644
--- a/retro-gtk/Makefile.am
+++ b/retro-gtk/Makefile.am
@@ -33,6 +33,7 @@ retro_gtk_public_h_sources = \
        retro-analog-id.h \
        retro-analog-index.h \
        retro-cairo-display.h \
+       retro-controller-iterator.h \
        retro-core-descriptor.h \
        retro-core-view.h \
        retro-device-type.h \
@@ -57,6 +58,7 @@ retro_gtk_public_h_sources = \
 retro_gtk_private_h_sources = \
        input/retro-keyboard-key.h \
        libretro-environment.h \
+       retro-controller-iterator-private.h \
        retro-core-private.h \
        retro-core-view-input-device.h \
        retro-disk-control-callback.h \
@@ -72,14 +74,13 @@ 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 \
        core-error.vala \
        retro.vala \
        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..e90c698
--- /dev/null
+++ b/retro-gtk/retro-controller-iterator.c
@@ -0,0 +1,57 @@
+// 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)
+{
+}
+
+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);
+}
+
+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..6c91dae
--- /dev/null
+++ b/retro-gtk/retro-controller-iterator.h
@@ -0,0 +1,25 @@
+// 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>
+
+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..4306c3a 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,146 @@ retro_core_set_memory (RetroCore       *self,
   memcpy (memory_region, data, length);
   memset (memory_region + length, 0, memory_region_size - length);
 }
+
+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);
+}
+
+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;
+}
+
+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);
+}
+
+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);
+  }
+}
+
+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);
+
+  g_hash_table_remove (internal->controllers, &port);
+  retro_core_controller_disconnected (self, port);
+}
+
+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]