diff options
author | Edward Hervey <bilboed@bilboed.com> | 2005-07-12 09:45:58 +0000 |
---|---|---|
committer | Edward Hervey <bilboed@bilboed.com> | 2005-07-12 09:45:58 +0000 |
commit | ae75cbd54bd7a6d7b4fef9a41d2dc7fbf29eb3dc (patch) | |
tree | 12663bd08c94a071fc9c0545da8fd39c224658d9 | |
parent | bc47432fc8a9b9b4879120ec34a5340ed8198a92 (diff) |
gst/: Added GError wrapping,
Original commit message from CVS:
* gst/gst-types.defs:
* gst/gst.defs:
Added GError wrapping,
Removed data field from Buffer,
Added virtual methods to object
Updated to latest API
* gst/gst.override:
wrapped gst_plugin_get_feature_list(), gst_uri_handler_get_protocols(),
gst_registry_pool_list()
* gst/gstbuffer.override:
gst.Buffer() works
get/setters fixed
wrapped gst_buffer_stamp()
* gst/gstbus.override:
wrapped gst_bus_set_sync_handler() and gst_bus_add_watch()
* gst/gstelement.override:
wrapped gst_element_send_event(), gst_element_factory_get_pad_templates()
gst_element_query_convert(), gst_element_get_query_types()
* gst/gstevent.override:
wrapped gst_event_discont_get_value()
* gst/gstmessage.override:
wrapped gst_message_parse_state_changed(), gst_message_parse_error(),
gst_message_parse_warning(), gst_message_parse_tag()
* gst/gstmodule.c:
Added registration of new fundamental type with pygtk
* gst/gstpad.override:
wrapped gst_pad_query(), gst_pad_[add|remove]_[data|event|buffer]_probe(),
gst_pad_query_position(), gst_pad_query_convert()
* gst/gstquery.override:
wrapped gst_query_parse_position(), gst_query_parse_convert(),
gst_query_parse_seeking_query(), gst_query_parse_seeking_reponse()
* gst/pygstminiobject.c:
fixes
* gst/Makefile.am:
added gstbus.override, gstmessage.override, gstquery.override
* testsuite/test_buffer.py:
* testsuite/test_element.py:
* testsuite/test_event.py:
* testsuite/test_pipeline.py:
Updating testsuites
-rw-r--r-- | ChangeLog | 55 | ||||
m--------- | common | 0 | ||||
-rw-r--r-- | gst/Makefile.am | 5 | ||||
-rw-r--r-- | gst/gst-types.defs | 16 | ||||
-rw-r--r-- | gst/gst.defs | 411 | ||||
-rw-r--r-- | gst/gst.override | 95 | ||||
-rw-r--r-- | gst/gstbuffer.override | 134 | ||||
-rw-r--r-- | gst/gstbus.override | 175 | ||||
-rw-r--r-- | gst/gstelement.override | 132 | ||||
-rw-r--r-- | gst/gstevent.override | 35 | ||||
-rw-r--r-- | gst/gstmessage.override | 109 | ||||
-rw-r--r-- | gst/gstmodule.c | 36 | ||||
-rw-r--r-- | gst/gstpad.override | 317 | ||||
-rw-r--r-- | gst/gstquery.override | 114 | ||||
-rw-r--r-- | gst/pygstminiobject.c | 14 | ||||
-rw-r--r-- | testsuite/test_buffer.py | 77 | ||||
-rw-r--r-- | testsuite/test_element.py | 63 | ||||
-rw-r--r-- | testsuite/test_event.py | 14 | ||||
-rw-r--r-- | testsuite/test_pipeline.py | 10 |
19 files changed, 1478 insertions, 334 deletions
@@ -1,3 +1,58 @@ +2005-07-12 Edward Hervey <edward@fluendo.com> + + * gst/gst-types.defs: + * gst/gst.defs: + Added GError wrapping, + Removed data field from Buffer, + Added virtual methods to object + Updated to latest API + + * gst/gst.override: + wrapped gst_plugin_get_feature_list(), gst_uri_handler_get_protocols(), + gst_registry_pool_list() + + * gst/gstbuffer.override: + gst.Buffer() works + get/setters fixed + wrapped gst_buffer_stamp() + + * gst/gstbus.override: + wrapped gst_bus_set_sync_handler() and gst_bus_add_watch() + + * gst/gstelement.override: + wrapped gst_element_send_event(), gst_element_factory_get_pad_templates() + gst_element_query_convert(), gst_element_get_query_types() + + * gst/gstevent.override: + wrapped gst_event_discont_get_value() + + * gst/gstmessage.override: + wrapped gst_message_parse_state_changed(), gst_message_parse_error(), + gst_message_parse_warning(), gst_message_parse_tag() + + * gst/gstmodule.c: + Added registration of new fundamental type with pygtk + + * gst/gstpad.override: + wrapped gst_pad_query(), gst_pad_[add|remove]_[data|event|buffer]_probe(), + gst_pad_query_position(), gst_pad_query_convert() + + * gst/gstquery.override: + wrapped gst_query_parse_position(), gst_query_parse_convert(), + gst_query_parse_seeking_query(), gst_query_parse_seeking_reponse() + + * gst/pygstminiobject.c: + fixes + + * gst/Makefile.am: + added gstbus.override, gstmessage.override, gstquery.override + + * testsuite/test_buffer.py: + * testsuite/test_element.py: + * testsuite/test_event.py: + * testsuite/test_pipeline.py: + Updating testsuites + 2005-07-05 Edward Hervey <edward@fluendo.com> * gst/gstmodule.c: diff --git a/common b/common -Subproject 4ca96aedcf2be0b3dcf31fce732aed1da21b885 +Subproject ac7272b7af934c2294a44ac1c0f3fac3f8d17ec diff --git a/gst/Makefile.am b/gst/Makefile.am index 71c6253..484370b 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -38,9 +38,12 @@ GST_OVERRIDES = \ gst.override \ gstbin.override \ gstbuffer.override \ + gstbus.override \ + gstevent.override \ gstcaps.override \ gstelement.override \ - gstevent.override \ + gstmessage.override \ + gstquery.override \ gstpad.override \ gststructure.override diff --git a/gst/gst-types.defs b/gst/gst-types.defs index be78936..3842144 100644 --- a/gst/gst-types.defs +++ b/gst/gst-types.defs @@ -152,7 +152,6 @@ (c-name "GstBuffer") (gtype-id "GST_TYPE_BUFFER") (fields - '("guint8*" "data") '("guint" "size") '("GstClockTime" "timestamp") '("GstClockTime" "duration") @@ -230,6 +229,18 @@ (gtype-id "GST_TYPE_TAG_LIST") ) +(define-boxed GError + (in-module "Gst") + (c-name "GError") + (gtype-id "GST_TYPE_G_ERROR") + (copy-func "g_error_copy") + (release-func "g_error_free") + (fields + '("GQuark" "domain") + '("gint" "code") + '("gchar*" "message")) +) + ;; Enumerations and flags ... (define-enum BinFlags @@ -779,12 +790,9 @@ (gtype-id "GST_TYPE_QUERY_TYPE") (values '("none" "GST_QUERY_NONE") - '("total" "GST_QUERY_TOTAL") '("position" "GST_QUERY_POSITION") '("latency" "GST_QUERY_LATENCY") '("jitter" "GST_QUERY_JITTER") - '("start" "GST_QUERY_START") - '("segment-end" "GST_QUERY_SEGMENT_END") '("rate" "GST_QUERY_RATE") '("seeking" "GST_QUERY_SEEKING") '("convert" "GST_QUERY_CONVERT") diff --git a/gst/gst.defs b/gst/gst.defs index 0a0a313..7e24f0c 100644 --- a/gst/gst.defs +++ b/gst/gst.defs @@ -3,133 +3,6 @@ (include "gst-extrafuncs.defs") (include "gst-types.defs") - -;; From ../gstreamer/gst/cothreads.h - -(define-function cothread_context_init - (c-name "cothread_context_init") - (return-type "cothread_context*") -) - -(define-function cothread_context_free - (c-name "cothread_context_free") - (return-type "none") - (parameters - '("cothread_context*" "ctx") - ) -) - -(define-function cothread_context_set_data - (c-name "cothread_context_set_data") - (return-type "none") - (parameters - '("cothread_state*" "cothread") - '("gchar*" "key") - '("gpointer" "data") - ) -) - -(define-function cothread_context_get_data - (c-name "cothread_context_get_data") - (return-type "gpointer") - (parameters - '("cothread_state*" "cothread") - '("gchar*" "key") - ) -) - -(define-function cothread_create - (c-name "cothread_create") - (return-type "cothread_state*") - (parameters - '("cothread_context*" "ctx") - ) -) - -(define-function cothread_free - (c-name "cothread_free") - (return-type "none") - (parameters - '("cothread_state*" "cothread") - ) -) - -(define-function cothread_setfunc - (c-name "cothread_setfunc") - (return-type "none") - (parameters - '("cothread_state*" "cothread") - '("cothread_func" "func") - '("int" "argc") - '("char**" "argv") - ) -) - -(define-function cothread_stop - (c-name "cothread_stop") - (return-type "none") - (parameters - '("cothread_state*" "cothread") - ) -) - -(define-function cothread_switch - (c-name "cothread_switch") - (return-type "none") - (parameters - '("cothread_state*" "cothread") - ) -) - -(define-function cothread_set_private - (c-name "cothread_set_private") - (return-type "none") - (parameters - '("cothread_state*" "cothread") - '("gpointer" "data") - ) -) - -(define-function cothread_get_private - (c-name "cothread_get_private") - (return-type "gpointer") - (parameters - '("cothread_state*" "cothread") - ) -) - -(define-function cothread_main - (c-name "cothread_main") - (return-type "cothread_state*") - (parameters - '("cothread_context*" "ctx") - ) -) - -(define-function cothread_current_main - (c-name "cothread_current_main") - (return-type "cothread_state*") -) - -(define-function cothread_current - (c-name "cothread_current") - (return-type "cothread_state*") -) - - - -;; From ../gstreamer/gst/gettext.h - - - -;; From ../gstreamer/gst/gst-i18n-app.h - - - -;; From ../gstreamer/gst/gst-i18n-lib.h - - - ;; From ../gstreamer/gst/gst.h (define-function init @@ -177,14 +50,6 @@ -;; From ../gstreamer/gst/gst_private.h - - - -;; From ../gstreamer/gst/gstarch.h - - - ;; From ../gstreamer/gst/gstbin.h (define-function gst_bin_get_type @@ -273,7 +138,21 @@ ) ) +(define-virtual add_element + (of-object "GstBin") + (return-type "gboolean") + (parameters + '("GstElement*" "element") + ) +) +(define-virtual remove_element + (of-object "GstBin") + (return-type "gboolean") + (parameters + '("GstElement*" "element") + ) +) ;; From ../gstreamer/gst/gstbuffer.h @@ -450,6 +329,7 @@ ) (define-function caps_new_empty + (is-constructor-of "GstCaps") (c-name "gst_caps_new_empty") (return-type "GstCaps*") ) @@ -822,14 +702,48 @@ (return-type "none") ) +(define-virtual change_resolution + (of-object "GstClock") + (return-type "guint64") + (parameters + '("guint64" "old_resolution") + '("guint64" "new_resolution") + ) +) +(define-virtual get_resolution + (of-object "GstClock") + (return-type "guint64") +) -;; From ../gstreamer/gst/gstcompat.h - +(define-virtual get_internal_time + (of-object "GstClock") + (return-type "GstClockTime") +) +(define-virtual wait + (of-object "GstClock") + (return-type "GstClockReturn") + (parameters + '("GstClockEntry*" "entry") + ) +) -;; From ../gstreamer/gst/gstconfig.h +(define-virtual wait_async + (of-object "GstClock") + (return-type "GstClockReturn") + (parameters + '("GstClockEntry*" "entry") + ) +) +(define-virtual unschedule + (of-object "GstClock") + (return-type "none") + (parameters + '("GstClockEntry" "entry") + ) +) ;; From ../gstreamer/gst/gstelement.h @@ -1167,7 +1081,108 @@ (return-type "GstElementFactory*") ) +(define-virtual send_event + (of-object "GstElement") + (return-type "gboolean") + (parameters + '("GstEvent*" "event") + ) +) +(define-virtual get_query_types + (of-object "GstElement") + (return-type "const-GstQueryType*") +) + +(define-virtual query + (of-object "GstElement") + (return-type "gboolean") + (parameters + '("GstQuery*" "query") + ) +) + +(define-virtual get_state + (of-object "GstElement") + (return-type "GstElementStateReturn") + (parameters + '("GstElementState*" "state") + '("GstElementState*" "pending") + '("GTimeVal*" "timeout") + ) +) + +(define-virtual change_state + (of-object "GstElement") + (return-type "GstElementStateReturn") +) + +(define-virtual request_new_pad + (of-object "GstElement") + (return-type "GstPad*") + (parameters + '("GstPadTemplate*" "templ") + '("const-gchar*" "name") + ) +) + +(define-virtual release_pad + (of-object "GstElement") + (return-type "none") + (parameters + '("GstPad*" "pad") + ) +) + +(define-virtual get_clock + (of-object "GstElement") + (return-type "GstClock*") +) + +(define-virtual set_clock + (of-object "GstElement") + (return-type "none") + (parameters + '("GstClock*" "clock") + ) +) + +(define-virtual get_index + (of-object "GstElement") + (return-type "GstIndex*") +) + +(define-virtual set_index + (of-object "GstElement") + (return-type "none") + (parameters + '("GstIndex*" "index") + ) +) + +(define-virtual set_manager + (of-object "GstElement") + (return-type "none") + (parameters + '("GstPipeline*" "pipeline") + ) +) + +(define-virtual set_bus + (of-object "GstElement") + (return-type "none") + (parameters + '("GstBus*" "bus") + ) +) + +(define-virtual set_scheduler + (of-object "GstElement") + (return-type "none") + (parameters + '("GstScheduler*" "scheduler") + ) +) ;; From ../gstreamer/gst/gstelementfactory.h @@ -1267,8 +1282,6 @@ ) ) - - ;; From ../gstreamer/gst/gstenumtypes.h (define-function gst_object_flags_get_type @@ -1906,6 +1919,29 @@ ) ) +(define-virtual add_entry + (of-object "GstIndex") + (return-type "none") + (parameters + '("GstIndexEntry*" "entry") + ) +) + +(define-virtual get_assoc_entry + (of-object "GstIndex") + (return-type "GstIndexEntry*") + (parameters + '("gint" "id") + '("GstIndexLookupMethod" "method") + '("GstAssocFlags" "flags") + '("GstFormat" "format") + '("gint64" "value") + '("GCompareDataFunc" "func") + '("gpointer" "user_data") + ) +) + + (define-function gst_index_entry_get_type (c-name "gst_index_entry_get_type") (return-type "GType") @@ -2229,8 +2265,6 @@ ) ) - - ;; From ../gstreamer/gst/gstiterator.h (define-function gst_iterator_new @@ -2332,16 +2366,6 @@ ) ) - - -;; From ../gstreamer/gst/gstmacros.h - - - -;; From ../gstreamer/gst/gstmarshal.h - - - ;; From ../gstreamer/gst/gstmemchunk.h (define-function gst_mem_chunk_new @@ -2588,8 +2612,6 @@ ) ) - - ;; From ../gstreamer/gst/gstobject.h (define-function gst_object_get_type @@ -2746,7 +2768,21 @@ ) ) +(define-virtual save_thyself + (of-object "GstObject") + (return-type "xmlNodePtr") + (parameters + '("xmlNodePtr" "parent") + ) +) +(define-virtual restore_thyself + (of-object "GstObject") + (return-type "none") + (parameters + '("xmlNodePtr" "self") + ) +) ;; From ../gstreamer/gst/gstpad.h @@ -3681,6 +3717,11 @@ (return-type "const-gchar*") ) +(define-virtual unload_thyself + (of-object "GstPluginFeature") + (return-type "none") +) + ;; From ../gstreamer/gst/gstquery.h (define-function gst_query_get_type @@ -4204,7 +4245,24 @@ (return-type "const-gchar*") ) +(define-virtual setup + (of-object "GstScheduler") + (return-type "none") +) +(define-virtual reset + (of-object "GstScheduler") + (return-type "none") +) + +(define-virtual create_task + (of-object "GstScheduler") + (return-type "GstTask*") + (parameters + '("GstTaskFunction" "func") + '("gpointer" "data") + ) +) ;; From ../gstreamer/gst/gststructure.h @@ -5197,7 +5255,20 @@ (return-type "gboolean") ) +(define-virtual start + (of-object "GstTask") + (return-type "gboolean") +) + +(define-virtual stop + (of-object "GstTask") + (return-type "gboolean") +) +(define-virtual pause + (of-object "GstTask") + (return-type "gboolean") +) ;; From ../gstreamer/gst/gsttrace.h @@ -5301,10 +5372,6 @@ -;; From ../gstreamer/gst/gsttrashstack.h - - - ;; From ../gstreamer/gst/gsttypefind.h (define-method peek @@ -5379,11 +5446,6 @@ ) - -;; From ../gstreamer/gst/gsttypes.h - - - ;; From ../gstreamer/gst/gsturi.h (define-function uri_protocol_is_valid @@ -5595,6 +5657,14 @@ (return-type "const-gchar*") ) +(define-function element_state_get_name + (c-name "gst_element_state_get_name") + (parameters + '("GstElementState" "state") + ) + (return-type "const-gchar*") +) + (define-method link (of-object "GstElement") (c-name "gst_element_link") @@ -6149,21 +6219,6 @@ ) - -;; From ../gstreamer/gst/gstversion.h - -(define-function version - (c-name "gst_version") - (return-type "none") - (parameters - '("guint*" "major") - '("guint*" "minor") - '("guint*" "micro") - ) -) - - - ;; From ../gstreamer/gst/gstxml.h (define-function gst_xml_get_type diff --git a/gst/gst.override b/gst/gst.override index f0f030c..2c920cc 100644 --- a/gst/gst.override +++ b/gst/gst.override @@ -217,9 +217,12 @@ _pygst_element_init (gpointer gclass, PyTypeObject *pyclass) include gstbin.override gstbuffer.override + gstevent.override gstcaps.override + gstbus.override gstelement.override - gstevent.override + gstmessage.override + gstquery.override gstpad.override gststructure.override %% @@ -565,6 +568,35 @@ _wrap_gst_plugin_feature_tp_str(PyObject *self) return ret; } %% +override gst_plugin_get_feature_list noargs +static PyObject * +_wrap_gst_plugin_get_feature_list(PyGObject *self) +{ + PyObject *ret; + PyObject *item; + GList *l, *features; + + features = gst_plugin_get_feature_list (GST_PLUGIN (self->obj)); + + ret = PyList_New(0); + + for (l = features; l; l = g_list_next(l)) { + item = pygobject_new((GObject *) GST_PLUGIN_FEATURE(l->data)); + + if (!item) { + Py_DECREF(ret); + return NULL; + } + PyList_Append(ret, item); + + Py_DECREF(item); + } + + g_list_free(features); + + return ret; +} +%% override gst_type_find_factory_get_caps noargs static PyObject * _wrap_gst_type_find_factory_get_caps(PyGObject *self) @@ -914,4 +946,65 @@ _wrap_gst_element_register(PyObject *self, PyObject *args, PyObject *kwargs) ret = gst_element_register(_pygst_get_plugin(), elementname, rank, type); return PyBool_FromLong(ret); } +%% +override-attr GError.domain +static PyObject * +_wrap_gst_g_error__get_domain(PyGObject *self, void *closure) +{ + return PyString_FromString(g_quark_to_string(((GError*)self->obj)->domain)); +} +%% +override-slot GError.tp_str +static PyObject * +_wrap_gst_g_error_tp_str(PyGObject *self) +{ + GError *error = (GError*)self->obj; + return PyString_FromString(gst_error_get_message (error->domain, + error->code)); +} +%% +override gst_uri_handler_get_protocols noargs +static PyObject * +_wrap_gst_uri_handler_get_protocols (PyGObject *self) +{ + gchar **tab; + int i, len; + PyObject *ret; + + tab = gst_uri_handler_get_protocols (GST_URI_HANDLER (self->obj)); + if (!tab) { + Py_INCREF (Py_None); + return Py_None; + } + ret = PyList_New(0); + + len = g_strv_length (tab); + for (i = 0; i < len; i++) { + PyList_Append(ret, PyString_FromString(tab[i])); + } + + return ret; +} +%% +override gst_registry_pool_list noargs +static PyObject * +_wrap_gst_registry_pool_list (PyObject *what) +{ + PyObject *ret, *item; + GList *res, *tmp; + ret = PyList_New(0); + res = gst_registry_pool_list(); + for (tmp = res; tmp; tmp = g_list_next(tmp)) { + item = pygobject_new((GObject*) GST_REGISTRY(tmp->data)); + + if (!item) { + Py_DECREF(ret); + return NULL; + } + PyList_Append(ret, item); + + Py_DECREF(item); + } + return ret; +} diff --git a/gst/gstbuffer.override b/gst/gstbuffer.override index a5a94cd..f7100d0 100644 --- a/gst/gstbuffer.override +++ b/gst/gstbuffer.override @@ -37,7 +37,7 @@ static int gst_buffer_getcharbuf (PyGstMiniObject *self, %% override gst_buffer_new kwargs static int -_wrap_gst_buffer_new(PyGBoxed *self, PyObject *args, PyObject *kwargs) +_wrap_gst_buffer_new(PyGstMiniObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "data", "buffer_size", NULL }; char *data = NULL; @@ -58,21 +58,20 @@ _wrap_gst_buffer_new(PyGBoxed *self, PyObject *args, PyObject *kwargs) PyErr_SetString(PyExc_TypeError, "buffer size must be >= data size"); return -1; } - self->gtype = GST_TYPE_BUFFER; - self->free_on_dealloc = TRUE; - self->boxed = gst_buffer_new_and_alloc(buf_size); + self->obj = GST_MINI_OBJECT(gst_buffer_new_and_alloc(buf_size)); - if (!self->boxed) { + if (!self->obj) { PyErr_SetString(PyExc_RuntimeError, "could not create GstBuffer object"); return -1; } + pygstminiobject_register_wrapper((PyObject *) self); if (data == NULL) return 0; - memcpy (GST_BUFFER_DATA (self->boxed), data, size); - GST_BUFFER_SIZE (self->boxed) = size; + memcpy (GST_BUFFER_DATA (self->obj), data, size); + GST_BUFFER_SIZE (self->obj) = size; return 0; } @@ -353,3 +352,124 @@ _wrap_gst_buffer_flag_unset(PyObject *self, PyObject *args) Py_INCREF(Py_None); return Py_None; } +%% +override-attr GstBuffer.timestamp +static PyObject * +_wrap_gst_buffer__get_timestamp(PyObject *self, void *closure) +{ + guint64 ret; + + ret = GST_BUFFER(pygstminiobject_get(self))->timestamp; + return PyLong_FromUnsignedLongLong(ret); +} +static int +_wrap_gst_buffer__set_timestamp(PyGstMiniObject *self, PyObject *value, void *closure) +{ + guint64 val; + + if (PyInt_CheckExact(value)) + val = PyInt_AsUnsignedLongLongMask(value); + else + val = PyLong_AsUnsignedLongLong(value); + if (PyErr_Occurred()) + return -1; + + GST_BUFFER(self->obj)->timestamp = val; + return 0; +} +%% +override-attr GstBuffer.duration +static PyObject * +_wrap_gst_buffer__get_duration(PyObject *self, void *closure) +{ + guint64 ret; + + ret = GST_BUFFER(pygstminiobject_get(self))->duration; + return PyLong_FromUnsignedLongLong(ret); +} +static int +_wrap_gst_buffer__set_duration(PyGstMiniObject *self, PyObject *value, void *closure) +{ + guint64 val; + + if (PyInt_CheckExact(value)) + val = PyInt_AsUnsignedLongLongMask(value); + else + val = PyLong_AsUnsignedLongLong(value); + if (PyErr_Occurred()) + return -1; + + GST_BUFFER(self->obj)->duration = val; + return 0; +} +%% +override-attr GstBuffer.offset +static PyObject * +_wrap_gst_buffer__get_offset(PyObject *self, void *closure) +{ + guint64 ret; + + ret = GST_BUFFER(pygstminiobject_get(self))->offset; + return PyLong_FromUnsignedLongLong(ret); +} +static int +_wrap_gst_buffer__set_offset(PyGstMiniObject *self, PyObject *value, void *closure) +{ + guint64 val; + + if (PyInt_CheckExact(value)) + val = PyInt_AsUnsignedLongLongMask(value); + else + val = PyLong_AsUnsignedLongLong(value); + if (PyErr_Occurred()) + return -1; + + GST_BUFFER(self->obj)->offset = val; + return 0; +} +%% +override-attr GstBuffer.offset_end +static PyObject * +_wrap_gst_buffer__get_offset_end(PyObject *self, void *closure) +{ + guint64 ret; + + ret = GST_BUFFER(pygstminiobject_get(self))->offset_end; + return PyLong_FromUnsignedLongLong(ret); +} + +static int +_wrap_gst_buffer__set_offset_end(PyGstMiniObject *self, PyObject *value, void *closure) +{ + guint64 val; + + if (PyInt_CheckExact(value)) + val = PyInt_AsUnsignedLongLongMask(value); + else + val = PyLong_AsUnsignedLongLong(value); + if (PyErr_Occurred()) + return -1; + + GST_BUFFER(self->obj)->offset_end = val; + return 0; +} +%% +override gst_buffer_stamp kwargs +static PyObject * +_wrap_gst_buffer_stamp (PyGstMiniObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "src", NULL }; + PyGstMiniObject *srcobj; + GstBuffer *dest, *src; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, + "0:GstBuffer.stamp", + kwlist, &srcobj)) + return NULL; + dest = GST_BUFFER(pygstminiobject_get(self)); + src = GST_BUFFER(pygstminiobject_get(srcobj)); + gst_buffer_stamp (dest, (const GstBuffer*) src); + + Py_INCREF(Py_None); + return Py_None; +} diff --git a/gst/gstbus.override b/gst/gstbus.override new file mode 100644 index 0000000..f8aeb87 --- /dev/null +++ b/gst/gstbus.override @@ -0,0 +1,175 @@ +/* -*- Mode: C; ; c-file-style: "python" -*- */ +/* gst-python + * Copyright (C) 2005 Edward Hervey + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Edward Hervey <edward@fluendo.com> + */ +%% +headers +static GstBusSyncReply +bus_sync_handler (GstBus *bus, GstMessage *message, gpointer user_data) +{ + PyGILState_STATE state; + GstBusSyncReply res; + PyObject *py_userdata; + PyObject *py_msg; + PyObject *callback, *args; + PyObject *ret; + gint i,len; + + g_return_val_if_fail (user_data != NULL, GST_BUS_PASS); + + state = pyg_gil_state_ensure(); + + py_userdata = (PyObject *) user_data; + py_msg = pygstminiobject_new(GST_MINI_OBJECT(message)); + callback = PyTuple_GetItem(py_userdata, 0); + args = Py_BuildValue("(NN)", + pygobject_new(G_OBJECT(bus)), + py_msg); + + len = PyTuple_Size(py_userdata); + for (i = 1; i < len; ++i) { + PyObject *tuple = args; + args = PySequence_Concat(tuple, PyTuple_GetItem(py_userdata, i)); + Py_DECREF(tuple); + } + ret = PyObject_CallObject(callback, args); + + if (!ret) { + PyErr_Print(); + res = GST_BUS_PASS; + } else { + if (pyg_enum_get_value(GST_TYPE_BUS_SYNC_REPLY, ret, (gint *) &res)) + res = GST_BUS_PASS; + Py_DECREF (ret); + } + + Py_DECREF(args); + + pyg_gil_state_release(state); + + return res; +} + +static gboolean +bus_handler (GstBus *bus, GstMessage *message, gpointer user_data) +{ + PyGILState_STATE state; + gboolean res; + PyObject *py_userdata; + PyObject *py_msg; + PyObject *callback, *args; + PyObject *ret; + gint i,len; + + g_return_val_if_fail (user_data != NULL, TRUE); + + state = pyg_gil_state_ensure(); + + py_userdata = (PyObject *) user_data; + py_msg = pygstminiobject_new(GST_MINI_OBJECT(message)); + callback = PyTuple_GetItem(py_userdata, 0); + args = Py_BuildValue("(NN)", + pygobject_new(G_OBJECT(bus)), + py_msg); + + len = PyTuple_Size(py_userdata); + for (i = 1; i < len; ++i) { + PyObject *tuple = args; + args = PySequence_Concat(tuple, PyTuple_GetItem(py_userdata, i)); + Py_DECREF(tuple); + } + ret = PyObject_CallObject(callback, args); + + if (!ret) { + PyErr_Print(); + res = TRUE; + } else { + res = PyObject_IsTrue(ret); + Py_DECREF(ret); + } + Py_DECREF(args); + + pyg_gil_state_release(state); + + return res; +} + +%% +override gst_bus_set_sync_handler args +static PyObject * +_wrap_gst_bus_set_sync_handler (PyGObject *self, PyObject *args) +{ + PyObject *callback, *cbargs = NULL, *data; + gint len; + + len = PyTuple_Size(args); + + if (len < 1) { + PyErr_SetString(PyExc_TypeError, "Bus requires at least 1 arg"); + return NULL; + } + callback = PySequence_GetItem(args, 0); + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "callback is not callable"); + return NULL; + } + cbargs = PySequence_GetSlice(args, 1, len); + if (cbargs == NULL) + return NULL; + data = Py_BuildValue("(ON)", callback, cbargs); + if (data == NULL) + return NULL; + gst_bus_set_sync_handler (GST_BUS (self->obj), + (GstBusSyncHandler) bus_sync_handler, + data); + + return (PyObject*) self; + +} +%% +override gst_bus_add_watch args +static PyObject * +_wrap_gst_bus_add_watch (PyGObject *self, PyObject *args) +{ + PyObject *callback, *cbargs = NULL, *data; + guint sigid; + guint len; + + len = PyTuple_Size(args); + + if (len < 1) { + PyErr_SetString(PyExc_TypeError, "Bus requires at least 1 arg"); + return NULL; + } + callback = PySequence_GetItem(args, 0); + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "callback is not callable"); + return NULL; + } + cbargs = PySequence_GetSlice(args, 1, len); + if (cbargs == NULL) + return NULL; + data = Py_BuildValue("(ON)", callback, cbargs); + if (data == NULL) + return NULL; + sigid = gst_bus_add_watch (GST_BUS (self->obj), (GstBusHandler) bus_handler, data); + + return PyInt_FromLong(sigid); +} diff --git a/gst/gstelement.override b/gst/gstelement.override index 5c867f9..74ebf4f 100644 --- a/gst/gstelement.override +++ b/gst/gstelement.override @@ -368,48 +368,32 @@ _wrap_gst_element_unlink_many(PyObject *self, PyObject *args) Py_INCREF(Py_None); return Py_None; } -%% -override gst_element_send_event kwargs -static PyObject * -_wrap_gst_element_send_event(PyGObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "event", NULL }; - PyObject *py_event; - int ret; - GstEvent *event = NULL; +/* override gst_element_send_event kwargs */ +/* static PyObject * */ +/* _wrap_gst_element_send_event(PyGObject *self, PyObject *args, PyObject *kwargs) */ +/* { */ +/* static char *kwlist[] = { "event", NULL }; */ +/* PyObject *py_event; */ +/* int ret; */ +/* GstEvent *event = NULL; */ - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:GstElement.send_event", kwlist, &py_event)) - return NULL; - if (pyg_boxed_check(py_event, GST_TYPE_EVENT)) - event = pyg_boxed_get(py_event, GstEvent); - else { - PyErr_SetString(PyExc_TypeError, "event should be a GstEvent"); - return NULL; - } +/* if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:GstElement.send_event", kwlist, &py_event)) */ +/* return NULL; */ +/* if (pyg_boxed_check(py_event, GST_TYPE_EVENT)) */ +/* event = pyg_boxed_get(py_event, GstEvent); */ +/* else { */ +/* PyErr_SetString(PyExc_TypeError, "event should be a GstEvent"); */ +/* return NULL; */ +/* } */ - /* The pipeline unrefs the event, but we want to keep the ownership */ - gst_event_ref(event); +/* /\* The pipeline unrefs the event, but we want to keep the ownership *\/ */ +/* gst_event_ref(event); */ - ret = gst_element_send_event(GST_ELEMENT(self->obj), event); - return PyBool_FromLong(ret); - -} -%% -override gst_element_factory_get_pad_templates -static PyObject * -_wrap_gst_element_factory_get_pad_templates(PyGObject *self) -{ - const GList *pads; - PyObject *list; - - pads = gst_element_factory_get_pad_templates(GST_ELEMENT_FACTORY(self->obj)); +/* ret = gst_element_send_event(GST_ELEMENT(self->obj), event); */ +/* return PyBool_FromLong(ret); */ - list = PyList_New(0); - for (; pads; pads = g_list_next (pads)) - PyList_Append(list, pygobject_new(pads->data)); - - return list; -} +/* } */ +/* %% */ %% override gst_element_query_position args static PyObject * @@ -419,7 +403,6 @@ _wrap_gst_element_query_position (PyGObject *self, PyObject *args) gint format; PyObject *pformat; PyObject *ret; - int i; pformat = (PyObject*)PyTuple_GetItem(args, 0); if (pyg_enum_get_value (GST_TYPE_FORMAT, pformat, &format)) { @@ -433,12 +416,73 @@ _wrap_gst_element_query_position (PyGObject *self, PyObject *args) PyList_Append(ret, PyLong_FromLong(end)); PyList_Append(ret, pyg_enum_from_gtype (GST_TYPE_FORMAT, format )); } else { - for (i = 0; i < 2; i++) { - Py_INCREF(Py_None); - PyList_Append(ret, Py_None); - } - PyList_Append(ret, pformat); + Py_INCREF(Py_None); + ret = Py_None; + } + + return ret; +} +%% +override gst_element_query_convert kwargs +static PyObject * +_wrap_gst_element_query_convert (PyGObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "fromformat", "fromvalue", "destformat", NULL }; + PyObject *pfromformat, *pdestformat; + GstFormat srcformat, destformat; + gint64 fromval, dstval; + PyObject *ret; + + /* Input : src_format, src_val, dst_format */ + /* Returns : dst_format, dst_val OR None */ + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "0L0:GstElement.query_convert", + kwlist, &pfromformat, &fromval, &pdestformat)) + return NULL; + if (pyg_enum_get_value(GST_TYPE_FORMAT, pfromformat, (gint *) &srcformat)) { + PyErr_SetString(PyExc_TypeError, "argument should be a GstFormat"); + return NULL; + } + if (pyg_enum_get_value(GST_TYPE_FORMAT, pdestformat, (gint *) &destformat)) { + PyErr_SetString(PyExc_TypeError, "argument should be a GstFormat"); + return NULL; + } + + if (!(gst_element_query_convert (GST_ELEMENT(self->obj), + srcformat, fromval, + &destformat, &dstval))) { + Py_INCREF(Py_None); + return Py_None; } + + ret = PyList_New(0); + PyList_Append(ret, pyg_enum_from_gtype (GST_TYPE_FORMAT, destformat)); + PyList_Append(ret, PyLong_FromLongLong(dstval)); return ret; } +%% +override gst_element_get_query_types noargs +static PyObject * +_wrap_gst_element_get_query_types (PyGObject *self) +{ + PyObject *ret; + PyObject *item; + int i; + GstQueryType *tab; + + tab = (GstQueryType*) gst_element_get_query_types(GST_ELEMENT(self->obj)); + if (tab == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + + ret = PyList_New(0); + for (i = 0; tab[i] != 0; i++) { + item = pyg_enum_from_gtype (GST_TYPE_QUERY_TYPE, tab[i]); + PyList_Append(ret, item); + } + + return ret; +} diff --git a/gst/gstevent.override b/gst/gstevent.override index f01e573..c8aabd4 100644 --- a/gst/gstevent.override +++ b/gst/gstevent.override @@ -19,3 +19,38 @@ * * Author: Johan Dahlin <johan@gnome.org> */ +%% +override gst_event_discont_get_value kwargs +static PyObject * +_wrap_gst_event_discont_get_value(PyGstMiniObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "format", NULL}; + PyObject *pformat; + GstFormat format; + gint64 start, end; + PyObject *ret; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O:GstEvent.discont_get_value", + kwlist, &pformat)) + return NULL; + if (pyg_enum_get_value (GST_TYPE_FORMAT, pformat, (gint *) &format)) { + PyErr_SetString(PyExc_TypeError, "argument should be a GstFormat"); + return NULL; + } + if (GST_EVENT_TYPE(self->obj) != GST_EVENT_DISCONTINUOUS) { + PyErr_SetString(PyExc_TypeError, "Event is not a discontinuous event"); + return NULL; + } + if (!gst_event_discont_get_value(GST_EVENT (self->obj), format, + &start, &end)) { + Py_INCREF (Py_None); + return Py_None; + } + + ret = PyList_New(0); + PyList_Append(ret, PyLong_FromLongLong(start)); + PyList_Append(ret, PyLong_FromLongLong(end)); + + return ret; +} diff --git a/gst/gstmessage.override b/gst/gstmessage.override new file mode 100644 index 0000000..470d737 --- /dev/null +++ b/gst/gstmessage.override @@ -0,0 +1,109 @@ +/* -*- Mode: C; ; c-file-style: "python" -*- */ +/* gst-python + * Copyright (C) 2005 Edward Hervey + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Johan Dahlin <johan@gnome.org> + */ + +%% +override gst_message_parse_state_changed noargs +static PyObject * +_wrap_gst_message_parse_state_changed (PyGstMiniObject *self) +{ + GstElementState old; + GstElementState new; + PyObject *ret; + + /* Should raise an exception if it's not a state-changed message */ + if (GST_MESSAGE(self->obj)->type != GST_MESSAGE_STATE_CHANGED) { + PyErr_SetString(PyExc_TypeError, "Message is not a state-changed message"); + return NULL; + } + gst_message_parse_state_changed (GST_MESSAGE(self->obj), &old, &new); + /* Return this as a tuple */ + ret = PyList_New(2); + PyList_SET_ITEM(ret, 0, pyg_enum_from_gtype(GST_TYPE_ELEMENT_STATE, old)); + PyList_SET_ITEM(ret, 1, pyg_enum_from_gtype(GST_TYPE_ELEMENT_STATE, new)); + return ret; +} +%% +override gst_message_parse_error noargs +static PyObject * +_wrap_gst_message_parse_error (PyGstMiniObject *self) +{ + PyObject *ret; + GError *error; + gchar *debug; + + if (GST_MESSAGE_TYPE(self->obj) != GST_MESSAGE_ERROR) { + PyErr_SetString(PyExc_TypeError, "Message is not an error message"); + return NULL; + } + + gst_message_parse_error (GST_MESSAGE(self->obj), &error, &debug); + + ret = PyList_New(0); + PyList_Append(ret, pyg_boxed_new (GST_TYPE_G_ERROR, error, TRUE, TRUE)); + if (debug != NULL) + PyList_Append(ret, PyString_FromString(debug)); + + return ret; +} +%% +override gst_message_parse_warning noargs +static PyObject * +_wrap_gst_message_parse_warning (PyGstMiniObject *self) +{ + PyObject *ret; + GError *warning; + gchar *debug; + + if (GST_MESSAGE_TYPE(self->obj) != GST_MESSAGE_WARNING) { + PyErr_SetString(PyExc_TypeError, "Message is not an warning message"); + return NULL; + } + + gst_message_parse_warning (GST_MESSAGE(self->obj), &warning, &debug); + + ret = PyList_New(0); + PyList_Append(ret, pyg_boxed_new (GST_TYPE_G_ERROR, warning, TRUE, TRUE)); + if (debug != NULL) + PyList_Append(ret, PyString_FromString(debug)); + + return ret; +} +%% +override gst_message_parse_tag noargs +static PyObject * +_wrap_gst_message_parse_tag (PyGstMiniObject *self) +{ + PyObject *ret; + GstTagList *taglist; + + if (GST_MESSAGE_TYPE(self->obj) != GST_MESSAGE_TAG) { + PyErr_SetString(PyExc_TypeError, "Message is not an Tag message"); + return NULL; + } + + gst_message_parse_tag (GST_MESSAGE(self->obj), &taglist); + + ret = PyList_New(0); + PyList_Append(ret, pyg_boxed_new (GST_TYPE_TAG_LIST, taglist, TRUE, TRUE)); + + return ret; +} diff --git a/gst/gstmodule.c b/gst/gstmodule.c index 8cab9ad..58c340e 100644 --- a/gst/gstmodule.c +++ b/gst/gstmodule.c @@ -66,14 +66,25 @@ python_do_pending_calls(gpointer data) return TRUE; } -/* static void */ -/* sink_gstobject(GObject *object) */ -/* { */ -/* if (GST_OBJECT_FLOATING(object)) { */ -/* g_object_ref(object); */ -/* gst_object_sink(GST_OBJECT(object)); */ -/* } */ -/* } */ + +static PyObject* +pygstminiobject_from_gvalue(const GValue *value) +{ + GstMiniObject *miniobj; + + if ((miniobj = gst_value_get_mini_object (value)) == NULL) + return NULL; + return pygstminiobject_new(miniobj); +} + +static int +pygstminiobject_to_gvalue(GValue *value, PyObject *obj) +{ + PyGstMiniObject *self = (PyGstMiniObject*) obj; + + gst_value_set_mini_object(value, self->obj); + return 0; +} DL_EXPORT(void) init_gst (void) @@ -139,6 +150,8 @@ init_gst (void) PyModule_AddIntConstant(m, "MSECOND", GST_MSECOND); PyModule_AddIntConstant(m, "NSECOND", GST_NSECOND); + PyModule_AddObject(m, "CLOCK_TIME_NONE", PyLong_FromUnsignedLongLong(-1)); + /* LinkError exception */ PyGstExc_LinkError = PyErr_NewException("gst.LinkError", PyExc_RuntimeError, @@ -146,11 +159,12 @@ init_gst (void) PyDict_SetItemString(d, "LinkError", PyGstExc_LinkError); - PyGstMiniObject_Type.tp_alloc = PyType_GenericAlloc; - PyGstMiniObject_Type.tp_new = PyType_GenericNew; pygstminiobject_register_class(d, "GstMiniObject", GST_TYPE_MINI_OBJECT, &PyGstMiniObject_Type, NULL); - + pyg_register_boxed_custom(GST_TYPE_MINI_OBJECT, + pygstminiobject_from_gvalue, + pygstminiobject_to_gvalue); + pygst_register_classes (d); pygst_add_constants (m, "GST_"); diff --git a/gst/gstpad.override b/gst/gstpad.override index 6fa3ada..ff93a18 100644 --- a/gst/gstpad.override +++ b/gst/gstpad.override @@ -105,6 +105,50 @@ py_pad_private(PyGObject *pad) return pad_private ((GstPad *)pygobject_get(pad)); } +static gboolean +probe_handler_marshal(GstPad *pad, GstMiniObject *data, gpointer user_data) +{ + PyGILState_STATE state; + PyObject *callback, *args; + PyObject *ret; + PyObject *py_data; + PyObject *py_user_data; + gboolean res; + gint len, i; + + g_return_val_if_fail(user_data != NULL, FALSE); + + state = pyg_gil_state_ensure(); + + py_user_data = (PyObject *) user_data; + + py_data = pygstminiobject_new(data); + + callback = PyTuple_GetItem(py_user_data, 0); + args = Py_BuildValue("(NN)", + pygobject_new(G_OBJECT(pad)), + py_data); + + len = PyTuple_Size(py_user_data); + for (i = 1; i < len; ++i) { + PyObject *tuple = args; + args = PySequence_Concat(tuple, PyTuple_GetItem(py_user_data, i)); + Py_DECREF(tuple); + } + ret = PyObject_CallObject(callback, args); + + if (!ret) { + PyErr_Print(); + res = FALSE; + } else { + res = PyObject_IsTrue(ret); + Py_DECREF(ret); + } + Py_DECREF(args); + pyg_gil_state_release(state); + + return res; +} %% ignore gst_pad_select @@ -356,25 +400,24 @@ _wrap_gst_pad_tp_repr (PyGObject *self) } %% -/* override gst_pad_query kwargs */ -/* static PyObject * */ -/* _wrap_gst_pad_query(PyGObject *self, PyObject *args, PyObject *kwargs) */ -/* { */ -/* static char *kwlist[] = { "type", "format", NULL }; */ -/* GstQueryType type; */ -/* GstFormat format; */ -/* gint64 value = 0; */ -/* gboolean ret; */ - -/* if (!PyArg_ParseTupleAndKeywords(args, kwargs, */ -/* "ii:GstPad.query", kwlist, */ -/* &type, &format)) */ -/* return NULL; */ - -/* ret = gst_pad_query(GST_PAD(self->obj), type, &format, &value); */ -/* return PyLong_FromLongLong(value); */ -/* } */ -/* %% */ +override gst_pad_query kwargs +static PyObject * +_wrap_gst_pad_query(PyGObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "query", NULL }; + int ret; + PyGstMiniObject *query; + GstMiniObject *copy; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!:GstPad.query", kwlist, &PyGstQuery_Type, &query)) + return NULL; + copy = gst_mini_object_make_writable(query->obj); + ret = gst_pad_query(GST_PAD(self->obj), GST_QUERY (copy)); + gst_mini_object_unref ((query->obj)); + gst_mini_object_replace (&(query->obj), copy); + return PyBool_FromLong(ret); +} +%% override gst_pad_convert kwargs static PyObject * _wrap_gst_pad_convert(PyGObject *self, PyObject *args, PyObject *kwargs) @@ -531,6 +574,175 @@ _wrap_gst_pad_new(PyGObject *self, PyObject *args, PyObject *kwargs) return 0; } %% +override gst_pad_add_data_probe args +static PyObject * +_wrap_gst_pad_add_data_probe(PyGObject *self, PyObject *args) +{ + PyObject *callback, *cbargs = NULL, *data; + gulong sigid; + gint len; + + len = PyTuple_Size(args); + + if (len < 1) { + PyErr_SetString(PyExc_TypeError, "Probe requires at least 1 arg"); + return NULL; + } + callback = PySequence_GetItem(args, 0); + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "callback is not callable"); + return NULL; + } + cbargs = PySequence_GetSlice(args, 1, len); + if (cbargs == NULL) + return NULL; + data = Py_BuildValue("(ON)", callback, cbargs); + if (data == NULL) + return NULL; + sigid = gst_pad_add_data_probe (GST_PAD (self->obj), (GCallback) probe_handler_marshal, data); + + return PyLong_FromUnsignedLong(sigid); +} +%% +override gst_pad_add_event_probe args +static PyObject * +_wrap_gst_pad_add_event_probe(PyGObject *self, PyObject *args) +{ + PyObject *callback, *cbargs = NULL, *data; + gulong sigid; + gint len; + + len = PyTuple_Size(args); + + if (len < 1) { + PyErr_SetString(PyExc_TypeError, "Probe requires at least 1 arg"); + return NULL; + } + callback = PySequence_GetItem(args, 0); + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "callback is not callable"); + return NULL; + } + cbargs = PySequence_GetSlice(args, 1, len); + if (cbargs == NULL) + return NULL; + data = Py_BuildValue("(ON)", callback, cbargs); + if (data == NULL) + return NULL; + sigid = gst_pad_add_event_probe (GST_PAD (self->obj), (GCallback) probe_handler_marshal, data); + + return PyLong_FromUnsignedLong(sigid); +} +%% +override gst_pad_add_buffer_probe args +static PyObject * +_wrap_gst_pad_add_buffer_probe(PyGObject *self, PyObject *args) +{ + PyObject *callback, *cbargs = NULL, *data; + gulong sigid; + gint len; + + len = PyTuple_Size(args); + + if (len < 1) { + PyErr_SetString(PyExc_TypeError, "Probe requires at least 1 arg"); + return NULL; + } + callback = PySequence_GetItem(args, 0); + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "callback is not callable"); + return NULL; + } + cbargs = PySequence_GetSlice(args, 1, len); + if (cbargs == NULL) + return NULL; + data = Py_BuildValue("(ON)", callback, cbargs); + if (data == NULL) + return NULL; + sigid = gst_pad_add_buffer_probe (GST_PAD (self->obj), (GCallback) probe_handler_marshal, data); + + return PyLong_FromUnsignedLong(sigid); +} +%% +override gst_pad_remove_data_probe kwargs +static PyObject * +_wrap_gst_pad_remove_data_probe(PyGObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "signalid", NULL }; + gulong signalid; + GstPad *pad = GST_PAD (self->obj); + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "k:GstPad.remove_data_probe", + kwlist, &signalid)) + return NULL; + GST_LOCK (pad); + if (!g_signal_handler_is_connected ((gpointer) pad, signalid)) { + GST_UNLOCK (pad); + Py_INCREF (Py_False); + return Py_False; + } + g_signal_handler_disconnect ((gpointer) pad, signalid); + GST_PAD_DO_BUFFER_SIGNALS (pad) -= 1; + GST_PAD_DO_EVENT_SIGNALS (pad) -= 1; + + GST_UNLOCK (pad); + Py_INCREF (Py_True); + return Py_True; +} +%% +override gst_pad_remove_event_probe kwargs +static PyObject * +_wrap_gst_pad_remove_event_probe(PyGObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "signalid", NULL }; + gulong signalid; + GstPad *pad = GST_PAD (self->obj); + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "k:GstPad.remove_event_probe", + kwlist, &signalid)) + return NULL; + GST_LOCK (pad); + if (!g_signal_handler_is_connected ((gpointer) pad, signalid)) { + GST_UNLOCK (pad); + Py_INCREF (Py_False); + return Py_False; + } + g_signal_handler_disconnect ((gpointer) pad, signalid); + GST_PAD_DO_EVENT_SIGNALS (pad) -= 1; + + GST_UNLOCK (pad); + Py_INCREF (Py_True); + return Py_True; +} +%% +override gst_pad_remove_buffer_probe kwargs +static PyObject * +_wrap_gst_pad_remove_buffer_probe(PyGObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "signalid", NULL }; + gulong signalid; + GstPad *pad = GST_PAD (self->obj); + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "k:GstPad.remove_buffer_probe", + kwlist, &signalid)) + return NULL; + GST_LOCK (pad); + if (!g_signal_handler_is_connected ((gpointer) pad, signalid)) { + GST_UNLOCK (pad); + Py_INCREF (Py_False); + return Py_False; + } + g_signal_handler_disconnect ((gpointer) pad, signalid); + GST_PAD_DO_BUFFER_SIGNALS (pad) -= 1; + + GST_UNLOCK (pad); + Py_INCREF (Py_True); + return Py_True; +} +%% override-slot GstPadTemplate.tp_getattr #define IS_ATTR(name) (strcmp (name, attr) == 0) PyObject * @@ -551,4 +763,71 @@ _wrap_gst_pad_template_tp_getattr(PyObject *self, char *attr) } return Py_FindMethod(_PyGstPadTemplate_methods, self, attr); } +%% +override gst_pad_query_position args +static PyObject * +_wrap_gst_pad_query_position (PyGObject *self, PyObject *args) +{ + gint64 cur, end; + gint format; + PyObject *pformat; + PyObject *ret; + + pformat = (PyObject*)PyTuple_GetItem(args, 0); + if (pyg_enum_get_value (GST_TYPE_FORMAT, pformat, &format)) { + PyErr_SetString(PyExc_TypeError, "argument should be a GstFormat"); + return NULL; + } + ret = PyList_New(0); + if ((gst_pad_query_position(GST_PAD (self->obj), (GstFormat*) &format, &cur, &end))) { + PyList_Append(ret, PyLong_FromLong(cur)); + PyList_Append(ret, PyLong_FromLong(end)); + PyList_Append(ret, pyg_enum_from_gtype (GST_TYPE_FORMAT, format )); + } else { + Py_INCREF(Py_None); + ret = Py_None; + } + + return ret; +} +%% +override gst_pad_query_convert kwargs +static PyObject * +_wrap_gst_pad_query_convert (PyGObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "fromformat", "fromvalue", "destformat", NULL }; + PyObject *pfromformat, *pdestformat; + GstFormat srcformat, destformat; + gint64 fromval, dstval; + PyObject *ret; + + /* Input : src_format, src_val, dst_format */ + /* Returns : dst_format, dst_val OR None */ + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "0L0:GstPad.query_convert", + kwlist, &pfromformat, &fromval, &pdestformat)) + return NULL; + if (pyg_enum_get_value(GST_TYPE_FORMAT, pfromformat, (gint *) &srcformat)) { + PyErr_SetString(PyExc_TypeError, "argument should be a GstFormat"); + return NULL; + } + if (pyg_enum_get_value(GST_TYPE_FORMAT, pdestformat, (gint *) &destformat)) { + PyErr_SetString(PyExc_TypeError, "argument should be a GstFormat"); + return NULL; + } + + if (!(gst_pad_query_convert (GST_PAD(self->obj), + srcformat, fromval, + &destformat, &dstval))) { + Py_INCREF(Py_None); + return Py_None; + } + + ret = PyList_New(0); + PyList_Append(ret, pyg_enum_from_gtype (GST_TYPE_FORMAT, destformat)); + PyList_Append(ret, PyLong_FromLongLong(dstval)); + + return ret; +} diff --git a/gst/gstquery.override b/gst/gstquery.override new file mode 100644 index 0000000..79b0558 --- /dev/null +++ b/gst/gstquery.override @@ -0,0 +1,114 @@ +/* -*- Mode: C; ; c-file-style: "python" -*- */ +/* gst-python + * Copyright (C) 2005 Edward Hervey + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Johan Dahlin <johan@gnome.org> + */ + +%% +override gst_query_parse_position noargs +static PyObject * +_wrap_gst_query_parse_position (PyGstMiniObject *self) +{ + GstFormat format; + gint64 cur, end; + PyObject *ret; + + if (GST_QUERY_TYPE(self->obj) != GST_QUERY_POSITION) { + PyErr_SetString(PyExc_TypeError, "Query is not a position query"); + return NULL; + } + + gst_query_parse_position (GST_QUERY(self->obj), &format, &cur, &end); + + ret = PyList_New(0); + PyList_Append(ret, pyg_enum_from_gtype(GST_TYPE_FORMAT, format)); + PyList_Append(ret, PyLong_FromLongLong(cur)); + PyList_Append(ret, PyLong_FromLongLong(end)); + + return ret; +} +%% +override gst_query_parse_convert noargs +static PyObject * +_wrap_gst_query_parse_convert (PyGstMiniObject *self) +{ + GstFormat srcformat, destformat; + gint64 srcvalue, destvalue; + PyObject *ret; + + if (GST_QUERY_TYPE(self->obj) != GST_QUERY_CONVERT) { + PyErr_SetString(PyExc_TypeError, "Query is not a convert query"); + return NULL; + } + + gst_query_parse_convert (GST_QUERY(self->obj), + &srcformat, &srcvalue, + &destformat, &destvalue); + + ret = PyList_New(0); + PyList_Append(ret, pyg_enum_from_gtype(GST_TYPE_FORMAT, srcformat)); + PyList_Append(ret, PyLong_FromLongLong(srcvalue)); + PyList_Append(ret, pyg_enum_from_gtype(GST_TYPE_FORMAT, destformat)); + PyList_Append(ret, PyLong_FromLongLong(destvalue)); + + return ret; +} +%% +override gst_query_parse_seeking_query noargs +static PyObject * +_wrap_gst_query_parse_seeking_query (PyGstMiniObject *self) +{ + GstFormat format; + + if (GST_QUERY_TYPE(self->obj) != GST_QUERY_SEEKING) { + PyErr_SetString(PyExc_TypeError, "Query is not a seeking query"); + return NULL; + } + + gst_query_parse_seeking_query (GST_QUERY(self->obj), &format); + + return pyg_enum_from_gtype(GST_TYPE_FORMAT, format); +} +%% +override gst_query_parse_seeking_response noargs +static PyObject * +_wrap_gst_query_parse_seeking_response (PyGstMiniObject *self) +{ + GstFormat format; + gboolean seekable; + gint64 segstart; + gint64 segend; + PyObject *ret; + + if (GST_QUERY_TYPE(self->obj) != GST_QUERY_SEEKING) { + PyErr_SetString(PyExc_TypeError, "Query is not a seeking query"); + return NULL; + } + + gst_query_parse_seeking_response (GST_QUERY(self->obj), &format, + &seekable, &segstart, &segend); + + ret = PyList_New(0); + PyList_Append(ret, pyg_enum_from_gtype(GST_TYPE_FORMAT, format)); + PyList_Append(ret, PyInt_FromLong((long) seekable)); + PyList_Append(ret, PyLong_FromLongLong(segstart)); + PyList_Append(ret, PyLong_FromLongLong(segend)); + + return ret; +} diff --git a/gst/pygstminiobject.c b/gst/pygstminiobject.c index 4c438e9..a511e0e 100644 --- a/gst/pygstminiobject.c +++ b/gst/pygstminiobject.c @@ -54,9 +54,15 @@ pygst_miniobject_init() PyTypeObject * pygstminiobject_lookup_class(GType gtype) { - PyTypeObject *py_type; + PyTypeObject *py_type = NULL; + GType ctype = gtype; - py_type = g_type_get_qdata(gtype, pygstminiobject_class_key); + while (!py_type && ctype) { + py_type = g_type_get_qdata(ctype, pygstminiobject_class_key); + ctype = g_type_parent(ctype); + } + if (!ctype) + g_error ("Couldn't find a good base type!!"); return py_type; } @@ -184,6 +190,8 @@ pygstminiobject_new(GstMiniObject *obj) } else { /* create wrapper */ PyTypeObject *tp = pygstminiobject_lookup_class(G_OBJECT_TYPE(obj)); + if (!tp) + g_warning ("Couldn't get class for type object : %p", obj); /* need to bump type refcount if created with pygstminiobject_new_with_interfaces(). fixes bug #141042 */ if (tp->tp_flags & Py_TPFLAGS_HEAPTYPE) @@ -214,6 +222,8 @@ pygstminiobject_dealloc(PyGstMiniObject *self) { GstMiniObject *obj = NULL; + g_return_if_fail (self != NULL); + PyGILState_STATE state; state = pyg_gil_state_ensure(); diff --git a/testsuite/test_buffer.py b/testsuite/test_buffer.py index 1621723..a28a3c0 100644 --- a/testsuite/test_buffer.py +++ b/testsuite/test_buffer.py @@ -29,14 +29,9 @@ class BufferTest(unittest.TestCase): test_string = 'a little string' buffer = gst.Buffer(test_string) assert len(buffer) == len(test_string) - #assert hasattr(buffer, 'size') - #assert buffer.size == len(buffer) + assert hasattr(buffer, 'size') + assert buffer.size == len(buffer) - def testBufferMaxSize(self): - buffer = gst.Buffer(buffer_size=16) - assert hasattr(buffer, 'maxsize') - assert buffer.maxsize == 16 - def testBufferCreateSub(self): s = '' for i in range(64): @@ -46,8 +41,7 @@ class BufferTest(unittest.TestCase): assert len(buffer) == 128 sub = buffer.create_sub(16, 16) - assert sub.maxsize == 16 - assert sub.offset == -1, sub.offset + assert sub.offset == gst.CLOCK_TIME_NONE, sub.offset def testBufferMerge(self): buffer1 = gst.Buffer('foo') @@ -73,27 +67,20 @@ class BufferTest(unittest.TestCase): def testBufferFlagIsSet(self): buffer = gst.Buffer() # Off by default - assert not buffer.flag_is_set(gst.BUFFER_READONLY) + assert not buffer.flag_is_set(gst.BUFFER_FLAG_READONLY) # Try switching on and off - buffer.flag_set(gst.BUFFER_READONLY) - assert buffer.flag_is_set(gst.BUFFER_READONLY) - buffer.flag_unset(gst.BUFFER_READONLY) - assert not buffer.flag_is_set(gst.BUFFER_READONLY) + buffer.flag_set(gst.BUFFER_FLAG_READONLY) + assert buffer.flag_is_set(gst.BUFFER_FLAG_READONLY) + buffer.flag_unset(gst.BUFFER_FLAG_READONLY) + assert not buffer.flag_is_set(gst.BUFFER_FLAG_READONLY) # Try switching on and off - buffer.flag_set(gst.BUFFER_IN_CAPS) - assert buffer.flag_is_set(gst.BUFFER_IN_CAPS) - buffer.flag_unset(gst.BUFFER_IN_CAPS) - assert not buffer.flag_is_set(gst.BUFFER_IN_CAPS) + buffer.flag_set(gst.BUFFER_FLAG_IN_CAPS) + assert buffer.flag_is_set(gst.BUFFER_FLAG_IN_CAPS) + buffer.flag_unset(gst.BUFFER_FLAG_IN_CAPS) + assert not buffer.flag_is_set(gst.BUFFER_FLAG_IN_CAPS) - def testAttrType(self): - buffer = gst.Buffer() - assert hasattr(buffer, "data_type") - # XXX: Expose this in gobject - #assert isinstance(buffer.data_type, gobject.GType) - assert buffer.data_type == buffer.__gtype__ - def testAttrFlags(self): buffer = gst.Buffer() assert hasattr(buffer, "flags") @@ -102,11 +89,47 @@ class BufferTest(unittest.TestCase): def testAttrTimestamp(self): buffer = gst.Buffer() assert hasattr(buffer, "timestamp") - assert isinstance(buffer.timestamp, int) + assert isinstance(buffer.timestamp, long) - assert buffer.timestamp == -1 + assert buffer.timestamp == gst.CLOCK_TIME_NONE buffer.timestamp = 0 assert buffer.timestamp == 0 + buffer.timestamp = 2**64 - 1 + assert buffer.timestamp == 2**64 - 1 + + def testAttrDuration(self): + buffer = gst.Buffer() + assert hasattr(buffer, "duration") + assert isinstance(buffer.duration, long) + + assert buffer.duration == gst.CLOCK_TIME_NONE + buffer.duration = 0 + assert buffer.duration == 0 + buffer.duration = 2**64 - 1 + assert buffer.duration == 2**64 - 1 + def testAttrOffset(self): + buffer = gst.Buffer() + assert hasattr(buffer, "offset") + assert isinstance(buffer.offset, long) + + assert buffer.offset == gst.CLOCK_TIME_NONE + buffer.offset = 0 + assert buffer.offset == 0 + buffer.offset = 2**64 - 1 + assert buffer.offset == 2**64 - 1 + + def testAttrOffset_end(self): + buffer = gst.Buffer() + assert hasattr(buffer, "offset_end") + assert isinstance(buffer.offset_end, long) + + assert buffer.offset_end == gst.CLOCK_TIME_NONE + buffer.offset_end = 0 + assert buffer.offset_end == 0 + buffer.offset_end = 2**64 - 1 + assert buffer.offset_end == 2**64 - 1 + + if __name__ == "__main__": unittest.main() diff --git a/testsuite/test_element.py b/testsuite/test_element.py index 561740a..c87bf61 100644 --- a/testsuite/test_element.py +++ b/testsuite/test_element.py @@ -49,29 +49,29 @@ class FakeSinkTest(ElementTest): self.element.get_state() == old_state, 'state changed' - def testStateErrorNullReady(self): - self.checkError(gst.STATE_NULL, gst.STATE_READY, - self.FAKESINK_STATE_ERROR_NULL_READY) +## def testStateErrorNullReady(self): +## self.checkError(gst.STATE_NULL, gst.STATE_READY, +## self.FAKESINK_STATE_ERROR_NULL_READY) - def testStateErrorReadyPaused(self): - self.checkError(gst.STATE_READY, gst.STATE_PAUSED, - self.FAKESINK_STATE_ERROR_READY_PAUSED) +## def testStateErrorReadyPaused(self): +## self.checkError(gst.STATE_READY, gst.STATE_PAUSED, +## self.FAKESINK_STATE_ERROR_READY_PAUSED) - def testStateErrorPausedPlaying(self): - self.checkError(gst.STATE_PAUSED, gst.STATE_PLAYING, - self.FAKESINK_STATE_ERROR_PAUSED_PLAYING) +## def testStateErrorPausedPlaying(self): +## self.checkError(gst.STATE_PAUSED, gst.STATE_PLAYING, +## self.FAKESINK_STATE_ERROR_PAUSED_PLAYING) - def testStateErrorPlayingPaused(self): - self.checkError(gst.STATE_PLAYING, gst.STATE_PAUSED, - self.FAKESINK_STATE_ERROR_PLAYING_PAUSED) +## def testStateErrorPlayingPaused(self): +## self.checkError(gst.STATE_PLAYING, gst.STATE_PAUSED, +## self.FAKESINK_STATE_ERROR_PLAYING_PAUSED) - def testStateErrorPausedReady(self): - self.checkError(gst.STATE_PAUSED, gst.STATE_READY, - self.FAKESINK_STATE_ERROR_PAUSED_READY) +## def testStateErrorPausedReady(self): +## self.checkError(gst.STATE_PAUSED, gst.STATE_READY, +## self.FAKESINK_STATE_ERROR_PAUSED_READY) - def testStateErrorReadyNull(self): - self.checkError(gst.STATE_READY, gst.STATE_NULL, - self.FAKESINK_STATE_ERROR_READY_NULL) +## def testStateErrorReadyNull(self): +## self.checkError(gst.STATE_READY, gst.STATE_NULL, +## self.FAKESINK_STATE_ERROR_READY_NULL) def checkStateChange(self, old, new): def state_change_cb(element, old_s, new_s): @@ -91,17 +91,17 @@ class FakeSinkTest(ElementTest): def testStateChangeNullReady(self): self.checkStateChange(gst.STATE_NULL, gst.STATE_READY) - def testStateChangeReadyPaused(self): - self.checkStateChange(gst.STATE_READY, gst.STATE_PAUSED) +## def testStateChangeReadyPaused(self): +## self.checkStateChange(gst.STATE_READY, gst.STATE_PAUSED) - def testStateChangePausedPlaying(self): - self.checkStateChange(gst.STATE_PAUSED, gst.STATE_PLAYING) +## def testStateChangePausedPlaying(self): +## self.checkStateChange(gst.STATE_PAUSED, gst.STATE_PLAYING) - def testStateChangePlayingPaused(self): - self.checkStateChange(gst.STATE_PLAYING, gst.STATE_PAUSED) +## def testStateChangePlayingPaused(self): +## self.checkStateChange(gst.STATE_PLAYING, gst.STATE_PAUSED) - def testStateChangePausedReady(self): - self.checkStateChange(gst.STATE_PAUSED, gst.STATE_READY) +## def testStateChangePausedReady(self): +## self.checkStateChange(gst.STATE_PAUSED, gst.STATE_READY) def testStateChangeReadyNull(self): self.checkStateChange(gst.STATE_READY, gst.STATE_NULL) @@ -134,7 +134,7 @@ class ElementName(unittest.TestCase): assert get_name(attr) == state assert get_name(gst.STATE_VOID_PENDING) == 'NONE_PENDING' - assert get_name(-1) == 'UNKNOWN!' + assert get_name(-1) == 'UNKNOWN!(-1)' self.assertRaises(TypeError, get_name, '') class QueryTest(unittest.TestCase): @@ -143,9 +143,12 @@ class QueryTest(unittest.TestCase): self.element = self.pipeline.get_by_name('source') def testQuery(self): - assert self.element.query(gst.QUERY_TOTAL, gst.FORMAT_BYTES) == -1 - assert self.element.query(gst.QUERY_POSITION, gst.FORMAT_BYTES) == 0 - assert self.element.query(gst.QUERY_POSITION, gst.FORMAT_TIME) == 0 + res = self.element.query_position(gst.FORMAT_BYTES) + assert res + assert res[0] == 0 + assert res[1] == -1 + res = self.element.query_position(gst.FORMAT_TIME) + assert not res class QueueTest(unittest.TestCase): def testConstruct(self): diff --git a/testsuite/test_event.py b/testsuite/test_event.py index 7e47429..6dd3099 100644 --- a/testsuite/test_event.py +++ b/testsuite/test_event.py @@ -8,12 +8,13 @@ class EventTest(unittest.TestCase): self.sink = pipeline.get_by_name('sink') pipeline.set_state(gst.STATE_PLAYING) - def testEventEmpty(self): - event = gst.Event(gst.EVENT_EMPTY) - self.sink.send_event(event) +## def testEventEmpty(self): +## event = gst.Event(gst.EVENT_EMPTY) +## self.sink.send_event(event) def testEventSeek(self): event = gst.event_new_seek(gst.SEEK_METHOD_CUR, 0) + assert event self.sink.send_event(event) class EventFileSrcTest(unittest.TestCase): @@ -27,6 +28,7 @@ class EventFileSrcTest(unittest.TestCase): self.source = self.pipeline.get_by_name('source') self.sink = self.pipeline.get_by_name('sink') self.sink.connect('handoff', self.handoff_cb) + self.bus = self.pipeline.get_bus() self.pipeline.set_state(gst.STATE_PLAYING) def tearDown(self): @@ -40,8 +42,10 @@ class EventFileSrcTest(unittest.TestCase): def playAndIter(self): self.handoffs = [] assert self.pipeline.set_state(gst.STATE_PLAYING) - while self.pipeline.iterate(): - pass + while 42: + msg = self.bus.pop() + if msg and msg.type == gst.MESSAGE_EOS: + break assert self.pipeline.set_state(gst.STATE_PAUSED) handoffs = self.handoffs self.handoffs = [] diff --git a/testsuite/test_pipeline.py b/testsuite/test_pipeline.py index ce5e90b..44a9bd2 100644 --- a/testsuite/test_pipeline.py +++ b/testsuite/test_pipeline.py @@ -8,11 +8,11 @@ class PipelineConstructor(unittest.TestCase): assert isinstance(pipeline, gst.Pipeline), 'pipeline is not a GstPipline' assert pipeline.get_name() == name, 'pipelines name is wrong' -class ThreadConstructor(unittest.TestCase): - def testCreate(self): - thread = gst.Thread('test-thread') - assert thread is not None, 'thread is None' - assert isinstance(thread, gst.Thread) +## class ThreadConstructor(unittest.TestCase): +## def testCreate(self): +## thread = gst.Thread('test-thread') +## assert thread is not None, 'thread is None' +## assert isinstance(thread, gst.Thread) class Pipeline(unittest.TestCase): def setUp(self): |