From f50c30441c3ee3195f1b49504feac72564ca4532 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Thu, 13 Oct 2005 10:41:06 +0000 Subject: [PATCH] examples/gstfile.py: misc fixes Original commit message from CVS: * examples/gstfile.py: misc fixes * gst/Makefile.am: * gst/pygstexception.c: * gst/pygstexception.h: * gst/gstelementfactory.override: * gst/gst.override: * gst/gstpad.override: * gst/gstmodule.c: (init_gst): Added exceptions system by Alessandro Decina Closes bug #315433 * gst/gstbus.override: * gst/gstelement.override: Fix for _wrap_gst_element_get_state() * gst/gstobject.override: More debug --- ChangeLog | 20 ++++ examples/gstfile.py | 29 +++--- gst/Makefile.am | 4 +- gst/gst.override | 6 +- gst/gstbus.override | 1 + gst/gstelement.override | 1 + gst/gstelementfactory.override | 44 ++++++++ gst/gstmodule.c | 22 +--- gst/gstobject.override | 12 ++- gst/gstpad.override | 8 +- gst/pygstexception.c | 225 +++++++++++++++++++++++++++++++++++++++++ gst/pygstexception.h | 34 +++++++ 12 files changed, 363 insertions(+), 43 deletions(-) create mode 100644 gst/gstelementfactory.override create mode 100644 gst/pygstexception.c create mode 100644 gst/pygstexception.h diff --git a/ChangeLog b/ChangeLog index 8c2c268..bc0ca25 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2005-10-13 Edward Hervey + + * examples/gstfile.py: + misc fixes + * gst/Makefile.am: + * gst/pygstexception.c: + * gst/pygstexception.h: + * gst/gstelementfactory.override: + * gst/gst.override: + * gst/gstpad.override: + * gst/gstmodule.c: (init_gst): + Added exceptions system by Alessandro Decina + Closes bug #315433 + + * gst/gstbus.override: + * gst/gstelement.override: + Fix for _wrap_gst_element_get_state() + * gst/gstobject.override: + More debug + 2005-10-12 Andy Wingo * autogen.sh (CONFIGURE_DEF_OPT): Check for automake 1.9 and 1.8, diff --git a/examples/gstfile.py b/examples/gstfile.py index 4f899b7..de60f9f 100644 --- a/examples/gstfile.py +++ b/examples/gstfile.py @@ -100,7 +100,7 @@ class Discoverer(gst.Pipeline): self.src.set_property("location", filename) self.src.set_property("blocksize", 1000000) self.dbin = gst.element_factory_make("decodebin") - self.add_many(self.src, self.dbin) + self.add(self.src, self.dbin) self.src.link(self.dbin) self.typefind = self.dbin.get_by_name("typefind") @@ -214,14 +214,16 @@ class Discoverer(gst.Pipeline): # We now get the total length of that stream q = gst.query_new_position(gst.FORMAT_TIME) #print "query refcount", q.__grefcount__ + pad.info("sending position query") if pad.get_peer().query(q): #print "query refcount", q.__grefcount__ length = q.structure["end"] pos = q.structure["cur"] format = q.structure["format"] + pad.info("got position query answer : %d:%d:%d" % (length, pos, format)) #print "got length", time_to_string(pos), time_to_string(length), format else: - print "query didn't work" + gst.warning("position query didn't work") #length = pad.get_peer().query(gst.QUERY_TOTAL, gst.FORMAT_TIME) # We store the caps and length in the proper location if "audio" in caps.to_string(): @@ -248,19 +250,20 @@ class Discoverer(gst.Pipeline): def _new_decoded_pad_cb(self, dbin, pad, is_last): # Does the file contain got audio or video ? caps = pad.get_caps() + gst.info("caps:%s" % caps.to_string()) # print "new decoded pad", caps.to_string() if "audio" in caps.to_string(): self.is_audio = True - if caps.is_fixed(): - print "have negotiated caps", caps - self.audiocaps = caps - return +## if caps.is_fixed(): +## print "have negotiated caps", caps +## self.audiocaps = caps +## return elif "video" in caps.to_string(): self.is_video = True - if caps.is_fixed(): - print "have negotiated caps", caps - self.videocaps = caps - return +## if caps.is_fixed(): +## print "have negotiated caps", caps +## self.videocaps = caps +## return else: print "got a different caps..", caps return @@ -268,18 +271,20 @@ class Discoverer(gst.Pipeline): self.finished = True return # we connect a fakesink to the new pad... + pad.info("adding queue->fakesink") fakesink = gst.element_factory_make("fakesink") queue = gst.element_factory_make("queue") - self.add_many(fakesink, queue) + self.add(fakesink, queue) queue.link(fakesink) sinkpad = fakesink.get_pad("sink") queuepad = queue.get_pad("sink") # ... and connect a callback for when the caps are fixed sinkpad.connect("notify::caps", self._notify_caps_cb) if pad.link(queuepad): - print "##### Couldn't link pad to queue" + pad.warning("##### Couldn't link pad to queue") queue.set_state(gst.STATE_PLAYING) fakesink.set_state(gst.STATE_PLAYING) + gst.info('finished here') def _found_tag_cb(self, dbin, source, tags): self.tags.update(tags) diff --git a/gst/Makefile.am b/gst/Makefile.am index f360a2e..4b17131 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -39,7 +39,8 @@ _gst_la_SOURCES = \ pygstiterator.c \ pygstminiobject.c \ pygstobject.c \ - pygstvalue.c + pygstvalue.c \ + pygstexception.c nodist__gst_la_SOURCES = gst.c GST_OVERRIDES = \ @@ -50,6 +51,7 @@ GST_OVERRIDES = \ gstevent.override \ gstcaps.override \ gstelement.override \ + gstelementfactory.override \ gstmessage.override \ gstobject.override \ gstquery.override \ diff --git a/gst/gst.override b/gst/gst.override index 3f2a050..8426ecf 100644 --- a/gst/gst.override +++ b/gst/gst.override @@ -44,16 +44,13 @@ headers #include "pygstvalue.h" #include "pygstminiobject.h" +#include "pygstexception.h" /* These headers have been included directly to get around multiple * GetAttrString calls */ #include #include -PyObject *PyGstExc_LinkError = NULL; -PyObject *PyGstExc_AddError = NULL; -PyObject *PyGstExc_RemoveError = NULL; - GST_DEBUG_CATEGORY_EXTERN (python_debug); GST_DEBUG_CATEGORY_EXTERN (pygst_debug); #define GST_CAT_DEFAULT pygst_debug @@ -259,6 +256,7 @@ include gstbus.override gstcaps.override gstelement.override + gstelementfactory.override gstevent.override gstmessage.override gstobject.override diff --git a/gst/gstbus.override b/gst/gstbus.override index fd58c81..1c7ad54 100644 --- a/gst/gstbus.override +++ b/gst/gstbus.override @@ -205,6 +205,7 @@ _wrap_gst_bus_add_watch (PyGObject *self, PyObject *args) data = Py_BuildValue("(ON)", callback, cbargs); if (data == NULL) return NULL; + sigid = gst_bus_add_watch (GST_BUS (self->obj), (GstBusFunc) bus_func, data); diff --git a/gst/gstelement.override b/gst/gstelement.override index de0fedc..cf2b695 100644 --- a/gst/gstelement.override +++ b/gst/gstelement.override @@ -99,6 +99,7 @@ _wrap_gst_element_get_state(PyGObject *self, PyObject *args, PyObject *kwargs) } if (timeout == Py_None) { /* infinite timeout */ + timeout64 = GST_CLOCK_TIME_NONE; } else { if (timeout == NULL) { diff --git a/gst/gstelementfactory.override b/gst/gstelementfactory.override new file mode 100644 index 0000000..ce72c7e --- /dev/null +++ b/gst/gstelementfactory.override @@ -0,0 +1,44 @@ +/* + * gstelementfactory.override - gstreamer element factory override + * Copyright (C) 2005 Alessandro Decina + * + * Authors: + * Alessandro Decina + * + * 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. + */ + +%% +override gst_element_factory_make kwargs +static PyObject * +_wrap_gst_element_factory_make(PyObject *self, PyObject *args, PyObject *kwargs){ + static char *kwlist[] = { "factoryname", "name", NULL }; + char *factoryname, *name = NULL; + PyObject *py_ret; + GstElement *ret; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|z:element_factory_make", kwlist, &factoryname, &name)) + return NULL; + ret = gst_element_factory_make(factoryname, name); + if (ret == NULL) { + PyErr_SetString(PyGstExc_PluginNotFoundError, factoryname); + return NULL; + } + py_ret = pygstobject_new((GObject *)ret); + pygst_object_unref((GObject *)ret); + return py_ret; +} + diff --git a/gst/gstmodule.c b/gst/gstmodule.c index 4480a60..2333d57 100644 --- a/gst/gstmodule.c +++ b/gst/gstmodule.c @@ -25,6 +25,7 @@ #endif #include "pygstminiobject.h" +#include "pygstexception.h" #include @@ -40,9 +41,6 @@ void _pygst_register_boxed_types(PyObject *moddict); extern PyMethodDef pygst_functions[]; extern GSList *mainloops; extern void _pygst_main_quit(void); -extern PyObject *PyGstExc_LinkError; -extern PyObject *PyGstExc_AddError; -extern PyObject *PyGstExc_RemoveError; GST_DEBUG_CATEGORY (pygst_debug); /* for bindings code */ GST_DEBUG_CATEGORY (python_debug); /* for python code */ @@ -185,22 +183,8 @@ init_gst (void) PyModule_AddObject(m, "CLOCK_TIME_NONE", PyLong_FromUnsignedLongLong(GST_CLOCK_TIME_NONE)); - /* exceptions */ - PyGstExc_LinkError = PyErr_NewException("gst.LinkError", - PyExc_RuntimeError, - NULL); - PyDict_SetItemString(d, "LinkError", PyGstExc_LinkError); - - PyGstExc_AddError = PyErr_NewException("gst.AddError", - PyExc_RuntimeError, - NULL); - PyDict_SetItemString(d, "AddError", PyGstExc_AddError); - - PyGstExc_RemoveError = PyErr_NewException("gst.RemoveError", - PyExc_RuntimeError, - NULL); - PyDict_SetItemString(d, "RemoveError", PyGstExc_RemoveError); - + pygst_exceptions_register_classes (d); + REGISTER_TYPE(d, PyGstIterator_Type, "Iterator"); diff --git a/gst/gstobject.override b/gst/gstobject.override index d0e362e..b59d1fa 100644 --- a/gst/gstobject.override +++ b/gst/gstobject.override @@ -60,27 +60,29 @@ _wrap_gst_object_tp_traverse(PyGObject *self, visitproc visit, void *arg) int ret = 0; GSList *tmp; - GST_LOG_OBJECT(self->obj, - "gst.Object.tp_traverse"); + GST_LOG_OBJECT(self->obj, "gst.Object.tp_traverse, arg:%p", arg); Py_VISIT(self->inst_dict); + GST_LOG_OBJECT(self->obj, "visited self->inst_dict"); + for (tmp = self->closures; tmp != NULL; tmp = tmp->next) { PyGClosure *closure = tmp->data; + GST_DEBUG_OBJECT (self->obj, "visiting closures"); Py_VISIT(closure->callback); Py_VISIT(closure->extra_args); Py_VISIT(closure->swap_data); } - if (self->obj && GST_OBJECT_REFCOUNT_VALUE(self->obj) == 1 && GST_OBJECT(self->obj)->parent == NULL) { + if (self->obj && GST_OBJECT_REFCOUNT_VALUE(self->obj) == 1) { GST_DEBUG_OBJECT(self->obj, "gst.Object.tp_traverse: GstObject refcount of %p is 1, visit", self->obj); ret = visit((PyObject *)self, arg); GST_LOG_OBJECT(self->obj, - "gst.Object.tp_traverse: GstObject %p visited, ret %d", - self->obj, ret); + "gst.Object.tp_traverse: GstObject %p visited, ret %d, refcount %d", + self->obj, ret, GST_OBJECT_REFCOUNT_VALUE(self->obj)); } return ret; diff --git a/gst/gstpad.override b/gst/gstpad.override index cb44eea..90b1c18 100644 --- a/gst/gstpad.override +++ b/gst/gstpad.override @@ -432,7 +432,9 @@ _wrap_gst_pad_link(PyGObject *self, PyObject *args, PyObject *kwargs) return NULL; ret = gst_pad_link(GST_PAD(self->obj), GST_PAD(sinkpad->obj)); if (ret) { - PyErr_SetString(PyGstExc_LinkError, "link failed"); + PyObject *exc_val = pyg_enum_from_gtype(GST_TYPE_PAD_LINK_RETURN, ret); + PyErr_SetObject(PyGstExc_LinkError, exc_val); + Py_DECREF(exc_val); return NULL; } return PyBool_FromLong(ret); @@ -463,7 +465,9 @@ _wrap_gst_pad_link_filtered(PyGObject *self, PyObject *args, PyObject *kwargs) GST_PAD(sinkpad->obj), filtercaps); if (ret) { - PyErr_SetString(PyGstExc_LinkError, "link failed"); + PyObject *exc_val = pyg_enum_from_gtype(GST_TYPE_PAD_LINK_RETURN, ret); + PyErr_SetObject(PyGstExc_LinkError, exc_val); + Py_DECREF(exc_val); return NULL; } return PyBool_FromLong(ret); diff --git a/gst/pygstexception.c b/gst/pygstexception.c new file mode 100644 index 0000000..0c880b7 --- /dev/null +++ b/gst/pygstexception.c @@ -0,0 +1,225 @@ +/* + * pygstexception.c - gst-python exceptions + * Copyright (C) 2005 Alessandro Decina + * + * Authors: + * Alessandro Decina + * + * 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. + */ + +#include +#include "structmember.h" + +PyObject *PyGstExc_LinkError = NULL; +PyObject *PyGstExc_AddError = NULL; +PyObject *PyGstExc_RemoveError = NULL; +PyObject *PyGstExc_PluginNotFoundError = NULL; + + +static PyObject * +call_exception_init(PyObject *args) +{ + PyObject *parent_init = NULL; + PyObject *res = NULL; + + /* get Exception.__init__ */ + parent_init = PyObject_GetAttrString(PyExc_Exception, "__init__"); + if (parent_init == NULL) + goto exception; + + /* call Exception.__init__. This will set self.args */ + res = PyObject_CallObject(parent_init, args); + if (res == NULL) + goto exception; + + Py_DECREF(parent_init); + + return res; + +exception: + Py_XDECREF(parent_init); + Py_XDECREF(res); + + return NULL; +} + +static int +add_method(PyObject *klass, PyObject *dict, PyMethodDef *method) { + PyObject *module = NULL; + PyObject *func = NULL; + PyObject *meth = NULL; + + module = PyString_FromString("gst"); + if (module == NULL) + goto exception; + + func = PyCFunction_NewEx(method, NULL, module); + if (func == NULL) + goto exception; + Py_DECREF(module); + + meth = PyMethod_New(func, NULL, klass); + if (meth == NULL) + goto exception; + Py_DECREF(func); + + if (PyDict_SetItemString(dict, method->ml_name, meth) < 0) + goto exception; + Py_DECREF(meth); + + return 0; + +exception: + Py_XDECREF(module); + Py_XDECREF(func); + Py_XDECREF(meth); + + return -1; +} + +static PyObject * +link_error_init(PyObject *self, PyObject *args) +{ + PyObject *err_type = NULL; + int status; + + if (!PyArg_ParseTuple(args, "O|O:__init__", &self, &err_type)) + return NULL; + + if (err_type == NULL) + err_type = Py_None; + Py_INCREF(err_type); + + /* set self.error */ + status = PyObject_SetAttrString(self, "error", err_type); + Py_DECREF(err_type); + if (status < 0) + return NULL; + + return call_exception_init(args); +} + +static PyObject * +plugin_not_found_error_init(PyObject *self, PyObject *args) +{ + PyObject *plugin_name = NULL; + int status; + + if (!PyArg_ParseTuple(args, "O|O:__init__", &self, &plugin_name)) + return NULL; + + if (plugin_name == NULL) + plugin_name = Py_None; + Py_INCREF(plugin_name); + + /* set self.name */ + status = PyObject_SetAttrString(self, "name", plugin_name); + Py_DECREF(plugin_name); + if (status < 0) + return NULL; + + return call_exception_init(args); +} + +static PyMethodDef link_error_init_method = {"__init__", + link_error_init, METH_VARARGS +}; + +static PyMethodDef plugin_not_found_error_init_method = {"__init__", + plugin_not_found_error_init, METH_VARARGS +}; + +void +pygst_exceptions_register_classes(PyObject *d) +{ + PyObject *dict = NULL; + + /* register gst.LinkError */ + dict = PyDict_New(); + if (dict == NULL) + goto exception; + + PyGstExc_LinkError = PyErr_NewException("gst.LinkError", + PyExc_Exception, dict); + if (PyGstExc_LinkError == NULL) + goto exception; + + if (add_method(PyGstExc_LinkError, dict, &link_error_init_method) < 0) + goto exception; + + Py_DECREF(dict); + + if (PyDict_SetItemString(d, "LinkError", PyGstExc_LinkError) < 0) + goto exception; + + Py_DECREF(PyGstExc_LinkError); + + /* register gst.AddError */ + PyGstExc_AddError = PyErr_NewException("gst.AddError", + PyExc_Exception, NULL); + if (PyGstExc_AddError == NULL) + goto exception; + + if (PyDict_SetItemString(d, "AddError", PyGstExc_AddError) < 0) + goto exception; + + Py_DECREF(PyGstExc_AddError); + + /* register gst.RemoveError */ + PyGstExc_RemoveError = PyErr_NewException("gst.RemoveError", + PyExc_Exception, NULL); + if (PyGstExc_RemoveError == NULL) + goto exception; + + if (PyDict_SetItemString(d, "RemoveError", PyGstExc_RemoveError) < 0) + goto exception; + + Py_DECREF(PyGstExc_RemoveError); + + /* register gst.PluginNotFoundError */ + dict = PyDict_New(); + if (dict == NULL) + goto exception; + + PyGstExc_PluginNotFoundError = \ + PyErr_NewException("gst.PluginNotFoundError", PyExc_Exception, dict); + if (PyGstExc_PluginNotFoundError == NULL) + goto exception; + + if (add_method(PyGstExc_PluginNotFoundError, + dict, &plugin_not_found_error_init_method) < 0) + goto exception; + + Py_DECREF(dict); + + if (PyDict_SetItemString(d, "PluginNotFoundError", + PyGstExc_PluginNotFoundError) < 0) + goto exception; + + Py_DECREF(PyGstExc_PluginNotFoundError); + + return; + +exception: + Py_XDECREF(dict); + Py_XDECREF(PyGstExc_LinkError); + Py_XDECREF(PyGstExc_AddError); + Py_XDECREF(PyGstExc_RemoveError); + Py_XDECREF(PyGstExc_PluginNotFoundError); + + return; +} diff --git a/gst/pygstexception.h b/gst/pygstexception.h new file mode 100644 index 0000000..bd50cf5 --- /dev/null +++ b/gst/pygstexception.h @@ -0,0 +1,34 @@ +/* + * pygstexception.h - gst-python exceptions + * Copyright (C) 2005 Alessandro Decina + * + * Authors: + * Alessandro Decina + * + * 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. + */ + +#ifndef _PYGSTEXCEPTION_H_ +#define _PYGSTEXCEPTION_H_ + +extern PyObject *PyGstExc_LinkError; +extern PyObject *PyGstExc_AddError; +extern PyObject *PyGstExc_RemoveError; +extern PyObject *PyGstExc_PluginNotFoundError; + +void pygst_exceptions_register_classes(PyObject *d); + +#endif /* _PYGSTEXCEPTION_H_ */ -- 2.7.4