[retro-gtk] retro-main-loop: Merge into RetroCore



commit 56d981adbb8e9a1ce115aff1af41e23b6dbdf523
Author: Alexander Mikhaylenko <alexm gnome org>
Date:   Tue Jan 7 03:31:30 2020 +0500

    retro-main-loop: Merge into RetroCore
    
    There's no point in separating these 2 classes, as one core cannot have
    two main loops anyway. Additionally, RetroMainLoop contains very little
    amount of logic, and having just one object will simplify things later
    with subprocess.

 demos/retro-demo.c             |   7 +-
 retro-gtk/meson.build          |   2 -
 retro-gtk/retro-core-private.h |   2 +
 retro-gtk/retro-core.c         | 137 ++++++++++++++++
 retro-gtk/retro-core.h         |   5 +
 retro-gtk/retro-gtk.h          |   1 -
 retro-gtk/retro-main-loop.c    | 351 -----------------------------------------
 retro-gtk/retro-main-loop.h    |  28 ----
 8 files changed, 145 insertions(+), 388 deletions(-)
---
diff --git a/demos/retro-demo.c b/demos/retro-demo.c
index 16372cd..abf5774 100644
--- a/demos/retro-demo.c
+++ b/demos/retro-demo.c
@@ -11,7 +11,6 @@ struct _RetroDemoApplication
   GtkApplication parent_instance;
 
   RetroCore *core;
-  RetroMainLoop *loop;
 };
 
 G_DEFINE_TYPE (RetroDemoApplication, retro_demo_application, GTK_TYPE_APPLICATION)
@@ -79,9 +78,6 @@ retro_demo_application_finalize (GObject *object)
   if (self->core != NULL)
     g_object_unref (self->core);
 
-  if (self->loop != NULL)
-    g_object_unref (self->loop);
-
   G_OBJECT_CLASS (retro_demo_application_parent_class)->finalize (object);
 }
 
@@ -110,8 +106,7 @@ retro_demo_activate (GApplication *application)
   gtk_application_add_window (GTK_APPLICATION (application),
                               GTK_WINDOW (window));
 
-  self->loop = retro_main_loop_new (self->core);
-  retro_main_loop_start (self->loop);
+  retro_core_start (self->core);
 }
 
 static void
diff --git a/retro-gtk/meson.build b/retro-gtk/meson.build
index d4321b7..28229f8 100644
--- a/retro-gtk/meson.build
+++ b/retro-gtk/meson.build
@@ -25,7 +25,6 @@ retro_gtk_sources = [
   'retro-keyboard.c',
   'retro-key-joypad-mapping.c',
   'retro-log.c',
-  'retro-main-loop.c',
   'retro-memory-type.c',
   'retro-module.c',
   'retro-module-iterator.c',
@@ -54,7 +53,6 @@ retro_gtk_headers = [
   'retro-input.h',
   'retro-key-joypad-mapping.h',
   'retro-log.h',
-  'retro-main-loop.h',
   'retro-memory-type.h',
   'retro-module-iterator.h',
   'retro-module-query.h',
diff --git a/retro-gtk/retro-core-private.h b/retro-gtk/retro-core-private.h
index 8e92eed..8f357c5 100644
--- a/retro-gtk/retro-core-private.h
+++ b/retro-gtk/retro-core-private.h
@@ -55,6 +55,8 @@ struct _RetroCore
   gboolean variable_updated;
   guint runahead;
   gssize run_remaining;
+  gdouble speed_rate;
+  glong main_loop;
   gint16 *audio_samples;
   gulong audio_samples_length;
 };
diff --git a/retro-gtk/retro-core.c b/retro-gtk/retro-core.c
index e1ece22..49081b1 100644
--- a/retro-gtk/retro-core.c
+++ b/retro-gtk/retro-core.c
@@ -37,6 +37,7 @@ enum {
   PROP_SUPPORT_NO_GAME,
   PROP_FRAMES_PER_SECOND,
   PROP_RUNAHEAD,
+  PROP_SPEED_RATE,
   N_PROPS,
 };
 
@@ -159,6 +160,8 @@ retro_core_finalize (GObject *object)
 
   g_return_if_fail (RETRO_IS_CORE (self));
 
+  retro_core_stop (self);
+
   retro_core_push_cb_data (self);
   if (retro_core_get_game_loaded (self)) {
     unload_game = retro_module_get_unload_game (self->module);
@@ -226,6 +229,10 @@ retro_core_get_property (GObject    *object,
   case PROP_RUNAHEAD:
     g_value_set_uint (value, retro_core_get_runahead (self));
 
+    break;
+  case PROP_SPEED_RATE:
+    g_value_set_double (value, retro_core_get_speed_rate (self));
+
     break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -262,6 +269,10 @@ retro_core_set_property (GObject      *object,
   case PROP_RUNAHEAD:
     retro_core_set_runahead (self, g_value_get_uint (value));
 
+    break;
+  case PROP_SPEED_RATE:
+    retro_core_set_speed_rate (self, g_value_get_double (value));
+
     break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -438,6 +449,21 @@ retro_core_class_init (RetroCoreClass *klass)
                        G_PARAM_STATIC_NICK |
                        G_PARAM_STATIC_BLURB);
 
+  /**
+   * RetroCore:speed-rate:
+   *
+   * The speed ratio at wich the core will run.
+   */
+  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_object_class_install_properties (G_OBJECT_CLASS (klass), N_PROPS, properties);
 
   /**
@@ -544,6 +570,9 @@ retro_core_init (RetroCore *self)
 
   self->controllers = g_hash_table_new_full (g_int_hash, g_int_equal,
                                              g_free, g_object_unref);
+
+  self->main_loop = -1;
+  self->speed_rate = 1;
 }
 
 static void
@@ -618,6 +647,16 @@ retro_core_get_needs_full_path (RetroCore *self)
   return system_info.need_fullpath;
 }
 
+static void
+restart (RetroCore *self)
+{
+  if (self->main_loop < 0)
+    return;
+
+  retro_core_stop (self);
+  retro_core_start (self);
+}
+
 void
 retro_core_set_system_av_info (RetroCore         *self,
                                RetroSystemAvInfo *system_av_info)
@@ -625,6 +664,7 @@ retro_core_set_system_av_info (RetroCore         *self,
   if (self->frames_per_second != system_av_info->timing.fps) {
     self->frames_per_second = system_av_info->timing.fps;
     g_object_notify (G_OBJECT (self), "frames-per-second");
+    restart (self);
   }
   retro_core_set_geometry (self, &system_av_info->geometry);
   self->sample_rate = system_av_info->timing.sample_rate;
@@ -1501,6 +1541,65 @@ retro_core_set_controller_port_device (RetroCore           *self,
   retro_core_pop_cb_data ();
 }
 
+static gboolean
+run_main_loop (RetroCore *self)
+{
+  if (self->main_loop < 0)
+    return FALSE;
+
+  retro_core_run (self);
+
+  return TRUE;
+}
+
+/**
+ * retro_core_start:
+ * @self: a #RetroCore
+ *
+ * Starts running the core. If the core was stopped, it will restart from this
+ * moment.
+ */
+void
+retro_core_start (RetroCore *self)
+{
+  gdouble fps;
+
+  g_return_if_fail (RETRO_IS_CORE (self));
+
+  if (self->main_loop >= 0 || self->speed_rate <= 0)
+    return;
+
+  // TODO What if fps <= 0?
+  fps = retro_core_get_frames_per_second (self);
+  /* Do not make the timeout source hold a reference on the RetroCore, so
+   * destroying the RetroCore while it is still running will stop it instead
+   * of leaking a reference.
+   */
+  self->main_loop =
+    g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE,
+                        (guint) (1000 / (fps * self->speed_rate)),
+                        (GSourceFunc) run_main_loop,
+                        self, NULL);
+}
+
+/**
+ * retro_core_stop:
+ * @self: a #RetroCore
+ *
+ * Stops running the core.
+ */
+void
+retro_core_stop (RetroCore *self)
+{
+  g_return_if_fail (RETRO_IS_CORE (self));
+
+  if (self->main_loop < 0)
+    return;
+
+  g_source_remove (self->main_loop);
+  self->main_loop = -1;
+}
+
 /**
  * retro_core_reset:
  * @self: a #RetroCore
@@ -2159,6 +2258,44 @@ retro_core_is_running_ahead (RetroCore *self)
   return self->run_remaining > 0;
 }
 
+/**
+ * retro_core_get_speed_rate:
+ * @self: a #RetroCore
+ *
+ * Gets the speed rate at which to run the core.
+ *
+ * Returns: the speed rate
+ */
+gdouble
+retro_core_get_speed_rate (RetroCore *self)
+{
+  g_return_val_if_fail (RETRO_IS_CORE (self), 1.0);
+
+  return self->speed_rate;
+}
+
+/**
+ * retro_core_set_speed_rate:
+ * @self: a #RetroCore
+ * @speed_rate: a speed rate
+ *
+ * Sets the speed rate at which to run the core.
+ */
+void
+retro_core_set_speed_rate (RetroCore *self,
+                           gdouble    speed_rate)
+{
+  g_return_if_fail (RETRO_IS_CORE (self));
+
+  if (self->speed_rate == speed_rate)
+    return;
+
+  self->speed_rate = speed_rate;
+  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SPEED_RATE]);
+
+  restart (self);
+}
+
 /**
  * retro_core_has_option:
  * @self: a #RetroCore
diff --git a/retro-gtk/retro-core.h b/retro-gtk/retro-core.h
index a00b719..460d86f 100644
--- a/retro-gtk/retro-core.h
+++ b/retro-gtk/retro-core.h
@@ -40,6 +40,8 @@ void retro_core_set_medias (RetroCore           *self,
 void retro_core_set_current_media (RetroCore  *self,
                                    guint       media_index,
                                    GError    **error);
+void retro_core_start (RetroCore *self);
+void retro_core_stop (RetroCore *self);
 void retro_core_reset (RetroCore *self);
 void retro_core_run (RetroCore *self);
 gboolean retro_core_get_can_access_state (RetroCore *self);
@@ -71,6 +73,9 @@ RetroControllerIterator *retro_core_iterate_controllers (RetroCore *self);
 guint retro_core_get_runahead (RetroCore *self);
 void retro_core_set_runahead (RetroCore *self,
                               guint      runahead);
+gdouble retro_core_get_speed_rate (RetroCore *self);
+void retro_core_set_speed_rate (RetroCore *self,
+                                gdouble    speed_rate);
 gboolean retro_core_has_option (RetroCore   *self,
                                 const gchar *key);
 RetroOption *retro_core_get_option (RetroCore   *self,
diff --git a/retro-gtk/retro-gtk.h b/retro-gtk/retro-gtk.h
index 94ae6d2..e5ef793 100644
--- a/retro-gtk/retro-gtk.h
+++ b/retro-gtk/retro-gtk.h
@@ -19,7 +19,6 @@
 #include "retro-input.h"
 #include "retro-key-joypad-mapping.h"
 #include "retro-log.h"
-#include "retro-main-loop.h"
 #include "retro-memory-type.h"
 #include "retro-module-iterator.h"
 #include "retro-module-query.h"


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