1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3 * Copyright (C) 2005 Raphael Slinckx
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301 USA.
25 #include <pygobject.h>
26 #include <pygtk/pygtk.h>
32 #include "rb-plugin.h"
33 #include "rb-python-module.h"
34 #include "rb-python-plugin.h"
37 #define RB_PYTHON_MODULE_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), \
38 RB_TYPE_PYTHON_MODULE, \
39 RBPythonModulePrivate))
46 } RBPythonModulePrivate
;
55 #ifndef PYGOBJECT_CAN_MARSHAL_GVALUE
57 pyg_value_g_value_as_pyobject (const GValue
*value
)
59 return pyg_value_as_pyobject((GValue
*)g_value_get_boxed(value
), FALSE
);
63 pyg_value_g_value_from_pyobject (GValue
*value
, PyObject
*obj
)
66 GValue obj_value
= { 0, };
68 type
= pyg_type_from_object((PyObject
*) obj
->ob_type
);
73 g_value_init(&obj_value
, type
);
74 if (pyg_value_from_pyobject(&obj_value
, obj
) == -1) {
75 g_value_unset(&obj_value
);
78 g_value_set_boxed(value
, &obj_value
);
79 g_value_unset(&obj_value
);
82 #endif /* PYGOBJECT_CAN_MARSHAL_GVALUE */
84 /* Exported by pyrhythmdb module */
85 void pyrhythmdb_register_classes (PyObject
*d
);
86 void pyrhythmdb_add_constants (PyObject
*module
, const gchar
*strip_prefix
);
87 extern PyMethodDef pyrhythmdb_functions
[];
89 /* Exported by pyrb module */
90 void pyrb_register_classes (PyObject
*d
);
91 void pyrb_add_constants (PyObject
*module
, const gchar
*strip_prefix
);
92 extern PyMethodDef pyrb_functions
[];
94 /* We retreive this to check for correct class hierarchy */
95 static PyTypeObject
*PyRBPlugin_Type
;
97 G_DEFINE_TYPE (RBPythonModule
, rb_python_module
, G_TYPE_TYPE_MODULE
);
100 rb_python_module_init_python (void)
102 PyObject
*pygtk
, *mdict
, *require
;
103 PyObject
*rb
, *rhythmdb
, *gtk
, *pygtk_version
, *pygtk_required_version
;
104 PyObject
*gettext
, *install
, *gettext_args
;
106 struct sigaction old_sigint
;
108 char *argv
[] = { "rb", "rhythmdb", NULL
};
111 if (Py_IsInitialized ()) {
112 g_warning ("Python Should only be initialized once, since it's in class_init");
113 g_return_if_reached ();
116 /* Hack to make python not overwrite SIGINT: this is needed to avoid
117 * the crash reported on gedit bug #326191 */
119 /* Save old handler */
120 res
= sigaction (SIGINT
, NULL
, &old_sigint
);
122 g_warning ("Error initializing Python interpreter: cannot get "
123 "handler to SIGINT signal (%s)",
129 /* Python initialization */
132 /* Restore old handler */
133 res
= sigaction (SIGINT
, &old_sigint
, NULL
);
135 g_warning ("Error initializing Python interpreter: cannot restore "
136 "handler to SIGINT signal (%s)",
141 PySys_SetArgv (1, argv
);
143 /* pygtk.require("2.8") */
144 pygtk
= PyImport_ImportModule ("pygtk");
146 g_warning ("Could not import pygtk");
151 mdict
= PyModule_GetDict (pygtk
);
152 require
= PyDict_GetItemString (mdict
, "require");
153 PyObject_CallObject (require
, Py_BuildValue ("(S)", PyString_FromString ("2.8")));
158 #ifndef PYGOBJECT_CAN_MARSHAL_GVALUE
159 pyg_register_gtype_custom (G_TYPE_VALUE
, pyg_value_g_value_as_pyobject
, pyg_value_g_value_from_pyobject
);
165 gtk
= PyImport_ImportModule ("gtk");
167 g_warning ("Could not import gtk");
172 mdict
= PyModule_GetDict (gtk
);
173 pygtk_version
= PyDict_GetItemString (mdict
, "pygtk_version");
174 pygtk_required_version
= Py_BuildValue ("(iii)", 2, 4, 0);
175 if (PyObject_Compare (pygtk_version
, pygtk_required_version
) == -1) {
176 g_warning("PyGTK %s required, but %s found.",
177 PyString_AsString (PyObject_Repr (pygtk_required_version
)),
178 PyString_AsString (PyObject_Repr (pygtk_version
)));
179 Py_DECREF (pygtk_required_version
);
182 Py_DECREF (pygtk_required_version
);
184 /* import rhythmdb */
185 rhythmdb
= Py_InitModule ("rhythmdb", pyrhythmdb_functions
);
186 mdict
= PyModule_GetDict (rhythmdb
);
188 pyrhythmdb_register_classes (mdict
);
189 pyrhythmdb_add_constants (rhythmdb
, "RHYTHMDB_");
192 paths
= rb_get_plugin_paths ();
193 sys_path
= PySys_GetObject ("path");
194 while (paths
!= NULL
) {
197 path
= PyString_FromString (paths
->data
);
198 if (PySequence_Contains (sys_path
, path
) == 0) {
199 PyList_Insert (sys_path
, 0, path
);
202 g_free (paths
->data
);
203 paths
= g_list_delete_link (paths
, paths
);
206 rb
= PyImport_ImportModule ("rb");
209 g_warning ("could not import python module 'rb'");
214 /* add pyrb_functions */
215 for (res
= 0; pyrb_functions
[res
].ml_name
!= NULL
; res
++) {
218 func
= PyCFunction_New (&pyrb_functions
[res
], rb
);
220 g_warning ("unable object for function '%s' create", pyrb_functions
[res
].ml_name
);
224 if (PyModule_AddObject (rb
, pyrb_functions
[res
].ml_name
, func
) < 0) {
225 g_warning ("unable to insert function '%s' in 'rb' module", pyrb_functions
[res
].ml_name
);
230 mdict
= PyModule_GetDict (rb
);
232 pyrb_register_classes (mdict
);
233 pyrb_add_constants (rb
, "RB_");
235 /* Retreive the Python type for rb.Plugin */
236 PyRBPlugin_Type
= (PyTypeObject
*) PyDict_GetItemString (mdict
, "Plugin");
237 if (PyRBPlugin_Type
== NULL
) {
243 gettext
= PyImport_ImportModule ("gettext");
244 if (gettext
== NULL
) {
245 g_warning ("Could not import gettext");
250 mdict
= PyModule_GetDict (gettext
);
251 install
= PyDict_GetItemString (mdict
, "install");
252 gettext_args
= Py_BuildValue ("ss", GETTEXT_PACKAGE
, GNOMELOCALEDIR
);
253 PyObject_CallObject (install
, gettext_args
);
254 Py_DECREF (gettext_args
);
258 rb_python_module_load (GTypeModule
*gmodule
)
260 RBPythonModulePrivate
*priv
= RB_PYTHON_MODULE_GET_PRIVATE (gmodule
);
261 PyObject
*main_module
, *main_locals
, *locals
, *key
, *value
;
262 PyObject
*module
, *fromlist
;
265 main_module
= PyImport_AddModule ("__main__");
266 if (main_module
== NULL
)
268 g_warning ("Could not get __main__.");
272 /* If we have a special path, we register it */
273 if (priv
->path
!= NULL
)
275 PyObject
*sys_path
= PySys_GetObject ("path");
276 PyObject
*path
= PyString_FromString (priv
->path
);
278 if (PySequence_Contains(sys_path
, path
) == 0)
279 PyList_Insert (sys_path
, 0, path
);
284 main_locals
= PyModule_GetDict (main_module
);
285 /* we need a fromlist to be able to import modules with a '.' in the
287 fromlist
= PyTuple_New(0);
288 module
= PyImport_ImportModuleEx (priv
->module
, main_locals
,
289 main_locals
, fromlist
);
290 Py_DECREF (fromlist
);
296 locals
= PyModule_GetDict (module
);
297 while (PyDict_Next (locals
, &pos
, &key
, &value
))
299 if (!PyType_Check(value
))
302 if (PyObject_IsSubclass (value
, (PyObject
*) PyRBPlugin_Type
))
304 priv
->type
= rb_python_object_get_type (gmodule
, value
);
313 rb_python_module_unload (GTypeModule
*module
)
315 RBPythonModulePrivate
*priv
= RB_PYTHON_MODULE_GET_PRIVATE (module
);
316 rb_debug ("Unloading python module");
322 rb_python_module_new_object (RBPythonModule
*module
)
324 RBPythonModulePrivate
*priv
= RB_PYTHON_MODULE_GET_PRIVATE (module
);
325 RBPythonObject
*object
;
330 rb_debug ("Creating object of type %s", g_type_name (priv
->type
));
331 object
= (RBPythonObject
*) (g_object_new (priv
->type
,
332 "name", priv
->module
,
334 if (object
->instance
== NULL
) {
335 g_warning ("could not instantiate python object");
339 /* FIXME, HACK: this is a hack because the gobject object->instance references
340 * isn't the same gobject as we think it is. Which Causes Issues.
342 * This still has issues, notably that it isn't safe to call any rb.Plugin methods
343 * from python before we get here.
345 * The solution is to not have weird proxy objects.
347 g_object_set (((PyGObject
*)(object
->instance
))->obj
, "name", priv
->module
, NULL
);
349 return G_OBJECT (object
);
353 rb_python_module_init (RBPythonModule
*module
)
355 rb_debug ("Init of python module");
359 rb_python_module_finalize (GObject
*object
)
361 RBPythonModulePrivate
*priv
= RB_PYTHON_MODULE_GET_PRIVATE (object
);
362 rb_debug ("Finalizing python module %s", g_type_name (priv
->type
));
364 g_free (priv
->module
);
367 G_OBJECT_CLASS (rb_python_module_parent_class
)->finalize (object
);
371 rb_python_module_get_property (GObject
*object
,
376 /* no readable properties */
377 g_return_if_reached ();
381 rb_python_module_set_property (GObject
*object
,
386 RBPythonModule
*mod
= RB_PYTHON_MODULE (object
);
391 RB_PYTHON_MODULE_GET_PRIVATE (mod
)->module
= g_value_dup_string (value
);
394 RB_PYTHON_MODULE_GET_PRIVATE (mod
)->path
= g_value_dup_string (value
);
397 g_return_if_reached ();
402 rb_python_module_class_init (RBPythonModuleClass
*class)
404 GObjectClass
*object_class
= G_OBJECT_CLASS (class);
405 GTypeModuleClass
*module_class
= G_TYPE_MODULE_CLASS (class);
407 object_class
->finalize
= rb_python_module_finalize
;
408 object_class
->get_property
= rb_python_module_get_property
;
409 object_class
->set_property
= rb_python_module_set_property
;
411 g_object_class_install_property
414 g_param_spec_string ("module",
416 "The python module to load for this plugin",
418 G_PARAM_WRITABLE
| G_PARAM_READABLE
| G_PARAM_CONSTRUCT_ONLY
));
420 g_object_class_install_property
423 g_param_spec_string ("path",
425 "The python path to use when loading this module",
427 G_PARAM_WRITABLE
| G_PARAM_READABLE
| G_PARAM_CONSTRUCT_ONLY
));
429 g_type_class_add_private (object_class
, sizeof (RBPythonModulePrivate
));
431 module_class
->load
= rb_python_module_load
;
432 module_class
->unload
= rb_python_module_unload
;
434 /* Init python subsystem, this should happen only once
435 * in the process lifetime, and doing it here is ok since
436 * class_init is called once */
437 rb_python_module_init_python ();
441 rb_python_module_new (const gchar
*path
,
444 RBPythonModule
*result
;
447 if (module
== NULL
|| module
[0] == '\0')
450 dir
= g_path_get_dirname (path
);
451 result
= g_object_new (RB_TYPE_PYTHON_MODULE
,
457 g_type_module_set_name (G_TYPE_MODULE (result
), module
);
462 /* --- these are not module methods, they are here out of convenience --- */
464 static gint idle_garbage_collect_id
= 0;
467 run_gc (gpointer data
)
469 while (PyGC_Collect ())
472 idle_garbage_collect_id
= 0;
478 rb_python_garbage_collect ()
480 if (Py_IsInitialized() && idle_garbage_collect_id
== 0) {
481 idle_garbage_collect_id
= g_idle_add (run_gc
, NULL
);
486 finalise_collect_cb (gpointer data
)
488 while (PyGC_Collect ())
491 /* useful if python is refusing to give up it's shell reference for some reason.
492 PyRun_SimpleString ("import gc, gobject\nfor o in gc.get_objects():\n\tif isinstance(o, gobject.GObject):\n\t\tprint o, gc.get_referrers(o)");
499 rb_python_shutdown ()
501 if (Py_IsInitialized ()) {
502 if (idle_garbage_collect_id
!= 0) {
503 g_source_remove (idle_garbage_collect_id
);
504 idle_garbage_collect_id
= 0;
508 /* this helps to force python to give up it's shell reference */
509 g_timeout_add (1000, finalise_collect_cb
, NULL
);
511 /* disable for now, due to bug 334188