From 7534ba048688b3c58f13ea478c20fb722838ea26 Mon Sep 17 00:00:00 2001 From: Johan Dahlin Date: Fri, 7 Oct 2005 01:21:57 +0000 Subject: [PATCH] Add GstIterator wrapping and tests. Original commit message from CVS: * codegen/argtypes.py: * gst/Makefile.am: * gst/common.h: * gst/gst.defs: * gst/gstbin.override: * gst/gstelement.override: * gst/pygstiterator.c: (pygst_iterator_dealloc), (pygst_iterator_iter_next), (pygst_iterator_new): * testsuite/test_iterator.py: Add GstIterator wrapping and tests. --- ChangeLog | 13 +++++ codegen/argtypes.py | 7 +++ gst/Makefile.am | 9 ++- gst/common.h | 1 + gst/gst.defs | 14 ++--- gst/gstbin.override | 9 ++- gst/gstelement.override | 7 +++ gst/pygstiterator.c | 113 +++++++++++++++++++++++++++++++++++++ testsuite/test_iterator.py | 67 ++++++++++++++++++++++ 9 files changed, 230 insertions(+), 10 deletions(-) create mode 100644 gst/pygstiterator.c create mode 100644 testsuite/test_iterator.py diff --git a/ChangeLog b/ChangeLog index e50da311a1..52ec80b86c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2005-10-06 Johan Dahlin + + * codegen/argtypes.py: + * gst/Makefile.am: + * gst/common.h: + * gst/gst.defs: + * gst/gstbin.override: + * gst/gstelement.override: + * gst/pygstiterator.c: (pygst_iterator_dealloc), + (pygst_iterator_iter_next), (pygst_iterator_new): + * testsuite/test_iterator.py: + Add GstIterator wrapping and tests. + 2005-10-06 Edward Hervey * gst/gstpad.override: diff --git a/codegen/argtypes.py b/codegen/argtypes.py index 7e591e3ea7..d4a62194ed 100644 --- a/codegen/argtypes.py +++ b/codegen/argtypes.py @@ -918,6 +918,11 @@ class ArgMatcher: if not self.argtypes.has_key(otype): return 0 return self.object_is_a(self.get(otype).parent, parent) +class GstIteratorArg(ArgType): + def write_return(self, ptype, ownsreturn, info): + info.varlist.add('GstIterator', '*ret') + info.codeafter.append(' return pygst_iterator_new(ret);') + matcher = ArgMatcher() arg = NoneArg() @@ -1003,6 +1008,8 @@ matcher.register('gfloat', arg) arg = FileArg() matcher.register('FILE*', arg) +matcher.register('GstIterator*', GstIteratorArg()) + # enums, flags, objects matcher.register('GdkAtom', AtomArg()) diff --git a/gst/Makefile.am b/gst/Makefile.am index 1e32cbb804..f360a2efa0 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -33,7 +33,14 @@ GEN_FILES = arg-types.py gst-types.defs libs.defs _gst_la_CFLAGS = $(common_cflags) _gst_la_LIBADD = $(common_libadd) _gst_la_LDFLAGS = $(common_ldflags) -export-symbols-regex init_gst $(GST_BASE_LIBS) $(GST_CONTROLLER_LIBS) -_gst_la_SOURCES = gst-argtypes.c gstmodule.c pygstvalue.c pygstminiobject.c pygstobject.c +_gst_la_SOURCES = \ + gst-argtypes.c \ + gstmodule.c \ + pygstiterator.c \ + pygstminiobject.c \ + pygstobject.c \ + pygstvalue.c + nodist__gst_la_SOURCES = gst.c GST_OVERRIDES = \ gst.override \ diff --git a/gst/common.h b/gst/common.h index 41e8779620..ab2024b9e6 100644 --- a/gst/common.h +++ b/gst/common.h @@ -52,6 +52,7 @@ typedef struct { /* gboolean pygst_data_from_pyobject(PyObject *object, GstData **data); */ /* PyObject *pygst_data_to_pyobject(GstData *data); */ GstCaps *pygst_caps_from_pyobject (PyObject *object, gboolean *copy); +PyObject* pygst_iterator_new(GstIterator *iter); #endif /* __COMMON_H__ */ diff --git a/gst/gst.defs b/gst/gst.defs index 46ad189d44..a5b88c8fdf 100644 --- a/gst/gst.defs +++ b/gst/gst.defs @@ -136,25 +136,25 @@ ) ) -(define-method iterate_elements +(define-method elements (of-object "GstBin") (c-name "gst_bin_iterate_elements") (return-type "GstIterator*") ) -(define-method iterate_sorted +(define-method sorted (of-object "GstBin") (c-name "gst_bin_iterate_sorted") (return-type "GstIterator*") ) -(define-method iterate_recurse +(define-method recurse (of-object "GstBin") (c-name "gst_bin_iterate_recurse") (return-type "GstIterator*") ) -(define-method iterate_sinks +(define-method sinks (of-object "GstBin") (c-name "gst_bin_iterate_sinks") (return-type "GstIterator*") @@ -1018,19 +1018,19 @@ ) ) -(define-method iterate_pads +(define-method pads (of-object "GstElement") (c-name "gst_element_iterate_pads") (return-type "GstIterator*") ) -(define-method iterate_src_pads +(define-method src_pads (of-object "GstElement") (c-name "gst_element_iterate_src_pads") (return-type "GstIterator*") ) -(define-method iterate_sink_pads +(define-method sink_pads (of-object "GstElement") (c-name "gst_element_iterate_sink_pads") (return-type "GstIterator*") diff --git a/gst/gstbin.override b/gst/gstbin.override index d0f6148019..8049291080 100644 --- a/gst/gstbin.override +++ b/gst/gstbin.override @@ -114,8 +114,6 @@ _wrap_gst_bin_remove_many(PyGObject *self, PyObject *args) return NULL; return _wrap_gst_bin_remove (self, args); } - - %% override gst_bin_get_by_name kwargs static PyObject * @@ -142,3 +140,10 @@ _wrap_gst_bin_get_by_name(PyGObject *self, PyObject *args, PyObject *kwargs) gst_object_unref (el); /* from _get_by_name */ return ret; } +%% +override-slot GstBin.tp_iter +static PyObject * +_wrap_gst_bin_tp_iter(PyGObject *self) +{ + return _wrap_gst_bin_iterate_elements(self); +} diff --git a/gst/gstelement.override b/gst/gstelement.override index c450558a42..95a4847f75 100644 --- a/gst/gstelement.override +++ b/gst/gstelement.override @@ -472,3 +472,10 @@ _wrap_gst_element_get_query_types (PyGObject *self) return ret; } +%% +override-slot GstElement.tp_iter +static PyObject * +_wrap_gst_element_tp_iter(PyGObject *self) +{ + return _wrap_gst_element_iterate_pads(self); +} diff --git a/gst/pygstiterator.c b/gst/pygstiterator.c new file mode 100644 index 0000000000..22c2af9ed7 --- /dev/null +++ b/gst/pygstiterator.c @@ -0,0 +1,113 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- */ +/* gst-python + * Copyright (C) 2005 Johan Dahlin + * + * 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 + */ + +#include +#include +#include +#include "pygstobject.h" + +typedef struct { + PyObject_HEAD + GstIterator *iter; +} PyGstIterator; + +static void +pygst_iterator_dealloc(PyGstIterator *self) +{ + gst_iterator_free(self->iter); + PyObject_Del((PyObject*) self); +} + +static PyObject * +pygst_iterator_iter_next(PyGstIterator *self) +{ + gpointer element; + PyObject *retval = NULL; + GstIteratorResult result; + + result = gst_iterator_next(self->iter, &element); + switch (result) + { + case GST_ITERATOR_DONE: + PyErr_SetNone(PyExc_StopIteration); + break; + case GST_ITERATOR_OK: + if (g_type_is_a(self->iter->type, G_TYPE_OBJECT)) + retval = pygstobject_new(G_OBJECT(element)); + else { + PyErr_Format(PyExc_TypeError, "Unsupported child type: %s", + g_type_name(self->iter->type)); + } + break; + case GST_ITERATOR_RESYNC: + PyErr_SetString(PyExc_TypeError, "Resync"); + break; + case GST_ITERATOR_ERROR: + PyErr_SetString(PyExc_TypeError, "Error"); + break; + default: + g_assert_not_reached(); + break; + } + + return retval; +} + +PyTypeObject PyGstIterator_Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "gst.Iterator", /* tp_name */ + sizeof(PyGstIterator), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)pygst_iterator_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "GstIterator wrapper", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)pygst_iterator_iter_next, /* tp_iternext */ +}; + +PyObject* +pygst_iterator_new(GstIterator *iter) +{ + PyGstIterator *self; + self = PyObject_NEW(PyGstIterator, &PyGstIterator_Type); + self->iter = iter; + return (PyObject *) self; +} diff --git a/testsuite/test_iterator.py b/testsuite/test_iterator.py new file mode 100644 index 0000000000..6a6eeb884d --- /dev/null +++ b/testsuite/test_iterator.py @@ -0,0 +1,67 @@ +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 +# +# Copyright (C) 2005 Johan Dahlin +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser 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 + +import unittest +from common import gst, TestCase + +class IteratorTest(TestCase): + # XXX: This is busted. Testsuite or iterator bindings? + def gcverify(self): + pass + + # XXX: Elements + + def testIteratePadsFakeSrc(self): + fakesrc = gst.element_factory_make('fakesrc') + pads = list(fakesrc.pads()) + srcpad = fakesrc.get_pad('src') + self.assertEqual(len(pads), 1) + self.assertEqual(pads[0], srcpad) + srcpads = list(fakesrc.src_pads()) + self.assertEqual(len(srcpads), 1) + self.assertEqual(srcpads[0], srcpad) + sinkpads = list(fakesrc.sink_pads()) + self.assertEqual(sinkpads, []) + + self.assertEqual(len(list(fakesrc)), 1) + for pad in fakesrc: + self.assertEqual(pad, srcpad) + break + else: + raise AssertionError + + def testIteratePadsFakeSink(self): + fakesink = gst.element_factory_make('fakesink') + pads = list(fakesink.pads()) + sinkpad = fakesink.get_pad('sink') + self.assertEqual(len(pads), 1) + self.assertEqual(pads[0], sinkpad) + srcpads = list(fakesink.src_pads()) + self.assertEqual(srcpads, []) + sinkpads = list(fakesink.sink_pads()) + self.assertEqual(len(sinkpads), 1) + self.assertEqual(sinkpads[0], sinkpad) + + self.assertEqual(len(list(fakesink)), 1) + for pad in fakesink: + self.assertEqual(pad, sinkpad) + break + else: + raise AssertionError +