python: Avoid treating float as int
[platform/upstream/gstreamer.git] / subprojects / gst-python / gi / overrides / gstmodule.c
1 /* -*- Mode: C; ; c-file-style: "k&r"; c-basic-offset: 4 -*- */
2 /* gst-python
3  * Copyright (C) 2002 David I. Lehn
4  * Copyright (C) 2012 Thibault Saunier <thibault.saunier@collabora.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  * Author: David I. Lehn <dlehn@users.sourceforge.net>
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 /* include this first, before NO_IMPORT_PYGOBJECT is defined */
29 #include <Python.h>
30 #include <pygobject.h>
31 #include <gst/gst.h>
32
33 #include <locale.h>
34
35 #define PYGLIB_MODULE_START(symbol, modname)            \
36     static struct PyModuleDef _##symbol##module = {     \
37     PyModuleDef_HEAD_INIT,                              \
38     modname,                                            \
39     NULL,                                               \
40     -1,                                                 \
41     symbol##_functions,                                 \
42     NULL,                                               \
43     NULL,                                               \
44     NULL,                                               \
45     NULL                                                \
46 };                                                      \
47 PyMODINIT_FUNC PyInit_##symbol(void);                   \
48 PyMODINIT_FUNC PyInit_##symbol(void)                    \
49 {                                                       \
50     PyObject *module;                                   \
51     module = PyModule_Create(&_##symbol##module);
52 #define PYGLIB_MODULE_END return module; }
53
54 GST_DEBUG_CATEGORY_STATIC (python_debug);
55 GST_DEBUG_CATEGORY_STATIC (pygst_debug);
56 #define GST_CAT_DEFAULT pygst_debug
57
58 static PyObject *
59 gi_gst_get_type (const gchar * type_name)
60 {
61   PyObject *module, *dict;
62
63   module = PyImport_ImportModule ("gi.repository.Gst");
64
65   if (module == NULL) {
66     PyErr_SetString (PyExc_KeyError,
67         "Could not get module for gi.repository.Gst");
68     return NULL;
69   }
70
71   dict = PyModule_GetDict (module);
72   Py_DECREF (module);
73
74   /* For some reason we need this intermediary step */
75   module = PyMapping_GetItemString (dict, "_overrides_module");
76   if (module == NULL) {
77     PyErr_SetString (PyExc_KeyError,
78         "Could not get module for _overrides_module");
79     return NULL;
80   }
81
82   dict = PyModule_GetDict (module);
83   return PyMapping_GetItemString (dict, type_name);
84 }
85
86 static PyObject *
87 gi_gst_fraction_from_value (const GValue * value)
88 {
89   PyObject *fraction_type, *args, *fraction;
90   gint numerator, denominator;
91
92   numerator = gst_value_get_fraction_numerator (value);
93   denominator = gst_value_get_fraction_denominator (value);
94
95   fraction_type = gi_gst_get_type ("Fraction");
96
97   args = Py_BuildValue ("(ii)", numerator, denominator);
98   fraction = PyObject_Call (fraction_type, args, NULL);
99   Py_DECREF (args);
100
101   return fraction;
102 }
103
104 static int
105 gi_gst_fraction_to_value (GValue * value, PyObject * object)
106 {
107   glong numerator, denominator;
108   PyObject *numerator_obj, *denominator_obj, *is_integer;
109
110   numerator_obj = PyObject_GetAttrString (object, "num");
111   if (numerator_obj == NULL)
112     goto fail;
113
114   is_integer = PyObject_CallMethod (numerator_obj, "is_integer", NULL);
115   if (is_integer != Py_True) {
116     PyErr_Format (PyExc_TypeError,
117         "numerator %f is not an integer.", PyFloat_AsDouble (numerator_obj));
118     Py_DECREF (is_integer);
119     goto fail;
120   }
121   Py_DECREF (is_integer);
122
123   numerator = PyFloat_AsDouble (numerator_obj);
124   if (numerator < -G_MAXINT || numerator > G_MAXINT) {
125     PyErr_Format (PyExc_ValueError,
126         "numerator %" G_GINT64_FORMAT " is out of bound. [-%d - %d]",
127         numerator, G_MAXINT, G_MAXINT);
128     goto fail;
129   }
130
131   denominator_obj = PyObject_GetAttrString (object, "denom");
132   if (denominator_obj == NULL)
133     goto fail;
134
135   is_integer = PyObject_CallMethod (denominator_obj, "is_integer", NULL);
136   if (is_integer != Py_True) {
137     PyErr_Format (PyExc_TypeError,
138         "denominator %f is not an integer.",
139         PyFloat_AsDouble (denominator_obj));
140     Py_DECREF (is_integer);
141     goto fail;
142   }
143   Py_DECREF (is_integer);
144
145   denominator = PyFloat_AsDouble (denominator_obj);
146   if (denominator == 0) {
147     PyErr_SetString (PyExc_ValueError, "denominator is 0.");
148     goto fail;
149   }
150
151   if (denominator < -G_MAXINT || denominator > G_MAXINT) {
152     PyErr_Format (PyExc_ValueError,
153         "denominator %" G_GINT64_FORMAT " is out of bound. [-%d - %d]",
154         denominator, G_MAXINT, G_MAXINT);
155     goto fail;
156   }
157
158   gst_value_set_fraction (value, numerator, denominator);
159
160   return 0;
161
162 fail:
163   return -1;
164 }
165
166 static PyObject *
167 gi_gst_int_range_from_value (const GValue * value)
168 {
169   gint min, max, step;
170   PyObject *int_range_type, *int_range, *range;
171
172   min = gst_value_get_int_range_min (value);
173   max = gst_value_get_int_range_max (value);
174   step = gst_value_get_int_range_step (value);
175
176   int_range_type = gi_gst_get_type ("IntRange");
177   range = PyObject_CallFunction ((PyObject *) & PyRange_Type, "iii",
178       min, max, step);
179   int_range = PyObject_CallFunction (int_range_type, "O", range);
180
181   Py_DECREF (int_range_type);
182   Py_DECREF (range);
183
184   return int_range;
185 }
186
187 static int
188 gi_gst_int_range_to_value (GValue * value, PyObject * object)
189 {
190   PyObject *range, *min, *max, *step;
191
192   range = PyObject_GetAttrString (object, "range");
193   if (range == NULL)
194     goto fail;
195
196   min = PyObject_GetAttrString (range, "start");
197   if (min == NULL)
198     goto fail;
199
200   max = PyObject_GetAttrString (range, "stop");
201   if (max == NULL)
202     goto fail;
203
204   step = PyObject_GetAttrString (range, "step");
205   if (step == NULL)
206     goto fail;
207
208   gst_value_set_int_range_step (value, PyLong_AsLong (min),
209       PyLong_AsLong (max), PyLong_AsLong (step));
210
211   return 0;
212
213 fail:
214   PyErr_SetString (PyExc_KeyError,
215       "Object is not compatible with Gst.IntRange");
216   return -1;
217 }
218
219 static PyObject *
220 gi_gst_int64_range_from_value (const GValue * value)
221 {
222   gint64 min, max, step;
223   PyObject *int64_range_type, *int64_range, *range;
224
225   min = gst_value_get_int64_range_min (value);
226   max = gst_value_get_int64_range_max (value);
227   step = gst_value_get_int64_range_step (value);
228
229   range = PyObject_CallFunction ((PyObject *) & PyRange_Type, "LLL",
230       min, max, step);
231   int64_range_type = gi_gst_get_type ("Int64Range");
232   int64_range = PyObject_CallFunction (int64_range_type, "O", range);
233
234   Py_DECREF (int64_range_type);
235   Py_DECREF (range);
236
237   return int64_range;
238 }
239
240 static int
241 gi_gst_int64_range_to_value (GValue * value, PyObject * object)
242 {
243   PyObject *range, *min, *max, *step;
244
245   range = PyObject_GetAttrString (object, "range");
246   if (range == NULL)
247     goto fail;
248
249   min = PyObject_GetAttrString (range, "start");
250   if (min == NULL)
251     goto fail;
252
253   max = PyObject_GetAttrString (range, "stop");
254   if (max == NULL)
255     goto fail;
256
257   step = PyObject_GetAttrString (range, "step");
258   if (step == NULL)
259     goto fail;
260
261   gst_value_set_int64_range_step (value, PyLong_AsLongLong (min),
262       PyLong_AsLongLong (max), PyLong_AsLongLong (step));
263
264   return 0;
265
266 fail:
267   PyErr_SetString (PyExc_KeyError,
268       "Object is not compatible with Gst.Int64Range");
269   return -1;
270 }
271
272 static PyObject *
273 gi_gst_double_range_from_value (const GValue * value)
274 {
275   PyObject *double_range_type, *double_range;
276   gdouble min, max;
277
278   min = gst_value_get_double_range_min (value);
279   max = gst_value_get_double_range_max (value);
280
281   double_range_type = gi_gst_get_type ("DoubleRange");
282   double_range = PyObject_CallFunction (double_range_type, "dd", min, max);
283
284   Py_DECREF (double_range_type);
285
286   return double_range;
287 }
288
289 static int
290 gi_gst_double_range_to_value (GValue * value, PyObject * object)
291 {
292   PyObject *min, *max;
293
294   min = PyObject_GetAttrString (object, "start");
295   if (min == NULL)
296     goto fail;
297
298   max = PyObject_GetAttrString (object, "stop");
299   if (max == NULL)
300     goto fail;
301
302   gst_value_set_double_range (value, PyFloat_AsDouble (min),
303       PyFloat_AsDouble (max));
304
305   return 0;
306
307 fail:
308   PyErr_SetString (PyExc_KeyError,
309       "Object is not compatible with Gst.DoubleRange");
310   return -1;
311 }
312
313 static PyObject *
314 gi_gst_fraction_range_from_value (const GValue * value)
315 {
316   PyObject *min, *max, *fraction_range_type, *fraction_range;
317   const GValue *fraction;
318
319   fraction = gst_value_get_fraction_range_min (value);
320   min = gi_gst_fraction_from_value (fraction);
321
322   fraction = gst_value_get_fraction_range_max (value);
323   max = gi_gst_fraction_from_value (fraction);
324
325   fraction_range_type = gi_gst_get_type ("FractionRange");
326   fraction_range = PyObject_CallFunction (fraction_range_type, "NN", min, max);
327
328   Py_DECREF (fraction_range_type);
329
330   return fraction_range;
331 }
332
333 static int
334 gi_gst_fraction_range_to_value (GValue * value, PyObject * object)
335 {
336   PyObject *min, *max;
337   GValue vmin = G_VALUE_INIT, vmax = G_VALUE_INIT;
338
339   min = PyObject_GetAttrString (object, "start");
340   if (min == NULL)
341     goto fail;
342
343   max = PyObject_GetAttrString (object, "stop");
344   if (max == NULL)
345     goto fail;
346
347   g_value_init (&vmin, GST_TYPE_FRACTION);
348   if (gi_gst_fraction_to_value (&vmin, min) < 0)
349     goto fail;
350
351   g_value_init (&vmax, GST_TYPE_FRACTION);
352   if (gi_gst_fraction_to_value (&vmax, max) < 0) {
353     g_value_unset (&vmin);
354     goto fail;
355   }
356
357   gst_value_set_fraction_range (value, &vmin, &vmax);
358   g_value_unset (&vmin);
359   g_value_unset (&vmax);
360
361   return 0;
362
363 fail:
364   PyErr_SetString (PyExc_KeyError,
365       "Object is not compatible with Gst.FractionRange");
366   return -1;
367 }
368
369 static PyObject *
370 gi_gst_array_from_value (const GValue * value)
371 {
372   PyObject *list, *array_type, *array;
373   gint i;
374
375   list = PyList_New (gst_value_array_get_size (value));
376
377   for (i = 0; i < gst_value_array_get_size (value); i++) {
378     const GValue *v = gst_value_array_get_value (value, i);
379     PyList_SET_ITEM (list, i, pyg_value_as_pyobject (v, TRUE));
380   }
381
382   array_type = gi_gst_get_type ("ValueArray");
383   array = PyObject_CallFunction (array_type, "N", list);
384
385   Py_DECREF (array_type);
386
387   return array;
388 }
389
390 static int
391 gi_gst_array_to_value (GValue * value, PyObject * object)
392 {
393   gint len, i;
394
395   len = PySequence_Length (object);
396
397   for (i = 0; i < len; i++) {
398     GValue v = G_VALUE_INIT;
399     GType type;
400     PyObject *item;
401
402     item = PySequence_GetItem (object, i);
403
404     if (item == Py_None)
405       type = G_TYPE_POINTER;
406     else
407       type = pyg_type_from_object ((PyObject *) Py_TYPE (item));
408
409     if (type == G_TYPE_NONE) {
410       Py_DECREF (item);
411       goto fail;
412     }
413
414     g_value_init (&v, type);
415
416     if (pyg_value_from_pyobject (&v, item) < 0) {
417       Py_DECREF (item);
418       goto fail;
419     }
420
421     gst_value_array_append_and_take_value (value, &v);
422     Py_DECREF (item);
423   }
424
425   return 0;
426
427 fail:
428   PyErr_SetString (PyExc_KeyError,
429       "Object is not compatible with Gst.ValueArray");
430   return -1;
431 }
432
433 static PyObject *
434 gi_gst_bitmask_from_value (const GValue * value)
435 {
436   PyObject *val, *bitmask_type;
437
438   bitmask_type = gi_gst_get_type ("Bitmask");
439   val = PyObject_CallFunction (bitmask_type, "L",
440       gst_value_get_bitmask (value));
441   Py_DECREF (bitmask_type);
442
443   return val;
444 }
445
446 static int
447 gi_gst_bitmask_to_value (GValue * value, PyObject * object)
448 {
449   PyObject *v = PyObject_GetAttrString (object, "v");
450   if (v == NULL)
451     goto fail;
452
453   gst_value_set_bitmask (value, PyLong_AsLong (v));
454
455   return 0;
456
457 fail:
458   PyErr_SetString (PyExc_KeyError, "Object is not compatible with Gst.Bitmask");
459   return -1;
460 }
461
462 static PyObject *
463 gi_gst_list_from_value (const GValue * value)
464 {
465   PyObject *list, *value_list_type, *value_list;
466   gint i;
467
468   list = PyList_New (gst_value_list_get_size (value));
469
470   for (i = 0; i < gst_value_list_get_size (value); i++) {
471     const GValue *v = gst_value_list_get_value (value, i);
472     PyList_SET_ITEM (list, i, pyg_value_as_pyobject (v, TRUE));
473   }
474
475   value_list_type = gi_gst_get_type ("ValueList");
476   value_list = PyObject_CallFunction (value_list_type, "N", list);
477
478   Py_DECREF (value_list_type);
479
480   return value_list;
481 }
482
483 static int
484 gi_gst_list_to_value (GValue * value, PyObject * object)
485 {
486   gint len, i;
487
488   len = PySequence_Length (object);
489
490   for (i = 0; i < len; i++) {
491     GValue v = G_VALUE_INIT;
492     GType type;
493     PyObject *item;
494
495     item = PySequence_GetItem (object, i);
496
497     if (item == Py_None)
498       type = G_TYPE_POINTER;
499     else
500       type = pyg_type_from_object ((PyObject *) Py_TYPE (item));
501
502     if (type == G_TYPE_NONE) {
503       Py_DECREF (item);
504       goto fail;
505     }
506
507     g_value_init (&v, type);
508
509     if (pyg_value_from_pyobject (&v, item) < 0) {
510       Py_DECREF (item);
511       goto fail;
512     }
513
514     gst_value_list_append_and_take_value (value, &v);
515     Py_DECREF (item);
516   }
517
518   return 0;
519
520 fail:
521   PyErr_SetString (PyExc_KeyError,
522       "Object is not compatible with Gst.ValueList");
523   return -1;
524 }
525
526 static void
527 gi_gst_register_types (PyObject * d)
528 {
529   pyg_register_gtype_custom (GST_TYPE_FRACTION,
530       gi_gst_fraction_from_value, gi_gst_fraction_to_value);
531   pyg_register_gtype_custom (GST_TYPE_INT_RANGE,
532       gi_gst_int_range_from_value, gi_gst_int_range_to_value);
533   pyg_register_gtype_custom (GST_TYPE_INT64_RANGE,
534       gi_gst_int64_range_from_value, gi_gst_int64_range_to_value);
535   pyg_register_gtype_custom (GST_TYPE_DOUBLE_RANGE,
536       gi_gst_double_range_from_value, gi_gst_double_range_to_value);
537   pyg_register_gtype_custom (GST_TYPE_FRACTION_RANGE,
538       gi_gst_fraction_range_from_value, gi_gst_fraction_range_to_value);
539   pyg_register_gtype_custom (GST_TYPE_ARRAY,
540       gi_gst_array_from_value, gi_gst_array_to_value);
541   pyg_register_gtype_custom (GST_TYPE_LIST,
542       gi_gst_list_from_value, gi_gst_list_to_value);
543 #if 0
544   /* TODO */
545   pyg_register_gtype_custom (GST_TYPE_DATE_TIME,
546       gi_gst_date_time_from_value, gi_gst_date_time_to_value);
547   pyg_register_gtype_custom (GST_TYPE_FLAG_SET,
548       gi_gst_flag_set_from_value, gi_gst_flag_set_to_value);
549 #endif
550   pyg_register_gtype_custom (GST_TYPE_BITMASK,
551       gi_gst_bitmask_from_value, gi_gst_bitmask_to_value);
552 }
553
554 static int
555 add_templates (gpointer gclass, PyObject * templates)
556 {
557   if (PyTuple_Check (templates)) {
558     gint i, len;
559     PyGObject *templ;
560
561     len = PyTuple_Size (templates);
562     if (len == 0)
563       return 0;
564
565     for (i = 0; i < len; i++) {
566       templ = (PyGObject *) PyTuple_GetItem (templates, i);
567
568       if (!pygobject_check (templ, &PyGObject_Type)) {
569         PyObject *repr = PyObject_Repr ((PyObject *) templ);
570 #if PY_VERSION_HEX < 0x03000000
571         PyErr_Format (PyExc_TypeError, "expected GObject but got %s",
572             PyString_AsString (repr));
573 #else
574         PyErr_Format (PyExc_TypeError, "expected GObject but got %s",
575             _PyUnicode_AsString (repr));
576 #endif
577         Py_DECREF (repr);
578
579         return -1;
580       } else if (!GST_IS_PAD_TEMPLATE (pygobject_get (templ))) {
581         gchar *error =
582             g_strdup_printf
583             ("entries for __gsttemplates__ must be of type GstPadTemplate (%s)",
584             G_OBJECT_TYPE_NAME (pygobject_get (templ)));
585         PyErr_SetString (PyExc_TypeError, error);
586         g_free (error);
587
588         return -1;
589       }
590     }
591
592     for (i = 0; i < len; i++) {
593       templ = (PyGObject *) PyTuple_GetItem (templates, i);
594       gst_element_class_add_pad_template (gclass,
595           GST_PAD_TEMPLATE (templ->obj));
596     }
597     return 0;
598
599   } else if (!pygobject_check (templates, &PyGObject_Type) ||
600       GST_IS_PAD_TEMPLATE (pygobject_get (templates)) == FALSE) {
601     PyErr_SetString (PyExc_TypeError,
602         "entry for __gsttemplates__ must be of type GstPadTemplate");
603
604     return -1;
605   }
606
607   gst_element_class_add_pad_template (gclass,
608       GST_PAD_TEMPLATE (pygobject_get (templates)));
609
610   return 0;
611 }
612
613 static int
614 _pygst_element_set_metadata (gpointer gclass, PyObject * metadata)
615 {
616
617   const gchar *longname, *classification, *description, *author;
618
619   if (!PyTuple_Check (metadata)) {
620     PyErr_SetString (PyExc_TypeError, "__gstmetadata__ must be a tuple");
621     return -1;
622   }
623   if (PyTuple_Size (metadata) != 4) {
624     PyErr_SetString (PyExc_TypeError,
625         "__gstmetadata__ must contain 4 elements");
626     return -1;
627   }
628   if (!PyArg_ParseTuple (metadata, "ssss", &longname, &classification,
629           &description, &author)) {
630     PyErr_SetString (PyExc_TypeError, "__gstmetadata__ must contain 4 strings");
631     return -1;
632   }
633   GST_DEBUG
634       ("setting metadata on gclass %p from __gstmetadata__, longname %s",
635       gclass, longname);
636
637   gst_element_class_set_metadata (gclass, longname, classification,
638       description, author);
639   return 0;
640 }
641
642 static int
643 _pygst_element_init (gpointer gclass, PyTypeObject * pyclass)
644 {
645   PyObject *templates, *metadata;
646
647   GST_DEBUG ("_pygst_element_init for gclass %p", gclass);
648   templates = PyDict_GetItemString (pyclass->tp_dict, "__gsttemplates__");
649   if (templates) {
650     if (add_templates (gclass, templates) != 0)
651       return -1;
652   } else {
653     PyErr_Clear ();
654   }
655   metadata = PyDict_GetItemString (pyclass->tp_dict, "__gstmetadata__");
656   if (metadata) {
657     if (_pygst_element_set_metadata (gclass, metadata) != 0)
658       return -1;
659     PyDict_DelItemString (pyclass->tp_dict, "__gstmetadata__");
660   } else {
661     PyErr_Clear ();
662   }
663
664   return 0;
665 }
666
667 #include <frameobject.h>
668
669 static PyObject *
670 pygst_debug_log (PyObject * pyobject, PyObject * string, GstDebugLevel level,
671     gboolean isgstobject)
672 {
673 #ifndef GST_DISABLE_GST_DEBUG
674   gchar *str;
675   gchar *function;
676   gchar *filename;
677   int lineno;
678   PyFrameObject *frame;
679   GObject *object = NULL;
680
681   if (!PyArg_ParseTuple (string, "s:gst.debug_log", &str)) {
682     PyErr_SetString (PyExc_TypeError, "Need a string!");
683     return NULL;
684   }
685
686   frame = PyEval_GetFrame ();
687   {
688     PyObject *utf8;
689     const gchar *utf8_str;
690
691     utf8 = PyUnicode_AsUTF8String (frame->f_code->co_name);
692     utf8_str = PyBytes_AS_STRING (utf8);
693
694     function = g_strdup (utf8_str);
695     Py_DECREF (utf8);
696
697     utf8 = PyUnicode_AsUTF8String (frame->f_code->co_filename);
698     utf8_str = PyBytes_AS_STRING (utf8);
699
700     filename = g_strdup (utf8_str);
701     Py_DECREF (utf8);
702   }
703   lineno = PyCode_Addr2Line (frame->f_code, frame->f_lasti);
704   /* gst_debug_log : category, level, file, function, line, object, format, va_list */
705   if (isgstobject)
706     object = G_OBJECT (pygobject_get (pyobject));
707   gst_debug_log (python_debug, level, filename, function, lineno, object,
708       "%s", str);
709   if (function)
710     g_free (function);
711   if (filename)
712     g_free (filename);
713 #endif
714   Py_INCREF (Py_None);
715   return Py_None;
716 }
717
718 static PyObject *
719 _wrap_gst_trace (PyObject * whatever, PyObject * string)
720 {
721   return pygst_debug_log (whatever, string, GST_LEVEL_TRACE, FALSE);
722 }
723
724 static PyObject *
725 _wrap_gst_log (PyObject * whatever, PyObject * string)
726 {
727   return pygst_debug_log (whatever, string, GST_LEVEL_LOG, FALSE);
728 }
729
730 static PyObject *
731 _wrap_gst_debug (PyObject * whatever, PyObject * string)
732 {
733   return pygst_debug_log (whatever, string, GST_LEVEL_DEBUG, FALSE);
734 }
735
736 static PyObject *
737 _wrap_gst_info (PyObject * whatever, PyObject * string)
738 {
739   return pygst_debug_log (whatever, string, GST_LEVEL_INFO, FALSE);
740 }
741
742 static PyObject *
743 _wrap_gst_warning (PyObject * whatever, PyObject * string)
744 {
745   return pygst_debug_log (whatever, string, GST_LEVEL_WARNING, FALSE);
746 }
747
748 static PyObject *
749 _wrap_gst_error (PyObject * whatever, PyObject * string)
750 {
751   return pygst_debug_log (whatever, string, GST_LEVEL_ERROR, FALSE);
752 }
753
754 static PyObject *
755 _wrap_gst_fixme (PyObject * whatever, PyObject * string)
756 {
757   return pygst_debug_log (whatever, string, GST_LEVEL_FIXME, FALSE);
758 }
759
760 static PyObject *
761 _wrap_gst_memdump (PyObject * whatever, PyObject * string)
762 {
763   return pygst_debug_log (whatever, string, GST_LEVEL_MEMDUMP, FALSE);
764 }
765
766 static PyObject *
767 _remap (GstMapInfo * mapinfo, PyObject * py_mapinfo)
768 {
769   PyObject *success = NULL;
770   PyObject *py_cmapinfo = NULL;
771   PyObject *py_mview = NULL;
772   PyObject *py_memory = NULL;
773   PyObject *py_flags = NULL;
774   PyObject *py_size = NULL;
775   PyObject *py_maxsize = NULL;
776
777   /* Fill and encapsulating the mapinfo pointer */
778   py_cmapinfo = PyCapsule_New (mapinfo, "__cmapinfo", NULL);
779   if (!py_cmapinfo
780       || PyObject_SetAttrString (py_mapinfo, "__cmapinfo", py_cmapinfo))
781     goto err;
782
783   /* Fill and create memoryview with compatible flags */
784   int flags;
785   flags = (mapinfo->flags & GST_MAP_WRITE) ? PyBUF_WRITE : PyBUF_READ;
786   py_mview =
787       PyMemoryView_FromMemory ((char *) mapinfo->data, mapinfo->size, flags);
788   if (!py_mview || PyObject_SetAttrString (py_mapinfo, "data", py_mview))
789     goto err;
790
791   /* Fill and box GstMemory into a Gst.Memory */
792   py_memory = pyg_boxed_new (_gst_memory_type, mapinfo->memory, FALSE, FALSE);
793   if (!py_memory || PyObject_SetAttrString (py_mapinfo, "memory", py_memory))
794     goto err;
795
796   /* Fill out Gst.MapInfo with values corresponding to GstMapInfo */
797   py_flags = Py_BuildValue ("i", mapinfo->flags);
798   if (!py_flags || PyObject_SetAttrString (py_mapinfo, "flags", py_flags))
799     goto err;
800
801   py_size = Py_BuildValue ("i", mapinfo->size);
802   if (!py_size || PyObject_SetAttrString (py_mapinfo, "size", py_size))
803     goto err;
804
805   py_maxsize = Py_BuildValue ("i", mapinfo->maxsize);
806   if (!py_maxsize || PyObject_SetAttrString (py_mapinfo, "maxsize", py_maxsize))
807     goto err;
808
809   Py_INCREF (Py_True);
810   success = Py_True;
811   goto end;
812
813 err:
814   GST_ERROR ("Could not map the Gst.MapInfo PyObject with GstMapInfo");
815   if (py_mview)
816     PyObject_CallMethod (py_mview, "release", NULL);
817
818 end:
819   Py_XDECREF (py_cmapinfo);
820   Py_XDECREF (py_mview);
821   Py_XDECREF (py_memory);
822   Py_XDECREF (py_flags);
823   Py_XDECREF (py_size);
824   Py_XDECREF (py_maxsize);
825   return success;
826 }
827
828 static PyObject *
829 _unmap (GstMapInfo ** mapinfo, PyObject * py_mapinfo)
830 {
831   PyObject *py_cmapinfo = NULL, *py_mview = NULL, *success = NULL;
832
833   if (!PyObject_HasAttrString (py_mapinfo, "__cmapinfo"))
834     goto done;
835
836   /* Extract attributes from Gst.MapInfo */
837   py_mview = PyObject_GetAttrString (py_mapinfo, "data");
838   if (!py_mview)
839     goto err;
840
841   /* Call the memoryview.release() Python method, there is no C API */
842   if (!PyObject_CallMethod (py_mview, "release", NULL))
843     goto err;
844
845   py_cmapinfo = PyObject_GetAttrString (py_mapinfo, "__cmapinfo");
846   if (!py_cmapinfo)
847     goto err;
848
849   /* Reconstruct GstMapInfo from Gst.MapInfo contents */
850   *mapinfo = PyCapsule_GetPointer (py_cmapinfo, "__cmapinfo");
851   if (!*mapinfo)
852     goto err;
853
854   if (PyObject_DelAttrString (py_mapinfo, "__cmapinfo") == -1)
855     goto err;
856
857 done:
858   Py_INCREF (Py_True);
859   success = Py_True;
860   goto end;
861
862 err:
863   GST_ERROR ("Could not unmap the GstMapInfo from Gst.MapInfo PyObject");
864   Py_INCREF (Py_False);
865   success = Py_False;
866
867 end:
868   Py_XDECREF (py_mview);
869   Py_XDECREF (py_cmapinfo);
870   return success;
871 }
872
873 static PyObject *
874 _gst_memory_override_map (PyObject * self, PyObject * args)
875 {
876   PyTypeObject *gst_memory_type;
877   PyObject *py_memory, *py_mapinfo, *success;
878   int flags;
879   GstMemory *memory;
880   GstMapInfo *mapinfo;
881   _Bool ok;
882
883   /* Look up Gst.memory, Gst.MapInfo, and Gst.MapFlags parameters */
884   gst_memory_type = pygobject_lookup_class (_gst_memory_type);
885   if (!PyArg_ParseTuple (args, "O!Oi", gst_memory_type, &py_memory,
886           &py_mapinfo, &flags))
887     return NULL;
888
889   /* Since Python does only support r/o or r/w it has to be changed to either */
890   flags = (flags & GST_MAP_WRITE) ? GST_MAP_READWRITE : GST_MAP_READ;
891
892   /* Extract GstMemory from Gst.Memory parameter */
893   memory = GST_MEMORY_CAST (pygobject_get (py_memory));
894
895   /* Map the memory, fill out GstMapInfo */
896   mapinfo = g_new0 (GstMapInfo, 1);
897   ok = gst_memory_map (memory, mapinfo, flags);
898   if (!ok) {
899     g_free (mapinfo);
900     goto err;
901   }
902
903   success = _remap (mapinfo, py_mapinfo);
904   if (!success) {
905     gst_memory_unmap (memory, mapinfo);
906     g_free (mapinfo);
907   }
908   return success;
909
910 err:
911   Py_INCREF (Py_False);
912   return Py_False;
913 }
914
915 static PyObject *
916 _gst_memory_override_unmap (PyObject * self, PyObject * args)
917 {
918   PyTypeObject *gst_memory_type;
919   PyObject *py_memory, *py_mapinfo, *success;
920   GstMemory *memory;
921   GstMapInfo *mapinfo = NULL;
922
923   /* Look up Gst.Buffer and Gst.Mapinfo parameters */
924   gst_memory_type = pygobject_lookup_class (_gst_memory_type);
925   if (!PyArg_ParseTuple (args, "O!O", gst_memory_type, &py_memory, &py_mapinfo)) {
926     PyErr_BadArgument ();
927     return NULL;
928   }
929
930   success = _unmap (&mapinfo, py_mapinfo);
931   if (PyBool_Check (success) && mapinfo) {
932     /* Extract GstBuffer from Gst.Buffer parameter */
933     memory = GST_MEMORY_CAST (pygobject_get (py_memory));
934
935     /* Unmap the buffer, using reconstructed GstMapInfo */
936     gst_memory_unmap (memory, mapinfo);
937     g_free (mapinfo);
938   }
939
940   return success;
941 }
942
943 static PyObject *
944 _gst_buffer_override_map_range (PyObject * self, PyObject * args)
945 {
946   PyTypeObject *gst_buffer_type;
947   PyObject *py_buffer, *py_mapinfo, *success;
948   int flags, range;
949   unsigned int idx;
950   GstBuffer *buffer;
951   GstMapInfo *mapinfo;
952   _Bool ok;
953
954   /* Look up Gst.Buffer, Gst.MapInfo, idx, range, and Gst.MapFlags parameters */
955   gst_buffer_type = pygobject_lookup_class (_gst_buffer_type);
956   if (!PyArg_ParseTuple (args, "O!OIii", gst_buffer_type, &py_buffer,
957           &py_mapinfo, &idx, &range, &flags))
958     goto err;
959
960   /* Since Python does only support r/o or r/w it has to be changed to either */
961   flags = (flags & GST_MAP_WRITE) ? GST_MAP_READWRITE : GST_MAP_READ;
962
963   /* Extract GstBuffer from Gst.Buffer parameter */
964   buffer = GST_BUFFER (pygobject_get (py_buffer));
965
966   /* Map the buffer, fill out GstMapInfo */
967   mapinfo = g_new0 (GstMapInfo, 1);
968   ok = gst_buffer_map_range (buffer, idx, range, mapinfo, flags);
969   if (!ok) {
970     g_free (mapinfo);
971     goto err;
972   }
973
974   success = _remap (mapinfo, py_mapinfo);
975   if (!success) {
976     gst_buffer_unmap (buffer, mapinfo);
977     g_free (mapinfo);
978   }
979   return success;
980
981 err:
982   Py_INCREF (Py_False);
983   return Py_False;
984 }
985
986 static PyObject *
987 _gst_buffer_override_map (PyObject * self, PyObject * args)
988 {
989   PyTypeObject *gst_buffer_type;
990   PyObject *py_buffer, *py_mapinfo, *success;
991   int flags;
992   GstBuffer *buffer;
993   GstMapInfo *mapinfo;
994   _Bool ok;
995
996   /* Look up Gst.Buffer, Gst.MapInfo, and Gst.MapFlags parameters */
997   gst_buffer_type = pygobject_lookup_class (_gst_buffer_type);
998   if (!PyArg_ParseTuple (args, "O!Oi", gst_buffer_type, &py_buffer, &py_mapinfo,
999           &flags)) {
1000     PyErr_BadArgument ();
1001     return NULL;
1002   }
1003
1004   /* Since Python does only support r/o or r/w it has to be changed to either */
1005   flags = (flags & GST_MAP_WRITE) ? GST_MAP_READWRITE : GST_MAP_READ;
1006
1007   /* Extract GstBuffer from Gst.Buffer parameter */
1008   buffer = GST_BUFFER (pygobject_get (py_buffer));
1009
1010   /* Map the buffer, fill out GstMapInfo */
1011   mapinfo = g_new0 (GstMapInfo, 1);
1012   ok = gst_buffer_map (buffer, mapinfo, flags);
1013   if (!ok) {
1014     g_free (mapinfo);
1015     goto err;
1016   }
1017
1018   success = _remap (mapinfo, py_mapinfo);
1019   if (!success) {
1020     gst_buffer_unmap (buffer, mapinfo);
1021     g_free (mapinfo);
1022   }
1023   return success;
1024
1025 err:
1026   Py_INCREF (Py_False);
1027   return Py_False;
1028 }
1029
1030 static PyObject *
1031 _gst_buffer_override_unmap (PyObject * self, PyObject * args)
1032 {
1033   PyTypeObject *gst_buf_type;
1034   PyObject *py_buffer, *py_mapinfo, *success;
1035   GstBuffer *buffer;
1036   GstMapInfo *mapinfo = NULL;
1037
1038   /* Look up Gst.Buffer and Gst.Mapinfo parameters */
1039   gst_buf_type = pygobject_lookup_class (_gst_buffer_type);
1040   if (!PyArg_ParseTuple (args, "O!O", gst_buf_type, &py_buffer, &py_mapinfo)) {
1041     PyErr_BadArgument ();
1042     return NULL;
1043   }
1044
1045   success = _unmap (&mapinfo, py_mapinfo);
1046   if (PyBool_Check (success) && mapinfo) {
1047     /* Extract GstBuffer from Gst.Buffer parameter */
1048     buffer = GST_BUFFER (pygobject_get (py_buffer));
1049
1050     /* Unmap the buffer, using reconstructed GstMapInfo */
1051     gst_buffer_unmap (buffer, mapinfo);
1052     g_free (mapinfo);
1053   }
1054
1055   return success;
1056 }
1057
1058 static PyMethodDef _gi_gst_functions[] = {
1059   {"trace", (PyCFunction) _wrap_gst_trace, METH_VARARGS,
1060       NULL},
1061   {"log", (PyCFunction) _wrap_gst_log, METH_VARARGS,
1062       NULL},
1063   {"debug", (PyCFunction) _wrap_gst_debug, METH_VARARGS,
1064       NULL},
1065   {"info", (PyCFunction) _wrap_gst_info, METH_VARARGS,
1066       NULL},
1067   {"warning", (PyCFunction) _wrap_gst_warning, METH_VARARGS,
1068       NULL},
1069   {"error", (PyCFunction) _wrap_gst_error, METH_VARARGS,
1070       NULL},
1071   {"fixme", (PyCFunction) _wrap_gst_fixme, METH_VARARGS,
1072       NULL},
1073   {"memdump", (PyCFunction) _wrap_gst_memdump, METH_VARARGS,
1074       NULL},
1075   {"buffer_override_map_range", (PyCFunction) _gst_buffer_override_map_range,
1076         METH_VARARGS,
1077       NULL},
1078   {"buffer_override_map", (PyCFunction) _gst_buffer_override_map, METH_VARARGS,
1079       NULL},
1080   {"buffer_override_unmap", (PyCFunction) _gst_buffer_override_unmap,
1081         METH_VARARGS,
1082       NULL},
1083   {"memory_override_map", (PyCFunction) _gst_memory_override_map, METH_VARARGS,
1084       NULL},
1085   {"memory_override_unmap", (PyCFunction) _gst_memory_override_unmap,
1086         METH_VARARGS,
1087       NULL},
1088   {NULL, NULL, 0, NULL}
1089 };
1090
1091 PYGLIB_MODULE_START (_gi_gst, "_gi_gst")
1092 {
1093   PyObject *d;
1094
1095   /* gst should have been initialized already */
1096
1097   /* Initialize debugging category */
1098   GST_DEBUG_CATEGORY_INIT (pygst_debug, "pygst", 0,
1099       "GStreamer python bindings");
1100   GST_DEBUG_CATEGORY_INIT (python_debug, "python", GST_DEBUG_FG_GREEN,
1101       "python code using gst-python");
1102
1103   pygobject_init (3, 0, 0);
1104
1105   d = PyModule_GetDict (module);
1106   gi_gst_register_types (d);
1107   pyg_register_class_init (GST_TYPE_ELEMENT, _pygst_element_init);
1108 }
1109
1110 PYGLIB_MODULE_END;