2 * Copyright (C) 2009 Edward Hervey <bilboed@bilboed.com>
3 * 2005 Benjamin Otte <otte@gnome.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library 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 GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
25 /* include this first, before NO_IMPORT_PYGOBJECT is defined */
26 #include <pygobject.h>
31 void *_PyGstElement_Type;
33 GST_DEBUG_CATEGORY_STATIC (pyplugindebug);
34 #define GST_CAT_DEFAULT pyplugindebug
36 #define GST_ORIGIN "http://gstreamer.freedesktop.org"
39 gst_python_plugin_load_file (GstPlugin * plugin, const char *name)
41 PyObject *main_module, *main_locals;
42 PyObject *elementfactory;
48 GST_DEBUG ("loading plugin %s", name);
50 main_module = PyImport_AddModule ("__main__");
51 if (main_module == NULL) {
52 GST_WARNING ("Could not get __main__, ignoring plugin %s", name);
58 main_locals = PyModule_GetDict (main_module);
60 PyImport_ImportModuleEx ((char *) name, main_locals, main_locals, NULL);
62 GST_DEBUG ("Could not load module, ignoring plugin %s", name);
68 /* Get __gstelementfactory__ from file */
69 elementfactory = PyObject_GetAttrString (module, "__gstelementfactory__");
70 if (!elementfactory) {
71 GST_DEBUG ("python file doesn't contain __gstelementfactory__");
76 /* parse tuple : name, rank, gst.ElementClass */
77 if (!PyArg_ParseTuple (elementfactory, "sIO", &facname, &rank, &class)) {
78 GST_WARNING ("__gstelementfactory__ isn't correctly formatted");
81 Py_DECREF (elementfactory);
85 if (!PyObject_IsSubclass (class, (PyObject *) & PyGObject_Type)) {
86 GST_WARNING ("the class provided isn't a subclass of GObject.Object");
89 Py_DECREF (elementfactory);
94 if (!g_type_is_a (pyg_type_from_object (class), GST_TYPE_ELEMENT)) {
95 GST_WARNING ("the class provided isn't a subclass of Gst.Element");
98 Py_DECREF (elementfactory);
103 GST_INFO ("Valid plugin");
104 Py_DECREF (elementfactory);
106 return gst_element_register (plugin, facname, rank,
107 pyg_type_from_object (class));
111 gst_python_load_directory (GstPlugin * plugin, const gchar * path)
115 GError *error = NULL;
117 dir = g_dir_open (path, 0, &error);
119 /*retval should probably be depending on error, but since we ignore it... */
120 GST_DEBUG ("Couldn't open Python plugin dir: %s", error->message);
121 g_error_free (error);
124 while ((file = g_dir_read_name (dir))) {
125 /* FIXME : go down in subdirectories */
126 if (g_str_has_suffix (file, ".py")) {
127 gsize len = strlen (file) - 3;
128 gchar *name = g_strndup (file, len);
129 gst_python_plugin_load_file (plugin, name);
137 gst_python_plugin_load (GstPlugin * plugin)
140 const gchar *plugin_path;
143 sys_path = PySys_GetObject ("path");
145 /* Mimic the order in which the registry is checked in core */
147 /* 1. check env_variable GST_PLUGIN_PATH */
148 plugin_path = g_getenv ("GST_PLUGIN_PATH_1_0");
149 if (plugin_path == NULL)
150 plugin_path = g_getenv ("GST_PLUGIN_PATH");
155 GST_DEBUG ("GST_PLUGIN_PATH set to %s", plugin_path);
156 list = g_strsplit (plugin_path, G_SEARCHPATH_SEPARATOR_S, 0);
157 for (i = 0; list[i]; i++) {
158 gchar *sysdir = g_build_filename (list[i], "python", NULL);
159 PyList_Insert (sys_path, 0, PyUnicode_FromString (sysdir));
160 gst_python_load_directory (plugin, sysdir);
167 /* 2. Check for GST_PLUGIN_SYSTEM_PATH */
168 plugin_path = g_getenv ("GST_PLUGIN_SYSTEM_PATH_1_0");
169 if (plugin_path == NULL)
170 plugin_path = g_getenv ("GST_PLUGIN_SYSTEM_PATH");
171 if (plugin_path == NULL) {
174 /* 2.a. Scan user and system-wide plugin directory */
175 GST_DEBUG ("GST_PLUGIN_SYSTEM_PATH not set");
177 /* plugins in the user's home directory take precedence over
178 * system-installed ones */
179 home_plugins = g_build_filename (g_get_home_dir (),
180 ".gstreamer-" GST_API_VERSION, "plugins", "python", NULL);
181 PyList_Insert (sys_path, 0, PyUnicode_FromString (home_plugins));
182 gst_python_load_directory (plugin, home_plugins);
183 g_free (home_plugins);
185 /* add the main (installed) library path */
186 PyList_Insert (sys_path, 0, PyUnicode_FromString (PLUGINDIR "/python"));
187 gst_python_load_directory (plugin, PLUGINDIR "/python");
192 /* 2.b. Scan GST_PLUGIN_SYSTEM_PATH */
193 GST_DEBUG ("GST_PLUGIN_SYSTEM_PATH set to %s", plugin_path);
194 list = g_strsplit (plugin_path, G_SEARCHPATH_SEPARATOR_S, 0);
195 for (i = 0; list[i]; i++) {
198 sysdir = g_build_filename (list[i], "python", NULL);
200 PyList_Insert (sys_path, 0, PyUnicode_FromString (sysdir));
201 gst_python_load_directory (plugin, sysdir);
212 plugin_init (GstPlugin * plugin)
214 PyGILState_STATE state = 0;
215 PyObject *gi, *require_version, *args, *gst, *dict, *pyplugin;
216 gboolean we_initialized = FALSE;
218 gpointer has_python = NULL;
219 const gchar *override_path;
221 GST_DEBUG_CATEGORY_INIT (pyplugindebug, "pyplugin", 0,
222 "Python plugin loader");
224 gst_plugin_add_dependency_simple (plugin,
225 "HOME/.gstreamer-" GST_API_VERSION
226 "/plugins/python:GST_PLUGIN_SYSTEM_PATH/python:GST_PLUGIN_PATH/python",
227 PLUGINDIR "/python:HOME/.gstreamer-" GST_API_VERSION "/plugins/python:"
228 "GST_PLUGIN_SYSTEM_PATH/python:GST_PLUGIN_PATH/python", NULL,
229 GST_PLUGIN_DEPENDENCY_FLAG_NONE);
231 GST_LOG ("Checking to see if libpython is already loaded");
232 if (g_module_symbol (g_module_open (NULL, G_MODULE_BIND_LOCAL),
233 "_Py_NoneStruct", &has_python) && has_python) {
234 GST_LOG ("libpython is already loaded");
236 const gchar *libpython_path =
237 PY_LIB_LOC "/libpython" PYTHON_VERSION PY_ABI_FLAGS "." PY_LIB_SUFFIX;
238 GST_LOG ("loading libpython from '%s'", libpython_path);
239 libpython = g_module_open (libpython_path, 0);
241 g_critical ("Couldn't g_module_open libpython. Reason: %s",
247 if (!Py_IsInitialized ()) {
248 GST_LOG ("python wasn't initialized");
249 /* set the correct plugin for registering stuff */
251 we_initialized = TRUE;
253 GST_LOG ("python was already initialized");
254 state = PyGILState_Ensure ();
257 if ((override_path = g_getenv ("GST_OVERRIDE_SRC_PATH"))) {
258 gchar *overrides_setup =
259 g_build_filename (override_path, "..", "..", "testsuite",
260 "overrides_hack.py", NULL);
261 FILE *fd = fopen (overrides_setup, "rb");
263 if (!fd || PyRun_SimpleFileExFlags (fd, overrides_setup, 1, 0)) {
264 g_free (overrides_setup);
268 g_free (overrides_setup);
269 GST_INFO ("Imported overrides setup");
273 GST_LOG ("Running with python version '%s'", Py_GetVersion ());
275 GST_LOG ("initializing pygobject");
276 if (!pygobject_init (3, 0, 0)) {
277 g_critical ("pygobject initialization failed");
281 gi = PyImport_ImportModule ("gi");
283 g_critical ("can't find gi");
288 require_version = PyObject_GetAttrString (gi, (char *) "require_version");
289 args = PyTuple_Pack (2, PyUnicode_FromString ("Gst"),
290 PyUnicode_FromString ("1.0"));
291 PyObject_CallObject (require_version, args);
292 Py_DECREF (require_version);
296 gst = PyImport_ImportModule ("gi.repository.Gst");
298 g_critical ("can't find gi.repository.Gst");
302 if (we_initialized) {
305 dict = PyModule_GetDict (gst);
307 g_critical ("gi.repository.Gst is no dict");
312 PyObject_GetAttr (PyMapping_GetItemString (dict,
313 "_introspection_module"), PyUnicode_FromString ("__dict__"));
315 _PyGstElement_Type = PyMapping_GetItemString (tmp, "Element");
317 if (!_PyGstElement_Type) {
318 g_critical ("Could not get Gst.Element");
322 pyplugin = pygobject_new (G_OBJECT (plugin));
323 if (!pyplugin || PyModule_AddObject (gst, "__plugin__", pyplugin) != 0) {
324 g_critical ("Couldn't set __plugin__ attribute");
326 Py_DECREF (pyplugin);
331 gst_python_plugin_load (plugin);
333 if (we_initialized) {
334 /* We need to release the GIL since we're going back to C land */
335 PyEval_SaveThread ();
337 PyGILState_Release (state);
341 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
342 GST_VERSION_MINOR, python,
343 "loader for plugins written in python",
344 plugin_init, VERSION, "LGPL", PACKAGE_NAME, GST_ORIGIN)