Updated Finnish translation
[rhythmbox.git] / plugins / rb-python-module.c
blobaaa47481a61e583bdd7de799b85d0721fab5520e
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.
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #include <pygobject.h>
26 #include <pygtk/pygtk.h>
28 #include <signal.h>
30 #include <gmodule.h>
32 #include "rb-plugin.h"
33 #include "rb-python-module.h"
34 #include "rb-python-plugin.h"
35 #include "rb-debug.h"
37 #define RB_PYTHON_MODULE_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), \
38 RB_TYPE_PYTHON_MODULE, \
39 RBPythonModulePrivate))
41 typedef struct
43 gchar *module;
44 gchar *path;
45 GType type;
46 } RBPythonModulePrivate;
48 enum
50 PROP_0,
51 PROP_PATH,
52 PROP_MODULE
55 #ifndef PYGOBJECT_CAN_MARSHAL_GVALUE
56 static PyObject *
57 pyg_value_g_value_as_pyobject (const GValue *value)
59 return pyg_value_as_pyobject((GValue *)g_value_get_boxed(value), FALSE);
62 static int
63 pyg_value_g_value_from_pyobject (GValue *value, PyObject *obj)
65 GType type;
66 GValue obj_value = { 0, };
68 type = pyg_type_from_object((PyObject *) obj->ob_type);
69 if (! type) {
70 PyErr_Clear();
71 return -1;
73 g_value_init(&obj_value, type);
74 if (pyg_value_from_pyobject(&obj_value, obj) == -1) {
75 g_value_unset(&obj_value);
76 return -1;
78 g_value_set_boxed(value, &obj_value);
79 g_value_unset(&obj_value);
80 return 0;
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);
99 static void
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;
105 PyObject *sys_path;
106 struct sigaction old_sigint;
107 gint res;
108 char *argv[] = { "rb", "rhythmdb", NULL };
109 GList *paths;
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);
121 if (res != 0) {
122 g_warning ("Error initializing Python interpreter: cannot get "
123 "handler to SIGINT signal (%s)",
124 strerror (errno));
126 return;
129 /* Python initialization */
130 Py_Initialize ();
132 /* Restore old handler */
133 res = sigaction (SIGINT, &old_sigint, NULL);
134 if (res != 0) {
135 g_warning ("Error initializing Python interpreter: cannot restore "
136 "handler to SIGINT signal (%s)",
137 strerror (errno));
138 return;
141 PySys_SetArgv (1, argv);
143 /* pygtk.require("2.8") */
144 pygtk = PyImport_ImportModule ("pygtk");
145 if (pygtk == NULL) {
146 g_warning ("Could not import pygtk");
147 PyErr_Print();
148 return;
151 mdict = PyModule_GetDict (pygtk);
152 require = PyDict_GetItemString (mdict, "require");
153 PyObject_CallObject (require, Py_BuildValue ("(S)", PyString_FromString ("2.8")));
155 /* import gobject */
156 init_pygobject ();
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);
160 #endif
162 /* import gtk */
163 init_pygtk ();
165 gtk = PyImport_ImportModule ("gtk");
166 if (gtk == NULL) {
167 g_warning ("Could not import gtk");
168 PyErr_Print();
169 return;
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);
180 return;
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_");
191 /* import rb */
192 paths = rb_get_plugin_paths ();
193 sys_path = PySys_GetObject ("path");
194 while (paths != NULL) {
195 PyObject *path;
197 path = PyString_FromString (paths->data);
198 if (PySequence_Contains (sys_path, path) == 0) {
199 PyList_Insert (sys_path, 0, path);
201 Py_DECREF (path);
202 g_free (paths->data);
203 paths = g_list_delete_link (paths, paths);
206 rb = PyImport_ImportModule ("rb");
208 if (rb == NULL) {
209 g_warning ("could not import python module 'rb'");
210 PyErr_Print ();
211 return;
214 /* add pyrb_functions */
215 for (res = 0; pyrb_functions[res].ml_name != NULL; res++) {
216 PyObject *func;
218 func = PyCFunction_New (&pyrb_functions[res], rb);
219 if (func == NULL) {
220 g_warning ("unable object for function '%s' create", pyrb_functions[res].ml_name);
221 PyErr_Print ();
222 return;
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);
226 PyErr_Print ();
227 return;
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) {
238 PyErr_Print ();
239 return;
242 /* i18n support */
243 gettext = PyImport_ImportModule ("gettext");
244 if (gettext == NULL) {
245 g_warning ("Could not import gettext");
246 PyErr_Print();
247 return;
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);
257 static gboolean
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;
263 int pos = 0;
265 main_module = PyImport_AddModule ("__main__");
266 if (main_module == NULL)
268 g_warning ("Could not get __main__.");
269 return FALSE;
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);
281 Py_DECREF(path);
284 main_locals = PyModule_GetDict (main_module);
285 /* we need a fromlist to be able to import modules with a '.' in the
286 name. */
287 fromlist = PyTuple_New(0);
288 module = PyImport_ImportModuleEx (priv->module, main_locals,
289 main_locals, fromlist);
290 Py_DECREF (fromlist);
291 if (!module) {
292 PyErr_Print ();
293 return FALSE;
296 locals = PyModule_GetDict (module);
297 while (PyDict_Next (locals, &pos, &key, &value))
299 if (!PyType_Check(value))
300 continue;
302 if (PyObject_IsSubclass (value, (PyObject*) PyRBPlugin_Type))
304 priv->type = rb_python_object_get_type (gmodule, value);
305 return TRUE;
309 return FALSE;
312 static void
313 rb_python_module_unload (GTypeModule *module)
315 RBPythonModulePrivate *priv = RB_PYTHON_MODULE_GET_PRIVATE (module);
316 rb_debug ("Unloading python module");
318 priv->type = 0;
321 GObject *
322 rb_python_module_new_object (RBPythonModule *module)
324 RBPythonModulePrivate *priv = RB_PYTHON_MODULE_GET_PRIVATE (module);
325 RBPythonObject *object;
327 if (priv->type == 0)
328 return NULL;
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,
333 NULL));
334 if (object->instance == NULL) {
335 g_warning ("could not instantiate python object");
336 return NULL;
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);
352 static void
353 rb_python_module_init (RBPythonModule *module)
355 rb_debug ("Init of python module");
358 static void
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);
365 g_free (priv->path);
367 G_OBJECT_CLASS (rb_python_module_parent_class)->finalize (object);
370 static void
371 rb_python_module_get_property (GObject *object,
372 guint prop_id,
373 GValue *value,
374 GParamSpec *pspec)
376 /* no readable properties */
377 g_return_if_reached ();
380 static void
381 rb_python_module_set_property (GObject *object,
382 guint prop_id,
383 const GValue *value,
384 GParamSpec *pspec)
386 RBPythonModule *mod = RB_PYTHON_MODULE (object);
388 switch (prop_id)
390 case PROP_MODULE:
391 RB_PYTHON_MODULE_GET_PRIVATE (mod)->module = g_value_dup_string (value);
392 break;
393 case PROP_PATH:
394 RB_PYTHON_MODULE_GET_PRIVATE (mod)->path = g_value_dup_string (value);
395 break;
396 default:
397 g_return_if_reached ();
401 static void
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
412 (object_class,
413 PROP_MODULE,
414 g_param_spec_string ("module",
415 "Module Name",
416 "The python module to load for this plugin",
417 NULL,
418 G_PARAM_WRITABLE | G_PARAM_READABLE | G_PARAM_CONSTRUCT_ONLY));
420 g_object_class_install_property
421 (object_class,
422 PROP_PATH,
423 g_param_spec_string ("path",
424 "Path",
425 "The python path to use when loading this module",
426 NULL,
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 ();
440 RBPythonModule *
441 rb_python_module_new (const gchar *path,
442 const gchar *module)
444 RBPythonModule *result;
445 gchar *dir;
447 if (module == NULL || module[0] == '\0')
448 return NULL;
450 dir = g_path_get_dirname (path);
451 result = g_object_new (RB_TYPE_PYTHON_MODULE,
452 "module", module,
453 "path", dir,
454 NULL);
455 g_free (dir);
457 g_type_module_set_name (G_TYPE_MODULE (result), module);
459 return result;
462 /* --- these are not module methods, they are here out of convenience --- */
464 static gint idle_garbage_collect_id = 0;
466 static gboolean
467 run_gc (gpointer data)
469 while (PyGC_Collect ())
472 idle_garbage_collect_id = 0;
474 return FALSE;
477 void
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);
485 static gboolean
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)");
495 return TRUE;
498 void
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;
507 run_gc (NULL);
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
512 Py_Finalize ();*/