[retro-gtk/wip/aplazas/master] Port MainLoop to C
- From: Adrien Plazas <aplazas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [retro-gtk/wip/aplazas/master] Port MainLoop to C
- Date: Sun, 8 Oct 2017 08:03:37 +0000 (UTC)
commit 6bd512501ce0ed2389d5cd39ec2d17d4f2267f0a
Author: Adrien Plazas <kekun plazas laposte net>
Date: Fri Sep 8 13:03:49 2017 +0200
Port MainLoop to C
retro-gtk/Makefile.am | 6 +-
retro-gtk/loop/main-loop.vala | 104 ------------
retro-gtk/retro-gtk.h | 1 +
retro-gtk/retro-main-loop.c | 349 +++++++++++++++++++++++++++++++++++++++++
retro-gtk/retro-main-loop.h | 33 ++++
5 files changed, 387 insertions(+), 106 deletions(-)
---
diff --git a/retro-gtk/Makefile.am b/retro-gtk/Makefile.am
index bd0edee..e510d90 100644
--- a/retro-gtk/Makefile.am
+++ b/retro-gtk/Makefile.am
@@ -40,6 +40,7 @@ retro_gtk_public_h_sources = \
retro-joypad-id.h \
retro-lightgun-id.h \
retro-log.h \
+ retro-main-loop.h \
retro-memory-type.h \
retro-module-iterator.h \
retro-module-query.h \
@@ -74,8 +75,6 @@ libretro_gtk_la_SOURCES = \
input/input-device-manager.vala \
input/retro-keyboard-key.c \
\
- loop/main-loop.vala \
- \
core.vala \
core-error.vala \
retro.vala \
@@ -92,6 +91,7 @@ libretro_gtk_la_SOURCES = \
retro-joypad-id.c \
retro-lightgun-id.c \
retro-log.c \
+ retro-main-loop.c \
retro-memory-type.c \
retro-module.c \
retro-module-iterator.c \
@@ -124,6 +124,8 @@ retro-environment.c: retro-gtk-internal.h libretro-environment.h
retro-log.c: retro-gtk-internal.h
+retro-main-loop.c: retro-gtk-internal.h
+
retro-module.c: retro-gtk-internal.h
retro-module-iterator.c: retro-gtk-internal.h
diff --git a/retro-gtk/retro-gtk.h b/retro-gtk/retro-gtk.h
index ef59b63..c16e249 100644
--- a/retro-gtk/retro-gtk.h
+++ b/retro-gtk/retro-gtk.h
@@ -19,6 +19,7 @@
#include "retro-joypad-id.h"
#include "retro-lightgun-id.h"
#include "retro-log.h"
+#include "retro-main-loop.h"
#include "retro-memory-type.h"
#include "retro-mouse-id.h"
#include "retro-pixel-format.h"
diff --git a/retro-gtk/retro-main-loop.c b/retro-gtk/retro-main-loop.c
new file mode 100644
index 0000000..43647f3
--- /dev/null
+++ b/retro-gtk/retro-main-loop.c
@@ -0,0 +1,349 @@
+// This file is part of retro-gtk. License: GPL-3.0+.
+
+#include "retro-main-loop.h"
+
+#include "retro-gtk-internal.h"
+
+struct _RetroMainLoop
+{
+ GObject parent_instance;
+ RetroCore *core;
+ gdouble speed_rate;
+ glong loop;
+ gulong core_fps_id;
+};
+
+G_DEFINE_TYPE (RetroMainLoop, retro_main_loop, G_TYPE_OBJECT)
+
+enum {
+ PROP_CORE = 1,
+ PROP_SPEED_RATE,
+ N_PROPS,
+};
+
+static GParamSpec *properties [N_PROPS];
+
+/* Private */
+
+static void
+retro_main_loop_finalize (GObject *object)
+{
+ RetroMainLoop *self = RETRO_MAIN_LOOP (object);
+
+ retro_main_loop_stop (self);
+ g_clear_object (&self->core);
+
+ G_OBJECT_CLASS (retro_main_loop_parent_class)->finalize (object);
+}
+
+static void
+retro_main_loop_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ RetroMainLoop *self = RETRO_MAIN_LOOP (object);
+
+ switch (prop_id) {
+ case PROP_CORE:
+ g_value_set_object (value, retro_main_loop_get_core (self));
+
+ break;
+ case PROP_SPEED_RATE:
+ g_value_set_double (value, retro_main_loop_get_speed_rate (self));
+
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+
+ break;
+ }
+}
+
+static void
+retro_main_loop_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ RetroMainLoop *self = RETRO_MAIN_LOOP (object);
+
+ switch (prop_id) {
+ case PROP_CORE:
+ retro_main_loop_set_core (self, g_value_get_object (value));
+
+ break;
+ case PROP_SPEED_RATE:
+ retro_main_loop_set_speed_rate (self, g_value_get_double (value));
+
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+
+ break;
+ }
+}
+
+static void
+retro_main_loop_class_init (RetroMainLoopClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = retro_main_loop_finalize;
+ object_class->get_property = retro_main_loop_get_property;
+ object_class->set_property = retro_main_loop_set_property;
+
+ properties[PROP_CORE] =
+ g_param_spec_object ("core",
+ "Core",
+ "The core",
+ RETRO_TYPE_CORE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB |
+ G_PARAM_CONSTRUCT);
+ g_object_class_install_property (G_OBJECT_CLASS (klass),
+ PROP_CORE,
+ properties[PROP_CORE]);
+
+ properties[PROP_SPEED_RATE] =
+ g_param_spec_double ("speed-rate",
+ "Speed rate",
+ "The speed ratio at wich the core will run",
+ -G_MAXDOUBLE, G_MAXDOUBLE, 1.0,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB |
+ G_PARAM_CONSTRUCT);
+ g_object_class_install_property (G_OBJECT_CLASS (klass),
+ PROP_SPEED_RATE,
+ properties[PROP_SPEED_RATE]);
+}
+
+static void
+retro_main_loop_on_notification (GObject *src,
+ GParamSpec *param,
+ gpointer user_data)
+{
+ RetroMainLoop *self = RETRO_MAIN_LOOP (user_data);
+ const gchar *param_name;
+
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (src != NULL);
+ g_return_if_fail (param != NULL);
+
+ if (self->loop < 0)
+ return;
+
+ param_name = g_param_spec_get_name (param);
+ if (g_strcmp0 (param_name, "speed-rate") != 0)
+ return;
+
+ retro_main_loop_stop (self);
+ retro_main_loop_start (self);
+}
+
+static void
+retro_main_loop_on_frames_per_second_changed (GObject *sender,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ RetroMainLoop *self = RETRO_MAIN_LOOP (user_data);
+
+ g_return_if_fail (self != NULL);
+
+ if (self->loop < 0)
+ return;
+
+ retro_main_loop_stop (self);
+ retro_main_loop_start (self);
+}
+
+static void
+retro_main_loop_init (RetroMainLoop *self)
+{
+ self->loop = -1;
+
+ g_signal_connect_object (G_OBJECT (self),
+ "notify",
+ (GCallback) retro_main_loop_on_notification,
+ self,
+ 0);
+}
+
+static gboolean
+retro_main_loop_run (RetroMainLoop *self)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+
+ if (self->core == NULL || self->loop < 0)
+ return FALSE;
+
+ retro_core_run (self->core);
+
+ return TRUE;
+}
+
+/* Public */
+
+/**
+ * retro_main_loop_get_speed_rate:
+ * @self: a #RetroMainLoop
+ *
+ * Gets the speed rate at which to run the core.
+ *
+ * Returns: the speed rate
+ */
+gdouble
+retro_main_loop_get_speed_rate (RetroMainLoop *self)
+{
+ g_return_val_if_fail (self != NULL, 1.0);
+
+ return self->speed_rate;
+}
+
+/**
+ * retro_main_loop_get_core:
+ * @self: a #RetroMainLoop
+ *
+ * Gets the core handled by @self.
+ *
+ * Returns: (transfer none): a #RetroCore
+ */
+RetroCore *
+retro_main_loop_get_core (RetroMainLoop *self)
+{
+ g_return_val_if_fail (self != NULL, NULL);
+
+ return self->core;
+}
+
+/**
+ * retro_main_loop_set_core:
+ * @self: a #RetroMainLoop
+ * @core: (nullable): a #RetroCore, or %NULL
+ *
+ * Sets @core as the #RetroCore handled by @self.
+ */
+void
+retro_main_loop_set_core (RetroMainLoop *self,
+ RetroCore *core)
+{
+ g_return_if_fail (self != NULL);
+
+ if (self->core == core)
+ return;
+
+ retro_main_loop_stop (self);
+
+ if (self->core != NULL) {
+ g_signal_handler_disconnect (G_OBJECT (self->core), self->core_fps_id);
+ g_clear_object (&self->core);
+ }
+
+ if (core != NULL) {
+ self->core = g_object_ref (core);
+ self->core_fps_id =
+ g_signal_connect_object (G_OBJECT (self->core),
+ "notify::frames-per-second",
+ (GCallback) retro_main_loop_on_frames_per_second_changed,
+ self,
+ 0);
+ }
+
+ g_object_notify_by_pspec ((GObject *) self, properties[PROP_CORE]);
+}
+
+/**
+ * retro_main_loop_get_speed_rate:
+ * @self: a #RetroMainLoop
+ * @speed_rate: a speed rate
+ *
+ * Sets the speed rate at which to run the core.
+ */
+void
+retro_main_loop_set_speed_rate (RetroMainLoop *self,
+ gdouble speed_rate)
+{
+ g_return_if_fail (self != NULL);
+
+ if (self->speed_rate == speed_rate)
+ return;
+
+ self->speed_rate = speed_rate;
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SPEED_RATE]);
+}
+
+/**
+ * retro_main_loop_start:
+ * @self: a #RetroMainLoop
+ *
+ * Starts runing the core. If the core was stopped, it will restart from this moment.
+ */
+void
+retro_main_loop_start (RetroMainLoop *self)
+{
+ gdouble fps;
+
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (self->core != NULL);
+
+ if (self->loop >= 0 || self->speed_rate <= 0)
+ return;
+
+ // TODO What if fps <= 0?
+ fps = retro_core_get_frames_per_second (self->core);
+ self->loop = g_timeout_add_full (G_PRIORITY_DEFAULT,
+ (guint) (1000 / (fps * self->speed_rate)),
+ (GSourceFunc) retro_main_loop_run,
+ g_object_ref (self),
+ g_object_unref);
+}
+
+/**
+ * retro_main_loop_reset:
+ * @self: a #RetroMainLoop
+ *
+ * Resets the core. Results depend on the core's implementation.
+ */
+void
+retro_main_loop_reset (RetroMainLoop *self)
+{
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (self->core != NULL);
+
+ retro_core_reset (self->core);
+}
+
+/**
+ * retro_main_loop_stop:
+ * @self: a #RetroMainLoop
+ *
+ * Stops runing the core.
+ */
+void
+retro_main_loop_stop (RetroMainLoop *self)
+{
+ g_return_if_fail (self != NULL);
+
+ if (self->loop < 0)
+ return;
+
+ g_source_remove (self->loop);
+ self->loop = -1;
+}
+
+/**
+ * retro_main_loop_new:
+ *
+ * Creates a new #RetroMainLoop.
+ *
+ * Returns: (transfer full): a new #RetroMainLoop
+ */
+RetroMainLoop *
+retro_main_loop_new (RetroCore *core)
+{
+ return g_object_new (RETRO_TYPE_MAIN_LOOP, "core", core, NULL);
+}
diff --git a/retro-gtk/retro-main-loop.h b/retro-gtk/retro-main-loop.h
new file mode 100644
index 0000000..ccf858f
--- /dev/null
+++ b/retro-gtk/retro-main-loop.h
@@ -0,0 +1,33 @@
+// This file is part of retro-gtk. License: GPL-3.0+.
+
+#ifndef RETRO_MAIN_LOOP_H
+#define RETRO_MAIN_LOOP_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
+
+// FIXME Remove as soon as possible.
+typedef struct _RetroCore RetroCore;
+
+#define RETRO_TYPE_MAIN_LOOP (retro_main_loop_get_type())
+
+G_DECLARE_FINAL_TYPE (RetroMainLoop, retro_main_loop, RETRO, MAIN_LOOP, GObject)
+
+RetroMainLoop *retro_main_loop_new (RetroCore *core);
+RetroCore *retro_main_loop_get_core (RetroMainLoop *self);
+void retro_main_loop_set_core (RetroMainLoop *self, RetroCore *value);
+void retro_main_loop_start (RetroMainLoop *self);
+void retro_main_loop_reset (RetroMainLoop *self);
+void retro_main_loop_stop (RetroMainLoop *self);
+gdouble retro_main_loop_get_speed_rate (RetroMainLoop *self);
+void retro_main_loop_set_speed_rate (RetroMainLoop *self,
+ gdouble speed_rate);
+
+G_END_DECLS
+
+#endif /* RETRO_MAIN_LOOP_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]