7fa44d1bbb
gnoemoe/gm-world.[ch]: fixed const, added gm_world_status, world specific log settings gnoemoe/gm-scripts.c: added World.status function gnoemoe/gm-pixbuf.c: added NULL filename checks
917 lines
21 KiB
C
917 lines
21 KiB
C
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <glib.h>
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
#include <ruby.h>
|
|
#include <libgnomevfs/gnome-vfs-mime-utils.h>
|
|
#include <libgnomevfs/gnome-vfs.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
|
|
#undef PACKAGE_BUGREPORT
|
|
#undef PACKAGE_NAME
|
|
#undef PACKAGE_STRING
|
|
#undef PACKAGE_TARNAME
|
|
#undef PACKAGE_VERSION
|
|
|
|
#include "gm-support.h"
|
|
#include "gm-debug.h"
|
|
#include "gm-world.h"
|
|
#include "gm-app.h"
|
|
#include "gm-scripts.h"
|
|
|
|
#include "gm-world.h"
|
|
#include "gm-string.h"
|
|
|
|
#define GM_SCRIPTS_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), \
|
|
GM_TYPE_SCRIPTS, GmScriptsPrivate))
|
|
#define RB_CALLBACK(x) (VALUE (*)())(x)
|
|
#define GM_SCRIPTS_GLOBAL PACKAGE_DATA_DIR "/" PACKAGE "/scripts"
|
|
|
|
static VALUE rb_world_class, rb_client_class, rb_scripts_class;
|
|
|
|
VALUE script_world_name(VALUE self);
|
|
VALUE gm_scripts_rb_world_new(GmWorld *world);
|
|
VALUE gm_scripts_rb_scripts_new(GmScripts *scripts);
|
|
|
|
void gm_scripts_rb_world_class_init();
|
|
void gm_scripts_rb_client_class_init();
|
|
void gm_scripts_rb_scripts_class_init();
|
|
|
|
void gm_scripts_unload(GmScripts *scripts);
|
|
void gm_scripts_rb_init();
|
|
|
|
struct _GmScriptsPrivate {
|
|
GList *files;
|
|
GmScript *loading;
|
|
GList *monitors;
|
|
};
|
|
|
|
/* Signals */
|
|
|
|
enum {
|
|
SCRIPT_ADDED,
|
|
SCRIPT_CHANGED,
|
|
SCRIPT_REMOVED,
|
|
RELOAD,
|
|
MESSAGE,
|
|
ERROR,
|
|
RUN,
|
|
NUM_SIGNALS
|
|
};
|
|
|
|
static guint gm_scripts_signals[NUM_SIGNALS] = {0};
|
|
|
|
G_DEFINE_TYPE(GmScripts, gm_scripts, G_TYPE_OBJECT)
|
|
|
|
|
|
static void
|
|
gm_scripts_finalize(GObject *object) {
|
|
GmScripts *scripts = GM_SCRIPTS(object);
|
|
GList *monitors;
|
|
|
|
gm_scripts_unload(scripts);
|
|
|
|
for (monitors = scripts->priv->monitors; monitors;
|
|
monitors = monitors->next) {
|
|
gnome_vfs_monitor_cancel((GnomeVFSMonitorHandle *)(monitors->data));
|
|
}
|
|
|
|
g_list_free(scripts->priv->monitors);
|
|
scripts->priv->monitors = NULL;
|
|
|
|
G_OBJECT_CLASS(gm_scripts_parent_class)->finalize(object);
|
|
}
|
|
|
|
static void
|
|
gm_scripts_class_init(GmScriptsClass *klass) {
|
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
|
|
|
object_class->finalize = gm_scripts_finalize;
|
|
|
|
gm_scripts_signals[SCRIPT_ADDED] =
|
|
g_signal_new("script_added",
|
|
G_OBJECT_CLASS_TYPE(object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET(GmScriptsClass, script_added),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__POINTER,
|
|
G_TYPE_NONE,
|
|
1,
|
|
G_TYPE_POINTER);
|
|
gm_scripts_signals[SCRIPT_CHANGED] =
|
|
g_signal_new("script_changed",
|
|
G_OBJECT_CLASS_TYPE(object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET(GmScriptsClass, script_changed),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__POINTER,
|
|
G_TYPE_NONE,
|
|
1,
|
|
G_TYPE_POINTER);
|
|
gm_scripts_signals[SCRIPT_REMOVED] =
|
|
g_signal_new("script_removed",
|
|
G_OBJECT_CLASS_TYPE(object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET(GmScriptsClass, script_removed),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__POINTER,
|
|
G_TYPE_NONE,
|
|
1,
|
|
G_TYPE_POINTER);
|
|
gm_scripts_signals[RELOAD] =
|
|
g_signal_new("reload",
|
|
G_OBJECT_CLASS_TYPE(object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET(GmScriptsClass, reload),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__VOID,
|
|
G_TYPE_NONE,
|
|
0);
|
|
gm_scripts_signals[MESSAGE] =
|
|
g_signal_new("message",
|
|
G_OBJECT_CLASS_TYPE(object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET(GmScriptsClass, message),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__STRING,
|
|
G_TYPE_NONE,
|
|
1,
|
|
G_TYPE_STRING);
|
|
gm_scripts_signals[ERROR] =
|
|
g_signal_new("error",
|
|
G_OBJECT_CLASS_TYPE(object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET(GmScriptsClass, error),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__STRING,
|
|
G_TYPE_NONE,
|
|
1,
|
|
G_TYPE_STRING);
|
|
gm_scripts_signals[RUN] =
|
|
g_signal_new("run",
|
|
G_OBJECT_CLASS_TYPE(object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET(GmScriptsClass, run),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__STRING,
|
|
G_TYPE_NONE,
|
|
1,
|
|
G_TYPE_STRING);
|
|
|
|
g_type_class_add_private(object_class, sizeof(GmScriptsPrivate));
|
|
|
|
gm_scripts_rb_init();
|
|
}
|
|
|
|
void
|
|
gm_scripts_rb_init(GmScriptsClass *klass) {
|
|
ruby_init();
|
|
|
|
gm_scripts_rb_world_class_init();
|
|
gm_scripts_rb_client_class_init();
|
|
gm_scripts_rb_scripts_class_init();
|
|
}
|
|
|
|
static void
|
|
gm_scripts_init(GmScripts *scripts) {
|
|
scripts->priv = GM_SCRIPTS_GET_PRIVATE(scripts);
|
|
|
|
scripts->priv->monitors = NULL;
|
|
scripts->priv->files = NULL;
|
|
}
|
|
|
|
GmScripts *
|
|
gm_scripts_new() {
|
|
GmScripts *scripts = GM_SCRIPTS(g_object_new(GM_TYPE_SCRIPTS, NULL));
|
|
|
|
return scripts;
|
|
}
|
|
|
|
void gm_scripts_monitor_cb (GnomeVFSMonitorHandle *handle,
|
|
const gchar *monitor_uri, const gchar *info_uri,
|
|
GnomeVFSMonitorEventType event_type,
|
|
GmScripts *scripts) {
|
|
gchar *filename = gnome_vfs_get_local_path_from_uri(info_uri);
|
|
|
|
switch (event_type) {
|
|
case GNOME_VFS_MONITOR_EVENT_CHANGED:
|
|
gm_scripts_reload_file(scripts, filename);
|
|
break;
|
|
case GNOME_VFS_MONITOR_EVENT_DELETED:
|
|
gm_scripts_remove_file(scripts, filename);
|
|
break;
|
|
case GNOME_VFS_MONITOR_EVENT_CREATED:
|
|
gm_scripts_add_file(scripts, filename);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
g_free(filename);
|
|
}
|
|
|
|
void
|
|
gm_script_function_destroy(GmScriptFunction *fi) {
|
|
g_free(fi->name);
|
|
g_free(fi->fname);
|
|
g_free(fi->description);
|
|
g_free(fi);
|
|
}
|
|
|
|
void
|
|
gm_script_destroy_functions(GmScript *script) {
|
|
GList *functions;
|
|
|
|
for (functions = script->functions; functions;
|
|
functions = functions->next) {
|
|
gm_script_function_destroy((GmScriptFunction *)(functions->data));
|
|
}
|
|
|
|
g_list_free(script->functions);
|
|
script->functions = NULL;
|
|
}
|
|
|
|
void
|
|
gm_script_destroy(GmScript *script) {
|
|
gm_script_destroy_functions(script);
|
|
g_free(script->filename);
|
|
g_free(script);
|
|
}
|
|
|
|
void
|
|
gm_scripts_unload(GmScripts *scripts) {
|
|
GList *files;
|
|
|
|
for (files = scripts->priv->files; files; files = files->next) {
|
|
gm_script_destroy((GmScript *)(files->data));
|
|
}
|
|
|
|
g_list_free(scripts->priv->files);
|
|
scripts->priv->files = NULL;
|
|
}
|
|
|
|
GmScriptFunction *
|
|
gm_scripts_find(GmScripts *scripts, gchar *name) {
|
|
GList *files;
|
|
GList *functions;
|
|
GmScriptFunction *func;
|
|
GmScript *script;
|
|
|
|
for (files = scripts->priv->files; files; files = files->next) {
|
|
script = (GmScript *)(files->data);
|
|
for (functions = script->functions; functions;
|
|
functions = functions->next) {
|
|
func = (GmScriptFunction *)(functions->data);
|
|
|
|
if (strcasecmp(func->name, name) == 0) {
|
|
return func;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
gboolean
|
|
gm_scripts_add(GmScripts *scripts, gchar *name, gchar *fname,
|
|
gchar *description) {
|
|
GmScriptFunction *func;
|
|
|
|
if (gm_scripts_find(scripts, name) == NULL) {
|
|
func = g_new(GmScriptFunction, 1);
|
|
func->script = scripts->priv->loading;
|
|
func->name = g_strdup(name);
|
|
func->fname = g_strdup(fname);;
|
|
func->description = g_strdup(description);
|
|
|
|
scripts->priv->loading->functions =
|
|
g_list_append(scripts->priv->loading->functions, func);
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
VALUE
|
|
gm_scripts_rb_register_functions_wrap(VALUE arg) {
|
|
return rb_eval_string("register_functions");
|
|
}
|
|
|
|
void
|
|
gm_scripts_rb_script_define_world(VALUE *world) {
|
|
rb_define_variable("$world", world);
|
|
}
|
|
|
|
void
|
|
gm_scripts_rb_error(GmScripts *scripts) {
|
|
int c;
|
|
VALUE lasterr;
|
|
char *err;
|
|
gchar *msg;
|
|
VALUE ary;
|
|
|
|
if(!NIL_P(ruby_errinfo)) {
|
|
lasterr = rb_gv_get("$!");
|
|
err = RSTRING(rb_obj_as_string(lasterr))->ptr;
|
|
|
|
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.Error: Error while executing Ruby code: %s",
|
|
err);
|
|
|
|
msg = g_strdup_printf(_("Error in execution: %s"), err);
|
|
g_signal_emit(scripts, gm_scripts_signals[MESSAGE], 0, msg);
|
|
g_free(msg);
|
|
|
|
ary = rb_funcall(ruby_errinfo, rb_intern("backtrace"), 0);
|
|
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.Error: Ruby backtrace:");
|
|
g_signal_emit(scripts, gm_scripts_signals[ERROR], 0,
|
|
_("Ruby backtrace:"));
|
|
|
|
for (c = 0; c < RARRAY(ary)->len; c++) {
|
|
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.Error: \tfrom %s",
|
|
RSTRING(RARRAY(ary)->ptr[c])->ptr);
|
|
|
|
msg = g_strdup_printf(_("\tfrom %s"),
|
|
RSTRING(RARRAY(ary)->ptr[c])->ptr);
|
|
g_signal_emit(scripts, gm_scripts_signals[ERROR], 0, msg);
|
|
g_free(msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
gm_scripts_rb_do(GmScripts *scripts, VALUE (*body)(), VALUE arg) {
|
|
int status;
|
|
|
|
rb_protect(body, arg, &status);
|
|
|
|
if (status != 0) {
|
|
gm_scripts_rb_error(scripts);
|
|
ruby_cleanup(status);
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
VALUE
|
|
gm_scripts_run_function(GmScriptInfo *arg) {
|
|
VALUE ret;
|
|
gchar *argstr;
|
|
gchar *func_all;
|
|
|
|
if (arg->argstr) {
|
|
argstr = gm_string_escape(arg->argstr);
|
|
func_all = g_strconcat(arg->name, "(\"", argstr, "\")", NULL);
|
|
g_free(argstr);
|
|
} else {
|
|
func_all = g_strconcat(arg->name, "()", NULL);
|
|
}
|
|
|
|
ret = rb_eval_string(func_all);
|
|
g_free(func_all);
|
|
|
|
return ret;
|
|
}
|
|
|
|
gboolean
|
|
gm_scripts_run(GmScripts *scripts, GmWorld *world, gchar *name, gchar *argstr) {
|
|
VALUE rbWorld, rbClient;
|
|
gchar *msg;
|
|
GmScriptInfo *info;
|
|
GmScriptFunction *f = gm_scripts_find(scripts, name);
|
|
|
|
if (!f) {
|
|
return FALSE;
|
|
}
|
|
|
|
info = g_new0(GmScriptInfo, 1);
|
|
info->name = g_strdup(f->fname);
|
|
|
|
if (argstr) {
|
|
info->argstr = g_strdup(argstr);
|
|
msg = g_strdup_printf(_("Run script '%s' from '%s' (%s)"), f->fname,
|
|
f->script->filename, argstr);
|
|
} else {
|
|
info->argstr = NULL;
|
|
msg = g_strdup_printf(_("Run script '%s' from '%s' ()"), f->fname,
|
|
f->script->filename);
|
|
}
|
|
|
|
g_signal_emit(scripts, gm_scripts_signals[RUN], 0, msg);
|
|
g_free(msg);
|
|
|
|
gm_scripts_rb_do(scripts, RB_CALLBACK(rb_load_file),
|
|
(VALUE)(f->script->filename));
|
|
ruby_exec();
|
|
|
|
rbWorld = gm_scripts_rb_world_new(world);
|
|
rb_define_variable("$world", &rbWorld);
|
|
|
|
rbClient = rb_class_new_instance(0, NULL, rb_client_class);
|
|
rb_define_variable("$client", &rbClient);
|
|
|
|
gm_scripts_rb_do(scripts, RB_CALLBACK(gm_scripts_run_function),
|
|
(VALUE)info);
|
|
|
|
g_free(info->name);
|
|
g_free(info->argstr);
|
|
g_free(info);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
VALUE
|
|
gm_scripts_rb_register_func_old(int argc, VALUE *argv) {
|
|
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.RegisterFunc: This is the deprecated way to "
|
|
"register functions is does no longer work. Use $scripts.register "
|
|
"instead.");
|
|
|
|
return Qfalse;
|
|
}
|
|
|
|
void
|
|
gm_scripts_register_functions(GmScripts *scripts) {
|
|
gchar *msg;
|
|
VALUE rbScripts;
|
|
|
|
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.RegisterFunctions: registering functions in %s",
|
|
scripts->priv->loading->filename);
|
|
|
|
msg = g_strdup_printf(_("Registering functions from '%s'"),
|
|
scripts->priv->loading->filename);
|
|
g_signal_emit(scripts, gm_scripts_signals[MESSAGE], 0, msg);
|
|
g_free(msg);
|
|
|
|
// Okay, I'm desperate... define an empty register_functions method so
|
|
// that the previous when gets cleared ... :(
|
|
rb_eval_string("def register_functions() end");
|
|
|
|
if (!gm_scripts_rb_do(scripts, RB_CALLBACK(rb_load_file),
|
|
(VALUE) scripts->priv->loading->filename)) {
|
|
return;
|
|
}
|
|
|
|
ruby_exec();
|
|
|
|
rbScripts = gm_scripts_rb_scripts_new(scripts);
|
|
rb_define_variable("$scripts", &rbScripts);
|
|
rb_define_global_function("register_func", &gm_scripts_rb_register_func_old,
|
|
-1);
|
|
|
|
gm_scripts_rb_do(scripts,
|
|
RB_CALLBACK(gm_scripts_rb_register_functions_wrap), 0);
|
|
}
|
|
|
|
void
|
|
gm_scripts_remove_file(GmScripts *scripts, const gchar *uri) {
|
|
GList *f, *l;
|
|
GmScript *script;
|
|
|
|
l = g_list_copy(scripts->priv->files);
|
|
|
|
for (f = l; f; f = f->next) {
|
|
script = (GmScript *)(f->data);
|
|
|
|
if (strcmp(script->filename, uri) == 0) {
|
|
scripts->priv->files = g_list_remove(scripts->priv->files, script);
|
|
|
|
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.RemoveFile: Removing scripts from `%s'",
|
|
script->filename);
|
|
g_signal_emit(scripts, gm_scripts_signals[SCRIPT_REMOVED], 0,
|
|
script);
|
|
|
|
gm_script_destroy(script);
|
|
}
|
|
}
|
|
|
|
g_list_free(l);
|
|
}
|
|
|
|
gboolean
|
|
gm_scripts_add_file(GmScripts *scripts, const gchar *uri) {
|
|
GList *f;
|
|
GmScript *script;
|
|
gchar *msg;
|
|
gchar *ext;
|
|
|
|
// Only .rb files
|
|
ext = strrchr(uri, '.');
|
|
|
|
if (ext == NULL || strncmp(ext, ".rb", 2) != 0) {
|
|
msg = g_strdup_printf(_("File `%s' is not a valid ruby file"), uri);
|
|
|
|
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.AddFile: %s", msg);
|
|
g_signal_emit(scripts, gm_scripts_signals[ERROR], 0, msg);
|
|
|
|
g_free(msg);
|
|
return FALSE;
|
|
}
|
|
|
|
for (f = scripts->priv->files; f; f = f->next) {
|
|
script = (GmScript *)(f->data);
|
|
|
|
if (strcmp(script->filename, uri) == 0) {
|
|
msg = g_strdup_printf(_("File `%s' already loaded"), uri);
|
|
|
|
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.AddFile: %s", msg);
|
|
g_signal_emit(scripts, gm_scripts_signals[ERROR], 0, msg);
|
|
|
|
g_free(msg);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
msg = g_strdup_printf(_("File `%s' added"), uri);
|
|
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.AddFile: %s", msg);
|
|
g_free(msg);
|
|
|
|
script = g_new0(GmScript, 1);
|
|
script->filename = g_strdup(uri);
|
|
|
|
if (strncmp(uri, GM_SCRIPTS_GLOBAL,
|
|
strlen(GM_SCRIPTS_GLOBAL)) == 0) {
|
|
script->type = GM_SCRIPT_TYPE_SHARE;
|
|
} else {
|
|
script->type = GM_SCRIPT_TYPE_USER;
|
|
}
|
|
|
|
scripts->priv->files = g_list_append(scripts->priv->files, script);
|
|
scripts->priv->loading = script;
|
|
|
|
gm_scripts_register_functions(scripts);
|
|
g_signal_emit(scripts, gm_scripts_signals[SCRIPT_ADDED], 0, script);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
gm_scripts_reload_file(GmScripts *scripts, const gchar *uri) {
|
|
GList *files;
|
|
GmScript *script;
|
|
|
|
for (files = scripts->priv->files; files; files = files->next) {
|
|
script = (GmScript *)(files->data);
|
|
|
|
if (strcmp(script->filename, uri) == 0) {
|
|
// Remove all functions and reregister the file
|
|
scripts->priv->loading = script;
|
|
|
|
gm_script_destroy_functions(script);
|
|
gm_scripts_register_functions(scripts);
|
|
|
|
g_signal_emit(scripts, gm_scripts_signals[SCRIPT_CHANGED], 0,
|
|
script);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// If the script does not yet exist, add it
|
|
gm_scripts_add_file(scripts, uri);
|
|
}
|
|
|
|
void
|
|
gm_scripts_load_dir(GmScripts *scripts, gchar *dirname) {
|
|
gchar *filename;
|
|
gchar *file;
|
|
GDir *d;
|
|
GnomeVFSMonitorHandle *handle;
|
|
|
|
if (g_file_test(dirname, G_FILE_TEST_EXISTS) &&
|
|
g_file_test(dirname, G_FILE_TEST_IS_DIR)) {
|
|
|
|
if ((d = g_dir_open(dirname, 0, NULL))) {
|
|
while ((file = (gchar *)g_dir_read_name(d))) {
|
|
filename = g_strconcat(dirname, "/", file, NULL);
|
|
gm_scripts_add_file(scripts, filename);
|
|
g_free(filename);
|
|
}
|
|
}
|
|
|
|
gnome_vfs_monitor_add(&handle, dirname, GNOME_VFS_MONITOR_DIRECTORY,
|
|
(GnomeVFSMonitorCallback)gm_scripts_monitor_cb, scripts);
|
|
scripts->priv->monitors = g_list_append(scripts->priv->monitors,
|
|
handle);
|
|
}
|
|
}
|
|
|
|
void
|
|
gm_scripts_load(GmScripts *scripts) {
|
|
gchar *path;
|
|
|
|
if (scripts->priv->files) {
|
|
g_signal_emit(scripts, gm_scripts_signals[RELOAD], 0);
|
|
gm_scripts_unload(scripts);
|
|
}
|
|
|
|
path = g_strconcat(gm_app_path(gm_app_instance()), "/scripts", NULL);
|
|
|
|
// Make user dir if it doesn't exist
|
|
if (!g_file_test(path, G_FILE_TEST_EXISTS)) {
|
|
mkdir(path, 0750);
|
|
}
|
|
|
|
gm_scripts_load_dir(scripts, path);
|
|
gm_scripts_load_dir(scripts, GM_SCRIPTS_GLOBAL);
|
|
|
|
g_free(path);
|
|
}
|
|
|
|
GList *
|
|
gm_scripts_scripts(GmScripts *scripts) {
|
|
return scripts->priv->files;
|
|
}
|
|
// Ruby class functions
|
|
|
|
VALUE
|
|
gm_scripts_rb_world_new(GmWorld *world) {
|
|
VALUE tdata = Data_Wrap_Struct(rb_world_class, 0, 0, world);
|
|
|
|
return tdata;
|
|
}
|
|
|
|
VALUE
|
|
gm_scripts_rb_scripts_new(GmScripts *scripts) {
|
|
VALUE tdata = Data_Wrap_Struct(rb_scripts_class, 0, 0, scripts);
|
|
|
|
return tdata;
|
|
}
|
|
|
|
// Ruby world class functions
|
|
static VALUE
|
|
gm_scripts_rb_world_name(VALUE self) {
|
|
GmWorld *world;
|
|
|
|
Data_Get_Struct(self, GmWorld, world);
|
|
|
|
return rb_str_new2(gm_options_get(gm_world_options(world), "name"));
|
|
}
|
|
|
|
static VALUE
|
|
gm_scripts_rb_world_host(VALUE self) {
|
|
GmWorld *world;
|
|
|
|
Data_Get_Struct(self, GmWorld, world);
|
|
|
|
return rb_str_new2(gm_options_get(gm_world_options(world), "host"));
|
|
}
|
|
|
|
static VALUE
|
|
gm_scripts_rb_world_port(VALUE self) {
|
|
GmWorld *world;
|
|
|
|
Data_Get_Struct(self, GmWorld, world);
|
|
|
|
return rb_str_new2(gm_options_get(gm_world_options(world), "port"));
|
|
}
|
|
|
|
static VALUE
|
|
gm_scripts_rb_world_writeln(VALUE self, VALUE str) {
|
|
GmWorld *world;
|
|
gchar *strVal;
|
|
|
|
Data_Get_Struct(self, GmWorld, world);
|
|
strVal = rb_string_value_cstr(&str);
|
|
|
|
gm_world_writeln(world, strVal);
|
|
|
|
return Qnil;
|
|
}
|
|
|
|
static VALUE
|
|
gm_scripts_rb_world_status(VALUE self, VALUE str) {
|
|
GmWorld *world;
|
|
gchar *strVal;
|
|
|
|
Data_Get_Struct(self, GmWorld, world);
|
|
strVal = rb_string_value_cstr(&str);
|
|
|
|
gm_world_status(world, strVal);
|
|
|
|
return Qnil;
|
|
}
|
|
|
|
static VALUE
|
|
gm_scripts_rb_world_sendln(VALUE self, VALUE str) {
|
|
GmWorld *world;
|
|
gchar *strVal;
|
|
|
|
Data_Get_Struct(self, GmWorld, world);
|
|
strVal = rb_string_value_cstr(&str);
|
|
|
|
gm_world_sendln(world, strVal);
|
|
|
|
return Qnil;
|
|
}
|
|
|
|
static VALUE
|
|
gm_scripts_rb_world_input(VALUE self, VALUE str) {
|
|
GmWorld *world;
|
|
gchar *strVal;
|
|
|
|
Data_Get_Struct(self, GmWorld, world);
|
|
strVal = rb_string_value_cstr(&str);
|
|
|
|
gm_world_process_input(world, strVal);
|
|
|
|
return Qnil;
|
|
}
|
|
|
|
static VALUE
|
|
gm_scripts_rb_world_loaded(VALUE self) {
|
|
GmWorld *world;
|
|
|
|
Data_Get_Struct(self, GmWorld, world);
|
|
|
|
if (gm_world_loaded(world)) {
|
|
return Qtrue;
|
|
} else {
|
|
return Qfalse;
|
|
}
|
|
}
|
|
|
|
static VALUE
|
|
gm_scripts_rb_world_connected(VALUE self) {
|
|
GmWorld *world;
|
|
|
|
Data_Get_Struct(self, GmWorld, world);
|
|
|
|
if (gm_world_state(world) == GM_NET_STATE_CONNECTED) {
|
|
return Qtrue;
|
|
} else {
|
|
return Qfalse;
|
|
}
|
|
}
|
|
|
|
static VALUE
|
|
gm_scripts_rb_world_quit(VALUE self) {
|
|
GmWorld *world;
|
|
|
|
Data_Get_Struct(self, GmWorld, world);
|
|
|
|
gm_world_unload(world);
|
|
return Qnil;
|
|
}
|
|
|
|
static VALUE
|
|
gm_scripts_rb_world_connect(int argc, VALUE *argv, VALUE self) {
|
|
GmWorld *world;
|
|
const gchar *strHost, *strPort;
|
|
|
|
Data_Get_Struct(self, GmWorld, world);
|
|
|
|
if (argc == 0) {
|
|
strHost = gm_options_get(gm_world_options(world), "host");
|
|
} else {
|
|
strHost = rb_string_value_cstr(&(argv[0]));
|
|
}
|
|
|
|
if (argc == 0 || argc == 1) {
|
|
strPort = gm_options_get(gm_world_options(world), "port");
|
|
} else {
|
|
strPort = rb_string_value_cstr(&(argv[1]));
|
|
}
|
|
|
|
gm_world_connect_to(world, (gchar *)strHost, (gchar *)strPort);
|
|
|
|
return Qnil;
|
|
}
|
|
|
|
static VALUE
|
|
gm_scripts_rb_world_disconnect(VALUE self) {
|
|
GmWorld *world;
|
|
|
|
Data_Get_Struct(self, GmWorld, world);
|
|
|
|
gm_world_disconnect(world);
|
|
return Qnil;
|
|
}
|
|
|
|
// Ruby client class functions
|
|
|
|
static VALUE
|
|
gm_scripts_rb_client_version(VALUE self) {
|
|
return rb_str_new2(VERSION);
|
|
}
|
|
|
|
static VALUE
|
|
gm_scripts_rb_client_worlds(VALUE self) {
|
|
GList *world;
|
|
VALUE rb_array = rb_ary_new();
|
|
VALUE rb_world;
|
|
|
|
for (world = gm_app_worlds(gm_app_instance()); world; world = world->next) {
|
|
rb_world = gm_scripts_rb_world_new((GmWorld *)(world->data));
|
|
rb_ary_push(rb_array, rb_world);
|
|
}
|
|
|
|
return rb_array;
|
|
}
|
|
|
|
static VALUE
|
|
gm_scripts_rb_client_open(VALUE self, VALUE str) {
|
|
GmWorld *world;
|
|
gchar *strVal;
|
|
|
|
strVal = rb_string_value_cstr(&str);
|
|
|
|
world = gm_app_world_by_name(gm_app_instance(), strVal);
|
|
|
|
if (world == NULL) {
|
|
return Qfalse;
|
|
} else {
|
|
gm_world_load(world);
|
|
return Qtrue;
|
|
}
|
|
}
|
|
|
|
// Ruby scripts class functions
|
|
VALUE
|
|
gm_scripts_rb_scripts_register(int argc, VALUE *argv, VALUE self) {
|
|
char *name, *fname = NULL, *description = NULL;
|
|
gchar *msg;
|
|
GmScripts *scripts;
|
|
|
|
Data_Get_Struct(self, GmScripts, scripts);
|
|
|
|
if (argc > 1) {
|
|
name = rb_string_value_cstr(&argv[0]);
|
|
description = rb_string_value_cstr(&argv[1]);
|
|
|
|
if (argc == 2) {
|
|
fname = name;
|
|
} else {
|
|
fname = rb_string_value_cstr(&argv[2]);
|
|
}
|
|
|
|
if (gm_scripts_add(scripts, name, fname, description)) {
|
|
msg = g_strdup_printf(_("Register function '%s' from '%s'"), name,
|
|
scripts->priv->loading->filename);
|
|
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.RbScriptsRegister: Adding script function "
|
|
"%s from %s", name, scripts->priv->loading->filename);
|
|
g_signal_emit(scripts, gm_scripts_signals[MESSAGE], 0, msg);
|
|
g_free(msg);
|
|
return Qtrue;
|
|
} else {
|
|
msg = g_strdup_printf(_("Script '%s' is already defined"), name);
|
|
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.RbScriptsRegister: Script function %s "
|
|
"already defined!", name);
|
|
g_signal_emit(scripts, gm_scripts_signals[ERROR], 0, msg);
|
|
g_free(msg);
|
|
return Qfalse;
|
|
}
|
|
} else {
|
|
return Qfalse;
|
|
}
|
|
}
|
|
|
|
// Ruby class initializations
|
|
|
|
void
|
|
gm_scripts_rb_world_class_init() {
|
|
rb_world_class = rb_define_class("World", rb_cObject);
|
|
|
|
rb_define_method(rb_world_class, "name", gm_scripts_rb_world_name, 0);
|
|
rb_define_method(rb_world_class, "host", gm_scripts_rb_world_host, 0);
|
|
rb_define_method(rb_world_class, "port", gm_scripts_rb_world_port, 0);
|
|
|
|
rb_define_method(rb_world_class, "writeln", gm_scripts_rb_world_writeln, 1);
|
|
rb_define_method(rb_world_class, "println", gm_scripts_rb_world_writeln, 1);
|
|
rb_define_method(rb_world_class, "status", gm_scripts_rb_world_status, 1);
|
|
rb_define_method(rb_world_class, "sendln", gm_scripts_rb_world_sendln, 1);
|
|
rb_define_method(rb_world_class, "input", gm_scripts_rb_world_input, 1);
|
|
rb_define_method(rb_world_class, "quit", gm_scripts_rb_world_quit, 0);
|
|
rb_define_method(rb_world_class, "connect",
|
|
gm_scripts_rb_world_connect, -1);
|
|
rb_define_method(rb_world_class, "disconnect",
|
|
gm_scripts_rb_world_disconnect, 0);
|
|
rb_define_method(rb_world_class, "loaded?", gm_scripts_rb_world_loaded, 0);
|
|
rb_define_method(rb_world_class, "connected?",
|
|
gm_scripts_rb_world_connected, 0);
|
|
}
|
|
|
|
void
|
|
gm_scripts_rb_client_class_init() {
|
|
rb_client_class = rb_define_class("Client", rb_cObject);
|
|
|
|
rb_define_method(rb_client_class, "version",
|
|
gm_scripts_rb_client_version, 0);
|
|
rb_define_method(rb_client_class, "worlds",
|
|
gm_scripts_rb_client_worlds, 0);
|
|
rb_define_method(rb_client_class, "open", gm_scripts_rb_client_open, 1);
|
|
}
|
|
|
|
void
|
|
gm_scripts_rb_scripts_class_init() {
|
|
rb_scripts_class = rb_define_class("Scripts", rb_cObject);
|
|
|
|
rb_define_method(rb_scripts_class, "register",
|
|
gm_scripts_rb_scripts_register, -1);
|
|
}
|