/* * Capa: Capa Assists Photograph Aquisition * * Copyright (C) 2009 Daniel P. Berrange * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include #include "capa-debug.h" #include "capa-plugin-javascript.h" #include #include #include #define CAPA_PLUGIN_JAVASCRIPT_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE((obj), CAPA_TYPE_PLUGIN_JAVASCRIPT, CapaPluginJavascriptPrivate)) struct _CapaPluginJavascriptPrivate { GjsContext *context; gboolean active; }; G_DEFINE_TYPE(CapaPluginJavascript, capa_plugin_javascript, CAPA_TYPE_PLUGIN); /* XXX * Evil hack. THis method is defined in the .so, but not in the * header files. This is the only apparant way to get the * JSContext that we need in order to define new global vars */ JSContext* gjs_context_get_context(GjsContext *js_context); static void capa_plugin_javascript_set_global(CapaPluginJavascript *plugin, const char *name, GObject *value) { CapaPluginJavascriptPrivate *priv = plugin->priv; JSContext *jscontext; JSObject *jsglobal; JSObject *jsvalue; /* XXX * Evil hack. GJS ought to provide a official public API * for defining a global variable from a GObject. */ jscontext = gjs_context_get_context(priv->context); jsglobal = JS_GetGlobalObject(jscontext); JS_EnterLocalRootScope(jscontext); jsvalue = gjs_object_from_g_object(jscontext, value); JS_DefineProperty(jscontext, jsglobal, name, OBJECT_TO_JSVAL(jsvalue), NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT); JS_LeaveLocalRootScope(jscontext); } static gboolean capa_plugin_javascript_eval(CapaPluginJavascript *plugin, GObject *app, const gchar *script) { CapaPluginJavascriptPrivate *priv = plugin->priv; gchar *file; int status; const gchar *searchpath[2]; file = g_strdup_printf("%s/main.js", capa_plugin_get_dir(CAPA_PLUGIN(plugin))); searchpath[0] = capa_plugin_get_dir(CAPA_PLUGIN(plugin)); searchpath[1] = NULL; if (!priv->context) { priv->context = gjs_context_new_with_search_path((gchar **)searchpath); /* We need to do this eval now so that the later * 'gjs_object_from_g_object' * call can find the introspection data it requires */ gjs_context_eval(priv->context, "const Capa = imports.gi.Capa", -1, file, &status, NULL); } capa_plugin_javascript_set_global(plugin, "plugin", G_OBJECT(plugin)); capa_plugin_javascript_set_global(plugin, "app", app); CAPA_DEBUG("Eval javascript '%s' in '%s'\n", script, file); gjs_context_eval(priv->context, script, -1, file, &status, NULL); g_free(file); return status == 0 ? TRUE : FALSE; } static gboolean capa_plugin_javascript_activate(CapaPlugin *iface, GObject *app) { CapaPluginJavascript *plugin = CAPA_PLUGIN_JAVASCRIPT(iface); CapaPluginJavascriptPrivate *priv = plugin->priv; if (priv->active) return TRUE; priv->active = TRUE; return capa_plugin_javascript_eval(plugin, app, "const Main = imports.main; Main.activate(plugin, app);"); } static gboolean capa_plugin_javascript_deactivate(CapaPlugin *iface, GObject *app) { CapaPluginJavascript *plugin = CAPA_PLUGIN_JAVASCRIPT(iface); CapaPluginJavascriptPrivate *priv = plugin->priv; if (!priv->active) return TRUE; priv->active = FALSE; return capa_plugin_javascript_eval(plugin, app, "const Main = imports.main; Main.deactivate(plugin, app);"); } static gboolean capa_plugin_javascript_is_active(CapaPlugin *iface) { CapaPluginJavascript *plugin = CAPA_PLUGIN_JAVASCRIPT(iface); CapaPluginJavascriptPrivate *priv = plugin->priv; return priv->active; } static void capa_plugin_javascript_finalize(GObject *object) { CapaPluginJavascript *plugin = CAPA_PLUGIN_JAVASCRIPT(object); CapaPluginJavascriptPrivate *priv = plugin->priv; g_object_unref(priv->context); G_OBJECT_CLASS(capa_plugin_javascript_parent_class)->finalize (object); } static void capa_plugin_javascript_class_init(CapaPluginJavascriptClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); CapaPluginClass *plugin_class = CAPA_PLUGIN_CLASS (klass); object_class->finalize = capa_plugin_javascript_finalize; plugin_class->activate = capa_plugin_javascript_activate; plugin_class->deactivate = capa_plugin_javascript_deactivate; plugin_class->is_active = capa_plugin_javascript_is_active; g_type_class_add_private(klass, sizeof(CapaPluginJavascriptPrivate)); } void capa_plugin_javascript_init(CapaPluginJavascript *plugin) { CapaPluginJavascriptPrivate *priv; priv = plugin->priv = CAPA_PLUGIN_JAVASCRIPT_GET_PRIVATE(plugin); memset(priv, 0, sizeof(*priv)); } /* * Local variables: * c-indent-level: 4 * c-basic-offset: 4 * indent-tabs-mode: nil * tab-width: 8 * End: */