X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=src%2Fchimara-glk.c;h=3580623920b0fa0d19e1ddf84794cef07b78a226;hb=91fd33a275d694fe467b856eb72b2c61c815a473;hp=63e9a38f53c0d44cb8cdea55d54e9649d114b887;hpb=c6cb6dcf2f5e1c581a847e8619ee49f75b2ec979;p=projects%2Fchimara%2Fchimara.git diff --git a/src/chimara-glk.c b/src/chimara-glk.c index 63e9a38..3580623 100644 --- a/src/chimara-glk.c +++ b/src/chimara-glk.c @@ -2,14 +2,18 @@ #include #include +#include #include "chimara-glk.h" #include "chimara-glk-private.h" #include "glk.h" +#include "abort.h" #include "window.h" #define CHIMARA_GLK_MIN_WIDTH 0 #define CHIMARA_GLK_MIN_HEIGHT 0 +typedef void (* glk_main_t) (void); + enum { PROP_0, PROP_INTERACTIVE, @@ -37,6 +41,7 @@ chimara_glk_init(ChimaraGlk *self) priv->self = self; priv->interactive = TRUE; priv->protect = FALSE; + priv->program = NULL; priv->thread = NULL; priv->event_queue = NULL; priv->event_lock = NULL; @@ -109,7 +114,7 @@ chimara_glk_finalize(GObject *object) g_mutex_unlock(priv->abort_lock); g_mutex_free(priv->abort_lock); priv->abort_lock = NULL; - + G_OBJECT_CLASS(chimara_glk_parent_class)->finalize(object); } @@ -125,7 +130,7 @@ chimara_glk_size_request(GtkWidget *widget, GtkRequisition *requisition) /* For now, just pass the size request on to the root Glk window */ if(priv->root_window) { GtkWidget *child = ((winid_t)(priv->root_window->data))->frame; - if(GTK_WIDGET_VISIBLE(child)) + if(GTK_WIDGET_VISIBLE(child)) gtk_widget_size_request(child, requisition); } else { requisition->width = CHIMARA_GLK_MIN_WIDTH; @@ -169,7 +174,11 @@ chimara_glk_forall(GtkContainer *container, gboolean include_internals, static void chimara_glk_stopped(ChimaraGlk *self) { - /* TODO: Add default signal handler implementation here */ + ChimaraGlkPrivate *priv = CHIMARA_GLK_PRIVATE(self); + + /* Free the plugin */ + if( priv->program && !g_module_close(priv->program) ) + g_warning( "Error closing module: %s", g_module_error() ); } static void @@ -278,25 +287,49 @@ chimara_glk_get_protect(ChimaraGlk *glk) return priv->protect; } -/* glk_enter() is called to create a new thread in which glk_main() runs. */ +/* glk_enter() is the actual function called in the new thread in which glk_main() runs. */ static gpointer -glk_enter(gpointer glk) +glk_enter(gpointer glk_main) { extern ChimaraGlkPrivate *glk_data; - - glk_data = CHIMARA_GLK_PRIVATE((ChimaraGlk *)glk); - glk_main(); + g_signal_emit_by_name(glk_data->self, "started"); + ((glk_main_t)glk_main)(); + g_signal_emit_by_name(glk_data->self, "stopped"); return NULL; } gboolean -chimara_glk_run(ChimaraGlk *glk, GError **error) +chimara_glk_run(ChimaraGlk *glk, gchar *plugin, GError **error) { g_return_val_if_fail(glk || CHIMARA_IS_GLK(glk), FALSE); - + g_return_val_if_fail(plugin, FALSE); + ChimaraGlkPrivate *priv = CHIMARA_GLK_PRIVATE(glk); + + /* Open the module to run */ + glk_main_t glk_main; + g_assert( g_module_supported() ); + priv->program = g_module_open(plugin, G_MODULE_BIND_LAZY); + + if(!priv->program) + { + g_warning( "Error opening module: %s", g_module_error() ); + return FALSE; + } + if( !g_module_symbol(priv->program, "glk_main", (gpointer *) &glk_main) ) + { + g_warning( "Error finding glk_main(): %s", g_module_error() ); + return FALSE; + } + + extern ChimaraGlkPrivate *glk_data; + /* Set the thread's private data */ + /* TODO: Do this with a GPrivate */ + glk_data = priv; + /* Run in a separate thread */ - priv->thread = g_thread_create(glk_enter, glk, TRUE, error); + priv->thread = g_thread_create(glk_enter, glk_main, TRUE, error); + return !(priv->thread == NULL); } @@ -305,7 +338,7 @@ chimara_glk_stop(ChimaraGlk *glk) { g_return_if_fail(glk || CHIMARA_IS_GLK(glk)); - /* TODO */ + signal_abort(); } void