d3d11screencapturesrc: Specify PAR 1/1 to template caps
[platform/upstream/gstreamer.git] / subprojects / gst-python / plugin / gstpythonplugin.c
1 /* gst-python
2  * Copyright (C) 2009 Edward Hervey <bilboed@bilboed.com>
3  *               2005 Benjamin Otte <otte@gnome.org>
4  *
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.
9  *
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.
14  *
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.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 /* include this first, before NO_IMPORT_PYGOBJECT is defined */
26 #include <pygobject.h>
27 #include <gst/gst.h>
28 #include <gmodule.h>
29 #include <Python.h>
30
31 void *_PyGstElement_Type;
32
33 GST_DEBUG_CATEGORY_STATIC (pyplugindebug);
34 #define GST_CAT_DEFAULT pyplugindebug
35
36 #define GST_ORIGIN "http://gstreamer.freedesktop.org"
37
38 static gboolean
39 gst_python_plugin_load_file (GstPlugin * plugin, const char *name)
40 {
41   PyObject *main_module, *main_locals;
42   PyObject *elementfactory;
43   PyObject *module;
44   const gchar *facname;
45   guint rank;
46   PyObject *class;
47
48   GST_DEBUG ("loading plugin %s", name);
49
50   main_module = PyImport_AddModule ("__main__");
51   if (main_module == NULL) {
52     GST_WARNING ("Could not get __main__, ignoring plugin %s", name);
53     PyErr_Print ();
54     PyErr_Clear ();
55     return FALSE;
56   }
57
58   main_locals = PyModule_GetDict (main_module);
59   module =
60       PyImport_ImportModuleEx ((char *) name, main_locals, main_locals, NULL);
61   if (!module) {
62     GST_DEBUG ("Could not load module, ignoring plugin %s", name);
63     PyErr_Print ();
64     PyErr_Clear ();
65     return FALSE;
66   }
67
68   /* Get __gstelementfactory__ from file */
69   elementfactory = PyObject_GetAttrString (module, "__gstelementfactory__");
70   if (!elementfactory) {
71     GST_DEBUG ("python file doesn't contain __gstelementfactory__");
72     PyErr_Clear ();
73     return FALSE;
74   }
75
76   /* parse tuple : name, rank, gst.ElementClass */
77   if (!PyArg_ParseTuple (elementfactory, "sIO", &facname, &rank, &class)) {
78     GST_WARNING ("__gstelementfactory__ isn't correctly formatted");
79     PyErr_Print ();
80     PyErr_Clear ();
81     Py_DECREF (elementfactory);
82     return FALSE;
83   }
84
85   if (!PyObject_IsSubclass (class, (PyObject *) & PyGObject_Type)) {
86     GST_WARNING ("the class provided isn't a subclass of GObject.Object");
87     PyErr_Print ();
88     PyErr_Clear ();
89     Py_DECREF (elementfactory);
90     Py_DECREF (class);
91     return FALSE;
92   }
93
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");
96     PyErr_Print ();
97     PyErr_Clear ();
98     Py_DECREF (elementfactory);
99     Py_DECREF (class);
100     return FALSE;
101   }
102
103   GST_INFO ("Valid plugin");
104   Py_DECREF (elementfactory);
105
106   return gst_element_register (plugin, facname, rank,
107       pyg_type_from_object (class));
108 }
109
110 static gboolean
111 gst_python_load_directory (GstPlugin * plugin, const gchar * path)
112 {
113   GDir *dir;
114   const gchar *file;
115   GError *error = NULL;
116
117   dir = g_dir_open (path, 0, &error);
118   if (!dir) {
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);
122     return FALSE;
123   }
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);
130       g_free (name);
131     }
132   }
133   return TRUE;
134 }
135
136 static gboolean
137 gst_python_plugin_load (GstPlugin * plugin)
138 {
139   PyObject *sys_path;
140   const gchar *plugin_path;
141   gboolean ret = TRUE;
142
143   sys_path = PySys_GetObject ("path");
144
145   /* Mimic the order in which the registry is checked in core */
146
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");
151   if (plugin_path) {
152     char **list;
153     int i;
154
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);
161       g_free (sysdir);
162     }
163
164     g_strfreev (list);
165   }
166
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) {
172     char *home_plugins;
173
174     /* 2.a. Scan user and system-wide plugin directory */
175     GST_DEBUG ("GST_PLUGIN_SYSTEM_PATH not set");
176
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);
184
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");
188   } else {
189     gchar **list;
190     gint i;
191
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++) {
196       gchar *sysdir;
197
198       sysdir = g_build_filename (list[i], "python", NULL);
199
200       PyList_Insert (sys_path, 0, PyUnicode_FromString (sysdir));
201       gst_python_load_directory (plugin, sysdir);
202       g_free (sysdir);
203     }
204     g_strfreev (list);
205   }
206
207
208   return ret;
209 }
210
211 static gboolean
212 plugin_init (GstPlugin * plugin)
213 {
214   PyGILState_STATE state = 0;
215   PyObject *gi, *require_version, *args, *gst, *dict, *pyplugin;
216   gboolean we_initialized = FALSE;
217   GModule *libpython;
218   gpointer has_python = NULL;
219   const gchar *override_path;
220
221   GST_DEBUG_CATEGORY_INIT (pyplugindebug, "pyplugin", 0,
222       "Python plugin loader");
223
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);
230
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");
235   } else {
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);
240     if (!libpython) {
241       g_critical ("Couldn't g_module_open libpython. Reason: %s",
242           g_module_error ());
243       return FALSE;
244     }
245   }
246
247   if (!Py_IsInitialized ()) {
248     GST_LOG ("python wasn't initialized");
249     /* set the correct plugin for registering stuff */
250     Py_Initialize ();
251     we_initialized = TRUE;
252   } else {
253     GST_LOG ("python was already initialized");
254     state = PyGILState_Ensure ();
255   }
256
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");
262
263     if (!fd || PyRun_SimpleFileExFlags (fd, overrides_setup, 1, 0)) {
264       g_free (overrides_setup);
265
266       return FALSE;
267     } else {
268       g_free (overrides_setup);
269       GST_INFO ("Imported overrides setup");
270     }
271   }
272
273   GST_LOG ("Running with python version '%s'", Py_GetVersion ());
274
275   GST_LOG ("initializing pygobject");
276   if (!pygobject_init (3, 0, 0)) {
277     g_critical ("pygobject initialization failed");
278     return FALSE;
279   }
280
281   gi = PyImport_ImportModule ("gi");
282   if (!gi) {
283     g_critical ("can't find gi");
284     return FALSE;
285   }
286
287
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);
293   Py_DECREF (args);
294   Py_DECREF (gi);
295
296   gst = PyImport_ImportModule ("gi.repository.Gst");
297   if (!gst) {
298     g_critical ("can't find gi.repository.Gst");
299     return FALSE;
300   }
301
302   if (we_initialized) {
303     PyObject *tmp;
304
305     dict = PyModule_GetDict (gst);
306     if (!dict) {
307       g_critical ("gi.repository.Gst is no dict");
308       return FALSE;
309     }
310
311     tmp =
312         PyObject_GetAttr (PyMapping_GetItemString (dict,
313             "_introspection_module"), PyUnicode_FromString ("__dict__"));
314
315     _PyGstElement_Type = PyMapping_GetItemString (tmp, "Element");
316
317     if (!_PyGstElement_Type) {
318       g_critical ("Could not get Gst.Element");
319       return FALSE;
320     }
321
322     pyplugin = pygobject_new (G_OBJECT (plugin));
323     if (!pyplugin || PyModule_AddObject (gst, "__plugin__", pyplugin) != 0) {
324       g_critical ("Couldn't set __plugin__ attribute");
325       if (pyplugin)
326         Py_DECREF (pyplugin);
327       return FALSE;
328     }
329   }
330
331   gst_python_plugin_load (plugin);
332
333   if (we_initialized) {
334     /* We need to release the GIL since we're going back to C land */
335     PyEval_SaveThread ();
336   } else
337     PyGILState_Release (state);
338   return TRUE;
339 }
340
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)