diff options
48 files changed, 280 insertions, 8322 deletions
@@ -32,7 +32,6 @@ libtool ltmain.sh missing stamp-h1 -bindings/python/rtspserver.c tags gst-rtsp.spec stamp-h.in diff --git a/bindings/Makefile.am b/bindings/Makefile.am index b193731..7a9ca5a 100644 --- a/bindings/Makefile.am +++ b/bindings/Makefile.am @@ -1,9 +1,5 @@ SUBDIRS = -if WITH_PYTHON - SUBDIRS += python -endif - if WITH_VALA SUBDIRS += vala endif diff --git a/bindings/python/Makefile.am b/bindings/python/Makefile.am deleted file mode 100644 index b9ba9c7..0000000 --- a/bindings/python/Makefile.am +++ /dev/null @@ -1,46 +0,0 @@ -SUBDIRS = codegen -pkgpyexecdir = $(pyexecdir)/gst-$(GST_MAJORMINOR)/gst - -# we install everything in pyexecdir; otherwise you end up with a mess for -# multilib -pygstrtspserverdir = $(pkgpyexecdir) -pygstrtspserver_PYTHON = - -pygstrtspserverexecdir = $(pkgpyexecdir) -pygstrtspserverexec_LTLIBRARIES = rtspserver.la - -DEFS = $(srcdir)/rtspserver-types.defs $(srcdir)/rtspserver.defs -defs_DATA = $(DEFS) -defsdir = $(pkgdatadir)/$(GST_MAJORMINOR)/defs -OVERRIDES = rtspserver.override - -INCLUDES = -I$(top_srcdir) -I$(srcdir) $(PYTHON_INCLUDES) - -rtspserver_la_CFLAGS = -I$(top_srcdir)/src \ - $(PYGOBJECT_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) -rtspserver_la_LDFLAGS = -export-symbols-regex "^(initrtspserver|_PyGObject_API).*" \ - -module -avoid-version $(GST_PLUGIN_LDFLAGS) -rtspserver_la_LIBADD = $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_MAJORMINOR@.la \ - $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) \ - -lgstrtp-@GST_MAJORMINOR@ -lgstrtsp-@GST_MAJORMINOR@ \ - -lgstsdp-@GST_MAJORMINOR@ $(GST_LIBS) $(LIBM) -rtspserver_la_SOURCES = rtspservermodule.c -nodist_rtspserver_la_SOURCES = rtspserver.c - -EXTRA_DIST = $(defs_DATA) $(OVERRIDES) arg-types.py - -CLEANFILES = rtspserver.c - -rtspserver.c: $(DEFS) $(OVERRIDES) arg-types.py - -.defs.c: - ($(PYTHON) $(srcdir)/codegen/codegen.py \ - --load-types $(srcdir)/arg-types.py \ - --register $(srcdir)/rtspserver-types.defs \ - --register $(PYGST_DEFSDIR)/gst-types.defs \ - --override $(srcdir)/$*.override \ - --extendpath $(top_builddir)/gst/ \ - --extendpath $(srcdir)/ \ - --prefix pygst_rtsp_server $<) > gen-$*.c \ - && cp gen-$*.c $*.c \ - && rm -f gen-$*.c diff --git a/bindings/python/arg-types.py b/bindings/python/arg-types.py deleted file mode 100644 index 112fb30..0000000 --- a/bindings/python/arg-types.py +++ /dev/null @@ -1,451 +0,0 @@ -# -*- Mode: Python -*- -# vi:si:et:sw=4:sts=4:ts=4 -# -# gst-python -# Copyright (C) 2002 David I. Lehn -# 2004 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: David I. Lehn <dlehn@users.sourceforge.net> - -from argtypes import UInt64Arg, Int64Arg, PointerArg, ArgMatcher, ArgType, matcher -from reversewrapper import Parameter, ReturnType, GBoxedParam, GBoxedReturn, IntParam, IntReturn - -class XmlNodeArg(ArgType): - """libxml2 node generator""" - - names = {"xobj":"xmlNode", - "xptr":"xmlNodePtr", - "xwrap":"libxml_xmlNodePtrWrap"} - - parm = (' if(xml == NULL) return NULL;\n' - ' xobj = PyObject_GetAttrString(xml, "%(xobj)s");\n' - ' if(!PyObject_IsInstance(py%(name)s, xobj)) {\n' - ' PyErr_Clear();\n' - ' PyErr_SetString(PyExc_RuntimeError,"%(name)s is not a %(xobj)s instance");\n' - ' Py_DECREF(xobj);Py_DECREF(xml);\n' - ' return NULL;\n' - ' }\n' - ' o = PyObject_GetAttrString(py%(name)s, "_o");\n' - ' %(name)s = PyCObject_AsVoidPtr(o);\n') - parmp = (' Py_DECREF(o); Py_DECREF(xobj);Py_DECREF(xml);\n') - - ret = (' if(xml == NULL) return NULL;\n') - retp = (' xargs = PyTuple_New(1);\n' - ' xobj = PyObject_GetAttrString(xml, "%(xobj)s");\n' - ' o = %(xwrap)s(ret);\n' - ' PyTuple_SetItem(xargs, 0, o);\n' - ' return PyInstance_New(xobj, xargs, PyDict_New());\n') - - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - info.varlist.add('PyObject', '*xml = _gst_get_libxml2_module()') - info.varlist.add('PyObject', '*o') - info.varlist.add('PyObject', '*xobj') - info.varlist.add('PyObject', '*py' + pname) - info.varlist.add(self.names["xptr"], pname) - #if pnull: - info.add_parselist('O', ['&py'+pname], [pname]) - info.arglist.append(pname) - self.names["name"] = pname - info.codebefore.append(self.parm % self.names) - info.codeafter.append(self.parmp % self.names); - def write_return(self, ptype, ownsreturn, info): - info.varlist.add('PyObject', '*xml = _gst_get_libxml2_module()') - info.varlist.add('PyObject', '*xargs') - info.varlist.add('PyObject', '*xobj') - info.varlist.add('PyObject', '*o') - info.varlist.add(self.names["xptr"], 'ret') - info.codebefore.append(self.ret % self.names) - info.codeafter.append(self.retp % self.names) - -class XmlDocArg(XmlNodeArg): - """libxml2 doc generator""" - names = {"xobj":"xmlDoc", - "xptr":"xmlDocPtr", - "xwrap":"libxml_xmlDocPtrWrap"} - -class GstCapsArg(ArgType): - """GstCaps node generator""" - - before = (' %(name)s = pygst_caps_from_pyobject (py_%(name)s, %(namecopy)s);\n' - ' if (PyErr_Occurred())\n' - ' return NULL;\n') - beforenull = (' if (py_%(name)s == Py_None || py_%(name)s == NULL)\n' - ' %(name)s = NULL;\n' - ' else\n' - ' ' + before) - after = (' if (%(name)s && %(name)s_is_copy)\n' - ' gst_caps_unref (%(name)s);\n') - - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if ptype == 'const-GstCaps*': - self.write_const_param(pname, pdflt, pnull, info) - elif ptype == 'GstCaps*': - self.write_normal_param(pname, pdflt, pnull, info) - else: - raise RuntimeError, "write_param not implemented for %s" % ptype - - def write_const_param(self, pname, pdflt, pnull, info): - if pdflt: - assert pdflt == 'NULL' - info.varlist.add('PyObject', '*py_' + pname + ' = NULL') - else: - info.varlist.add('PyObject', '*py_' + pname) - info.varlist.add('GstCaps', '*'+pname) - info.varlist.add('gboolean', pname+'_is_copy') - info.add_parselist('O', ['&py_'+pname], [pname]) - info.arglist.append(pname) - if pnull: - info.codebefore.append (self.beforenull % { 'name' : pname, 'namecopy' : '&'+pname+'_is_copy' }) - else: - info.codebefore.append (self.before % { 'name' : pname, 'namecopy' : '&'+pname+'_is_copy' }) - info.codeafter.append (self.after % { 'name' : pname, 'namecopy' : '&'+pname+'_is_copy' }) - - def write_normal_param(self, pname, pdflt, pnull, info): - if pdflt: - assert pdflt == 'NULL' - info.varlist.add('PyObject', '*py_' + pname + ' = NULL') - else: - info.varlist.add('PyObject', '*py_' + pname) - info.varlist.add('GstCaps', '*'+pname) - info.add_parselist('O', ['&py_'+pname], [pname]) - info.arglist.append(pname) - if pnull: - info.codebefore.append (self.beforenull % { 'name' : pname, 'namecopy' : 'NULL' }) - else: - info.codebefore.append (self.before % { 'name' : pname, 'namecopy' : 'NULL' }) - - def write_return(self, ptype, ownsreturn, info): - if ptype == 'GstCaps*': - info.varlist.add('GstCaps', '*ret') - copyval = 'FALSE' - elif ptype == 'const-GstCaps*': - info.varlist.add('const GstCaps', '*ret') - copyval = 'TRUE' - else: - raise RuntimeError, "write_return not implemented for %s" % ptype - info.codeafter.append(' return pyg_boxed_new (GST_TYPE_CAPS, ret, '+copyval+', TRUE);') - -class GstIteratorArg(ArgType): - def write_return(self, ptype, ownsreturn, info): - info.varlist.add('GstIterator', '*ret') - info.codeafter.append(' return pygst_iterator_new(ret);') - -class GstRTSPUrlArg(ArgType): - """GstRTSPUrl node generator""" - - before = (' parse_result = gst_rtsp_url_parse (py_%(name)s, &%(name)s);\n' - ' if (parse_result != GST_RTSP_OK) {\n' - ' PyErr_SetString(PyExc_TypeError, "invalid url");\n' - ' return NULL;\n' - ' }') - beforenull = (' if (py_%(name)s == NULL)\n' - ' %(name)s = NULL;\n' - ' else\n' - ' ' + before) - after = (' if (%(name)s)\n' - ' gst_rtsp_url_free (%(name)s);\n') - - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if ptype in ('const-GstRTSPUrl*', 'GstRTSPUrl*'): - self.write_normal_param(pname, pdflt, pnull, info) - else: - raise RuntimeError, "write_param not implemented for %s" % ptype - - def write_normal_param(self, pname, pdflt, pnull, info): - info.varlist.add('GstRTSPResult', 'parse_result') - if pdflt: - assert pdflt == 'NULL' - info.varlist.add('const char', '*py_' + pname + ' = NULL') - else: - info.varlist.add('const char', '*py_' + pname) - info.varlist.add('GstRTSPUrl', '*'+pname) - info.add_parselist('s', ['&py_'+pname], [pname]) - info.arglist.append(pname) - if pnull: - info.codebefore.append (self.beforenull % { 'name' : pname }) - else: - info.codebefore.append (self.before % { 'name' : pname }) - info.codeafter.append (self.after % { 'name' : pname }) - - def write_return(self, ptype, ownsreturn, info): - if ptype == 'GstRTSPUrl*': - info.varlist.add('GstRTSPUrl', '*ret') - copyval = 'FALSE' - elif ptype == 'const-GstRTSPUrl*': - info.varlist.add('const GstRTSPUrl', '*ret') - copyval = 'TRUE' - else: - raise RuntimeError, "write_return not implemented for %s" % ptype - info.codeafter.append(' return pyg_boxed_new (GST_TYPE_RTSP_URL, ret, '+copyval+', TRUE);') - -class GstMiniObjectParam(Parameter): - - def get_c_type(self): - return self.props.get('c_type', 'GstMiniObject *') - - def convert_c2py(self): - self.wrapper.add_declaration("PyObject *py_%s = NULL;" % self.name) - self.wrapper.write_code(code=("if (%s) {\n" - " py_%s = pygstminiobject_new((GstMiniObject *) %s);\n" - " gst_mini_object_unref ((GstMiniObject *) %s);\n" - "} else {\n" - " Py_INCREF(Py_None);\n" - " py_%s = Py_None;\n" - "}" - % (self.name, self.name, self.name, self.name, self.name)), - cleanup=("gst_mini_object_ref ((GstMiniObject *) %s);\nPy_DECREF(py_%s);" % (self.name, self.name))) - self.wrapper.add_pyargv_item("py_%s" % self.name) - -matcher.register_reverse('GstMiniObject*', GstMiniObjectParam) - -class GstRTSPUrlParam(Parameter): - - def get_c_type(self): - c_type = self.props.get('c_type', None) - if c_type and c_type.startswith('const'): - return 'const GstRTSPUrl *' - return 'GstRTSPUrl *' - - def convert_c2py(self): - self.wrapper.add_declaration("char *%s_str = NULL;" % self.name) - self.wrapper.add_declaration("PyObject *py_%s = NULL;" % self.name) - self.wrapper.write_code(code=("if (%(name)s) {\n" - " %(name)s_str = gst_rtsp_url_get_request_uri ((GstRTSPUrl*) %(name)s);\n" - " py_%(name)s = PyString_FromString (%(name)s_str);\n" - " g_free (%(name)s_str);\n" - "} else {\n" - " Py_INCREF(Py_None);\n" - " py_%(name)s = Py_None;\n" - "}" % {'name': self.name}), - cleanup=("Py_DECREF(py_%s);" % self.name)) - self.wrapper.add_pyargv_item("py_%s" % self.name) - -matcher.register_reverse('const-GstRTSPUrl*', GstRTSPUrlParam) -matcher.register_reverse('GstRTSPUrl*', GstRTSPUrlParam) - -class GstMiniObjectReturn(ReturnType): - - def get_c_type(self): - return self.props.get('c_type', 'GstMiniObject *') - - def write_decl(self): - self.wrapper.add_declaration("%s retval;" % self.get_c_type()) - - def write_error_return(self): - self.wrapper.write_code("return NULL;") - - def write_conversion(self): - self.wrapper.write_code("retval = (%s) pygstminiobject_get(py_retval);" - % self.get_c_type()) - self.wrapper.write_code("gst_mini_object_ref((GstMiniObject *) retval);") - -matcher.register_reverse_ret('GstMiniObject*', GstMiniObjectReturn) - -class GstCapsParam(Parameter): - - def get_c_type(self): - return self.props.get('c_type', 'GstCaps *') - - def convert_c2py(self): - self.wrapper.add_declaration("PyObject *py_%s = NULL;" % self.name) - self.wrapper.write_code(code=("if (%s)\n" - " py_%s = pyg_boxed_new (GST_TYPE_CAPS, %s, FALSE, TRUE);\n" - "else {\n" - " Py_INCREF(Py_None);\n" - " py_%s = Py_None;\n" - "}" - % (self.name, self.name, self.name, self.name)), - cleanup=("gst_caps_ref(%s);\nPy_DECREF(py_%s);" % (self.name, self.name))) - self.wrapper.add_pyargv_item("py_%s" % self.name) - -matcher.register_reverse('GstCaps*', GstCapsParam) - -class GstCapsReturn(ReturnType): - - def get_c_type(self): - return self.props.get('c_type', 'GstCaps *') - - def write_decl(self): - self.wrapper.add_declaration("%s retval;" % self.get_c_type()) - - def write_error_return(self): - self.wrapper.write_code("return NULL;") - - def write_conversion(self): - self.wrapper.write_code("retval = (%s) pygst_caps_from_pyobject (py_retval, NULL);" - % self.get_c_type()) -## self.wrapper.write_code("gst_mini_object_ref((GstMiniObject *) retval);") - -matcher.register_reverse_ret('GstCaps*', GstCapsReturn) - - -class Int64Param(Parameter): - - def get_c_type(self): - return self.props.get('c_type', 'gint64') - - def convert_c2py(self): - self.wrapper.add_declaration("PyObject *py_%s;" % self.name) - self.wrapper.write_code(code=("py_%s = PyLong_FromLongLong(%s);" % - (self.name, self.name)), - cleanup=("Py_DECREF(py_%s);" % self.name)) - self.wrapper.add_pyargv_item("py_%s" % self.name) - -class Int64Return(ReturnType): - def get_c_type(self): - return self.props.get('c_type', 'gint64') - def write_decl(self): - self.wrapper.add_declaration("%s retval;" % self.get_c_type()) - def write_error_return(self): - self.wrapper.write_code("return -G_MAXINT;") - def write_conversion(self): - self.wrapper.write_code( - code=None, - failure_expression="!PyLong_Check(py_retval)", - failure_cleanup='PyErr_SetString(PyExc_TypeError, "retval should be an long");') - self.wrapper.write_code("retval = PyLong_AsLongLong(py_retval);") - -class UInt64Param(Parameter): - - def get_c_type(self): - return self.props.get('c_type', 'guint64') - - def convert_c2py(self): - self.wrapper.add_declaration("PyObject *py_%s;" % self.name) - self.wrapper.write_code(code=("py_%s = PyLong_FromUnsignedLongLong(%s);" % - (self.name, self.name)), - cleanup=("Py_DECREF(py_%s);" % self.name)) - self.wrapper.add_pyargv_item("py_%s" % self.name) - -class UInt64Return(ReturnType): - def get_c_type(self): - return self.props.get('c_type', 'guint64') - def write_decl(self): - self.wrapper.add_declaration("%s retval;" % self.get_c_type()) - def write_error_return(self): - self.wrapper.write_code("return -G_MAXINT;") - def write_conversion(self): - self.wrapper.write_code( - code=None, - failure_expression="!PyLong_Check(py_retval)", - failure_cleanup='PyErr_SetString(PyExc_TypeError, "retval should be an long");') - self.wrapper.write_code("retval = PyLong_AsUnsignedLongLongMask(py_retval);") - -class ULongParam(Parameter): - - def get_c_type(self): - return self.props.get('c_type', 'gulong') - - def convert_c2py(self): - self.wrapper.add_declaration("PyObject *py_%s;" % self.name) - self.wrapper.write_code(code=("py_%s = PyLong_FromUnsignedLong(%s);" % - (self.name, self.name)), - cleanup=("Py_DECREF(py_%s);" % self.name)) - self.wrapper.add_pyargv_item("py_%s" % self.name) - -class ULongReturn(ReturnType): - def get_c_type(self): - return self.props.get('c_type', 'gulong') - def write_decl(self): - self.wrapper.add_declaration("%s retval;" % self.get_c_type()) - def write_error_return(self): - self.wrapper.write_code("return -G_MAXINT;") - def write_conversion(self): - self.wrapper.write_code( - code=None, - failure_expression="!PyLong_Check(py_retval)", - failure_cleanup='PyErr_SetString(PyExc_TypeError, "retval should be an long");') - self.wrapper.write_code("retval = PyLong_AsUnsignedLongMask(py_retval);") - -class ConstStringReturn(ReturnType): - - def get_c_type(self): - return "const gchar *" - - def write_decl(self): - self.wrapper.add_declaration("const gchar *retval;") - - def write_error_return(self): - self.wrapper.write_code("return NULL;") - - def write_conversion(self): - self.wrapper.write_code( - code=None, - failure_expression="!PyString_Check(py_retval)", - failure_cleanup='PyErr_SetString(PyExc_TypeError, "retval should be a string");') - self.wrapper.write_code("retval = g_strdup(PyString_AsString(py_retval));") - -class StringArrayArg(ArgType): - """Arg type for NULL-terminated string pointer arrays (GStrv, aka gchar**).""" - def write_return(self, ptype, ownsreturn, info): - if ownsreturn: - raise NotImplementedError () - else: - info.varlist.add("gchar", "**ret") - info.codeafter.append(" if (ret) {\n" - " guint size = g_strv_length(ret);\n" - " PyObject *py_ret = PyTuple_New(size);\n" - " gint i;\n" - " for (i = 0; i < size; i++)\n" - " PyTuple_SetItem(py_ret, i,\n" - " PyString_FromString(ret[i]));\n" - " return py_ret;\n" - " }\n" - " return PyTuple_New (0);\n") - -matcher.register('GstClockTime', UInt64Arg()) -matcher.register('GstClockTimeDiff', Int64Arg()) -matcher.register('xmlNodePtr', XmlNodeArg()) -matcher.register('xmlDocPtr', XmlDocArg()) -matcher.register('GstCaps', GstCapsArg()) #FIXME: does this work? -matcher.register('GstCaps*', GstCapsArg()) #FIXME: does this work? -matcher.register('const-GstCaps*', GstCapsArg()) -matcher.register('GstIterator*', GstIteratorArg()) -matcher.register('const-GstRTSPUrl*', GstRTSPUrlArg()) -matcher.register('GstRTSPUrl*', GstRTSPUrlArg()) - -arg = PointerArg('gpointer', 'G_TYPE_POINTER') -matcher.register('GstClockID', arg) - -for typename in ["GstPlugin", "GstStructure", "GstTagList", "GError", "GstDate", "GstSegment"]: - matcher.register_reverse(typename, GBoxedParam) - matcher.register_reverse_ret(typename, GBoxedReturn) - -for typename in ["GstBuffer*", "GstEvent*", "GstMessage*", "GstQuery*"]: - matcher.register_reverse(typename, GstMiniObjectParam) - matcher.register_reverse_ret(typename, GstMiniObjectReturn) - -for typename in ["gint64", "GstClockTimeDiff"]: - matcher.register_reverse(typename, Int64Param) - matcher.register_reverse_ret(typename, Int64Return) - -for typename in ["guint64", "GstClockTime"]: - matcher.register_reverse(typename, UInt64Param) - matcher.register_reverse_ret(typename, UInt64Return) - -matcher.register_reverse_ret("const-gchar*", ConstStringReturn) - -matcher.register_reverse("GType", IntParam) -matcher.register_reverse_ret("GType", IntReturn) - -matcher.register_reverse("gulong", ULongParam) -matcher.register_reverse_ret("gulong", ULongReturn) - -matcher.register("GStrv", StringArrayArg()) - -del arg diff --git a/bindings/python/codegen/Makefile.am b/bindings/python/codegen/Makefile.am deleted file mode 100644 index dd3eea0..0000000 --- a/bindings/python/codegen/Makefile.am +++ /dev/null @@ -1,15 +0,0 @@ -EXTRA_DIST = \ - argtypes.py \ - code-coverage.py \ - codegen.py \ - definitions.py \ - defsparser.py \ - docextract.py \ - docgen.py \ - h2def.py \ - __init__.py \ - mergedefs.py \ - mkskel.py \ - override.py \ - reversewrapper.py \ - scmexpr.py diff --git a/bindings/python/codegen/__init__.py b/bindings/python/codegen/__init__.py deleted file mode 100644 index cfa896e..0000000 --- a/bindings/python/codegen/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# -*- Mode: Python; py-indent-offset: 4 -*- - -__all__ = [ - 'argtypes', - 'codegen', - 'definitions', - 'defsparser', - 'docextract', - 'docgen', - 'h2def', - 'mergedefs', - 'mkskel', - 'override', - 'scmexpr' -] diff --git a/bindings/python/codegen/argtypes.py b/bindings/python/codegen/argtypes.py deleted file mode 100644 index 948bae1..0000000 --- a/bindings/python/codegen/argtypes.py +++ /dev/null @@ -1,1075 +0,0 @@ -# -*- Mode: Python; py-indent-offset: 4 -*- -import string -import keyword -import struct - -class VarList: - """Nicely format a C variable list""" - def __init__(self): - self.vars = {} - def add(self, ctype, name): - if self.vars.has_key(ctype): - self.vars[ctype] = self.vars[ctype] + (name,) - else: - self.vars[ctype] = (name,) - def __str__(self): - ret = [] - for type in self.vars.keys(): - ret.append(' ') - ret.append(type) - ret.append(' ') - ret.append(string.join(self.vars[type], ', ')) - ret.append(';\n') - if ret: - ret.append('\n') - return string.join(ret, '') - return '' - -class WrapperInfo: - """A class that holds information about variable defs, code - snippets, etcd for use in writing out the function/method - wrapper.""" - def __init__(self): - self.varlist = VarList() - self.parsestr = '' - self.parselist = ['', 'kwlist'] - self.codebefore = [] - self.codeafter = [] - self.arglist = [] - self.kwlist = [] - def get_parselist(self): - return string.join(self.parselist, ', ') - def get_codebefore(self): - return string.join(self.codebefore, '') - def get_codeafter(self): - return string.join(self.codeafter, '') - def get_arglist(self): - return string.join(self.arglist, ', ') - def get_varlist(self): - return str(self.varlist) - def get_kwlist(self): - ret = ' static char *kwlist[] = { %s };\n' % \ - string.join(self.kwlist + [ 'NULL' ], ', ') - if not self.get_varlist(): - ret = ret + '\n' - return ret - - def add_parselist(self, codes, parseargs, keywords): - self.parsestr = self.parsestr + codes - for arg in parseargs: - self.parselist.append(arg) - for kw in keywords: - if keyword.iskeyword(kw): - kw = kw + '_' - self.kwlist.append('"%s"' % kw) - -class ArgType: - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - """Add code to the WrapperInfo instance to handle - parameter.""" - raise RuntimeError, "write_param not implemented for %s" % \ - self.__class__.__name__ - def write_return(self, ptype, ownsreturn, info): - """Adds a variable named ret of the return type to - info.varlist, and add any required code to info.codeafter to - convert the return value to a python object.""" - raise RuntimeError, "write_return not implemented for %s" % \ - self.__class__.__name__ - -class NoneArg(ArgType): - def write_return(self, ptype, ownsreturn, info): - info.codeafter.append(' Py_INCREF(Py_None);\n' + - ' return Py_None;') - -class StringArg(ArgType): - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - if pdflt != 'NULL': pdflt = '"' + pdflt + '"' - info.varlist.add('char', '*' + pname + ' = ' + pdflt) - else: - info.varlist.add('char', '*' + pname) - info.arglist.append(pname) - if pnull: - info.add_parselist('z', ['&' + pname], [pname]) - else: - info.add_parselist('s', ['&' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - if ownsreturn: - # have to free result ... - info.varlist.add('gchar', '*ret') - info.codeafter.append(' if (ret) {\n' + - ' PyObject *py_ret = PyString_FromString(ret);\n' + - ' g_free(ret);\n' + - ' return py_ret;\n' + - ' }\n' + - ' Py_INCREF(Py_None);\n' + - ' return Py_None;') - else: - info.varlist.add('const gchar', '*ret') - info.codeafter.append(' if (ret)\n' + - ' return PyString_FromString(ret);\n'+ - ' Py_INCREF(Py_None);\n' + - ' return Py_None;') - -class UCharArg(ArgType): - # allows strings with embedded NULLs. - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add('guchar', '*' + pname + ' = "' + pdflt + '"') - else: - info.varlist.add('guchar', '*' + pname) - info.varlist.add('int', pname + '_len') - info.arglist.append(pname) - if pnull: - info.add_parselist('z#', ['&' + pname, '&' + pname + '_len'], - [pname]) - else: - info.add_parselist('s#', ['&' + pname, '&' + pname + '_len'], - [pname]) - -class CharArg(ArgType): - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add('char', pname + " = '" + pdflt + "'") - else: - info.varlist.add('char', pname) - info.arglist.append(pname) - info.add_parselist('c', ['&' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add('gchar', 'ret') - info.codeafter.append(' return PyString_FromStringAndSize(&ret, 1);') -class GUniCharArg(ArgType): - ret_tmpl = ('#if !defined(Py_UNICODE_SIZE) || Py_UNICODE_SIZE == 2\n' - ' if (ret > 0xffff) {\n' - ' PyErr_SetString(PyExc_RuntimeError, "returned character can not be represented in 16-bit unicode");\n' - ' return NULL;\n' - ' }\n' - '#endif\n' - ' py_ret = (Py_UNICODE)ret;\n' - ' return PyUnicode_FromUnicode(&py_ret, 1);\n') - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add('gunichar', pname + " = '" + pdflt + "'") - else: - info.varlist.add('gunichar', pname) - info.arglist.append(pname) - info.add_parselist('O&', ['pyg_pyobj_to_unichar_conv', '&' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add('gunichar', 'ret') - info.varlist.add('Py_UNICODE', 'py_ret') - info.codeafter.append(self.ret_tmpl) - - -class IntArg(ArgType): - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add('int', pname + ' = ' + pdflt) - else: - info.varlist.add('int', pname) - info.arglist.append(pname) - info.add_parselist('i', ['&' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add('int', 'ret') - info.codeafter.append(' return PyInt_FromLong(ret);') - -class UIntArg(ArgType): - dflt = (' if (py_%(name)s) {\n' - ' if (PyLong_Check(py_%(name)s))\n' - ' %(name)s = PyLong_AsUnsignedLong(py_%(name)s);\n' - ' else if (PyInt_Check(py_%(name)s))\n' - ' %(name)s = PyInt_AsLong(py_%(name)s);\n' - ' else\n' - ' PyErr_SetString(PyExc_TypeError, "Parameter \'%(name)s\' must be an int or a long");\n' - ' if (PyErr_Occurred())\n' - ' return NULL;\n' - ' }\n') - before = (' if (PyLong_Check(py_%(name)s))\n' - ' %(name)s = PyLong_AsUnsignedLong(py_%(name)s);\n' - ' else if (PyInt_Check(py_%(name)s))\n' - ' %(name)s = PyInt_AsLong(py_%(name)s);\n' - ' else\n' - ' PyErr_SetString(PyExc_TypeError, "Parameter \'%(name)s\' must be an int or a long");\n' - ' if (PyErr_Occurred())\n' - ' return NULL;\n') - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if not pdflt: - pdflt = '0'; - - info.varlist.add(ptype, pname + ' = ' + pdflt) - info.codebefore.append(self.dflt % {'name':pname}) - info.varlist.add('PyObject', "*py_" + pname + ' = NULL') - info.arglist.append(pname) - info.add_parselist('O', ['&py_' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add(ptype, 'ret') - info.codeafter.append(' return PyLong_FromUnsignedLong(ret);') - -class SizeArg(ArgType): - - if struct.calcsize('P') <= struct.calcsize('l'): - llp64 = True - else: - llp64 = False - - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add(ptype, pname + ' = ' + pdflt) - else: - info.varlist.add(ptype, pname) - info.arglist.append(pname) - if self.llp64: - info.add_parselist('k', ['&' + pname], [pname]) - else: - info.add_parselist('K', ['&' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add(ptype, 'ret') - if self.llp64: - info.codeafter.append(' return PyLong_FromUnsignedLongLong(ret);\n') - else: - info.codeafter.append(' return PyLong_FromUnsignedLong(ret);\n') - -class SSizeArg(ArgType): - - if struct.calcsize('P') <= struct.calcsize('l'): - llp64 = True - else: - llp64 = False - - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add(ptype, pname + ' = ' + pdflt) - else: - info.varlist.add(ptype, pname) - info.arglist.append(pname) - if self.llp64: - info.add_parselist('l', ['&' + pname], [pname]) - else: - info.add_parselist('L', ['&' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add(ptype, 'ret') - if self.llp64: - info.codeafter.append(' return PyLong_FromLongLong(ret);\n') - else: - info.codeafter.append(' return PyLong_FromLong(ret);\n') - -class LongArg(ArgType): - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add(ptype, pname + ' = ' + pdflt) - else: - info.varlist.add(ptype, pname) - info.arglist.append(pname) - info.add_parselist('l', ['&' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add(ptype, 'ret') - info.codeafter.append(' return PyInt_FromLong(ret);\n') - -class BoolArg(IntArg): - def write_return(self, ptype, ownsreturn, info): - info.varlist.add('int', 'ret') - info.codeafter.append(' return PyBool_FromLong(ret);\n') - -class TimeTArg(ArgType): - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add('time_t', pname + ' = ' + pdflt) - else: - info.varlist.add('time_t', pname) - info.arglist.append(pname) - info.add_parselist('i', ['&' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add('time_t', 'ret') - info.codeafter.append(' return PyInt_FromLong(ret);') - -class ULongArg(ArgType): - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add('unsigned long', pname + ' = ' + pdflt) - else: - info.varlist.add('unsigned long', pname) - info.arglist.append(pname) - info.add_parselist('k', ['&' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add(ptype, 'ret') - info.codeafter.append(' return PyLong_FromUnsignedLong(ret);\n') - -class UInt32Arg(ULongArg): - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - ULongArg.write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info) - ## if sizeof(unsigned long) > sizeof(unsigned int), we need to - ## check the value is within guint32 range - if struct.calcsize('L') > struct.calcsize('I'): - info.codebefore.append(( - ' if (%(pname)s > G_MAXUINT32) {\n' - ' PyErr_SetString(PyExc_ValueError,\n' - ' "Value out of range in conversion of"\n' - ' " %(pname)s parameter to unsigned 32 bit integer");\n' - ' return NULL;\n' - ' }\n') % vars()) - -class Int64Arg(ArgType): - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add('gint64', pname + ' = ' + pdflt) - else: - info.varlist.add('gint64', pname) - info.arglist.append(pname) - info.add_parselist('L', ['&' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add('gint64', 'ret') - info.codeafter.append(' return PyLong_FromLongLong(ret);') - -class UInt64Arg(ArgType): - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add('guint64', pname + ' = ' + pdflt) - else: - info.varlist.add('guint64', pname) - info.arglist.append(pname) - info.add_parselist('K', ['&' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add('guint64', 'ret') - info.codeafter.append(' return PyLong_FromUnsignedLongLong(ret);') - - -class DoubleArg(ArgType): - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add('double', pname + ' = ' + pdflt) - else: - info.varlist.add('double', pname) - info.arglist.append(pname) - info.add_parselist('d', ['&' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add('double', 'ret') - info.codeafter.append(' return PyFloat_FromDouble(ret);') - -class FileArg(ArgType): - nulldflt = (' if (py_%(name)s == Py_None)\n' - ' %(name)s = NULL;\n' - ' else if (py_%(name)s && PyFile_Check(py_%(name)s)\n' - ' %s = PyFile_AsFile(py_%(name)s);\n' - ' else if (py_%(name)s) {\n' - ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a file object or None");\n' - ' return NULL;\n' - ' }') - null = (' if (py_%(name)s && PyFile_Check(py_%(name)s)\n' - ' %(name)s = PyFile_AsFile(py_%(name)s);\n' - ' else if (py_%(name)s != Py_None) {\n' - ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a file object or None");\n' - ' return NULL;\n' - ' }\n') - dflt = (' if (py_%(name)s)\n' - ' %(name)s = PyFile_AsFile(py_%(name)s);\n') - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pnull: - if pdflt: - info.varlist.add('FILE', '*' + pname + ' = ' + pdflt) - info.varlist.add('PyObject', '*py_' + pname + ' = NULL') - info.codebefore.append(self.nulldflt % {'name':pname}) - else: - info.varlist.add('FILE', '*' + pname + ' = NULL') - info.varlist.add('PyObject', '*py_' + pname) - info.codebefore.append(self.null & {'name':pname}) - info.arglist.appned(pname) - info.add_parselist('O', ['&py_' + pname], [pname]) - else: - if pdflt: - info.varlist.add('FILE', '*' + pname + ' = ' + pdflt) - info.varlist.add('PyObject', '*py_' + pname + ' = NULL') - info.codebefore.append(self.dflt % {'name':pname}) - info.arglist.append(pname) - else: - info.varlist.add('PyObject', '*' + pname) - info.arglist.append('PyFile_AsFile(' + pname + ')') - info.add_parselist('O!', ['&PyFile_Type', '&' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add('FILE', '*ret') - info.codeafter.append(' if (ret)\n' + - ' return PyFile_FromFile(ret, "", "", fclose);\n' + - ' Py_INCREF(Py_None);\n' + - ' return Py_None;') - -class EnumArg(ArgType): - enum = (' if (pyg_enum_get_value(%(typecode)s, py_%(name)s, (gint *)&%(name)s))\n' - ' return NULL;\n') - def __init__(self, enumname, typecode): - self.enumname = enumname - self.typecode = typecode - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add(self.enumname, pname + ' = ' + pdflt) - else: - info.varlist.add(self.enumname, pname) - info.varlist.add('PyObject', '*py_' + pname + ' = NULL') - info.codebefore.append(self.enum % { 'typecode': self.typecode, - 'name': pname}) - info.arglist.append(pname) - info.add_parselist('O', ['&py_' + pname], [pname]); - def write_return(self, ptype, ownsreturn, info): - info.varlist.add('gint', 'ret') - info.codeafter.append(' return pyg_enum_from_gtype(%s, ret);' % self.typecode) - -class FlagsArg(ArgType): - flag = (' if (%(default)spyg_flags_get_value(%(typecode)s, py_%(name)s, (gint *)&%(name)s))\n' - ' return NULL;\n') - def __init__(self, flagname, typecode): - self.flagname = flagname - self.typecode = typecode - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add(self.flagname, pname + ' = ' + pdflt) - default = "py_%s && " % (pname,) - else: - info.varlist.add(self.flagname, pname) - default = "" - info.varlist.add('PyObject', '*py_' + pname + ' = NULL') - info.codebefore.append(self.flag % {'default':default, - 'typecode':self.typecode, - 'name':pname}) - info.arglist.append(pname) - info.add_parselist('O', ['&py_' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add('guint', 'ret') - info.codeafter.append(' return pyg_flags_from_gtype(%s, ret);' % self.typecode) - -class ObjectArg(ArgType): - # should change these checks to more typesafe versions that check - # a little further down in the class heirachy. - nulldflt = (' if ((PyObject *)py_%(name)s == Py_None)\n' - ' %(name)s = NULL;\n' - ' else if (py_%(name)s && pygobject_check(py_%(name)s, &Py%(type)s_Type))\n' - ' %(name)s = %(cast)s(py_%(name)s->obj);\n' - ' else if (py_%(name)s) {\n' - ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(type)s or None");\n' - ' return NULL;\n' - ' }\n') - null = (' if (py_%(name)s && pygobject_check(py_%(name)s, &Py%(type)s_Type))\n' - ' %(name)s = %(cast)s(py_%(name)s->obj);\n' - ' else if ((PyObject *)py_%(name)s != Py_None) {\n' - ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(type)s or None");\n' - ' return NULL;\n' - ' }\n') - dflt = ' if (py_%(name)s)\n' \ - ' %(name)s = %(cast)s(py_%(name)s->obj);\n' - def __init__(self, objname, parent, typecode): - self.objname = objname - self.cast = string.replace(typecode, '_TYPE_', '_', 1) - self.parent = parent - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pnull: - if pdflt: - info.varlist.add(self.objname, '*' + pname + ' = ' + pdflt) - info.varlist.add('PyGObject', '*py_' + pname + ' = NULL') - info.codebefore.append(self.nulldflt % {'name':pname, - 'cast':self.cast, - 'type':self.objname}) - else: - info.varlist.add(self.objname, '*' + pname + ' = NULL') - info.varlist.add('PyGObject', '*py_' + pname) - info.codebefore.append(self.null % {'name':pname, - 'cast':self.cast, - 'type':self.objname}) - if ptype.endswith('*'): - typename = ptype[:-1] - try: - const, typename = typename.split('const-') - except ValueError: - const = '' - if typename != ptype: - info.arglist.append('(%s *) %s' % (ptype[:-1], pname)) - else: - info.arglist.append(pname) - - info.add_parselist('O', ['&py_' + pname], [pname]) - else: - if pdflt: - info.varlist.add(self.objname, '*' + pname + ' = ' + pdflt) - info.varlist.add('PyGObject', '*py_' + pname + ' = NULL') - info.codebefore.append(self.dflt % {'name':pname, - 'cast':self.cast}) - info.arglist.append(pname) - info.add_parselist('O!', ['&Py%s_Type' % self.objname, - '&py_' + pname], [pname]) - else: - info.varlist.add('PyGObject', '*' + pname) - info.arglist.append('%s(%s->obj)' % (self.cast, pname)) - info.add_parselist('O!', ['&Py%s_Type' % self.objname, - '&' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - if ptype.endswith('*'): - typename = ptype[:-1] - try: - const, typename = typename.split('const-') - except ValueError: - const = '' - info.varlist.add(typename, '*ret') - if ownsreturn: - info.varlist.add('PyObject', '*py_ret') - # < GLib 2.8: using our custom _new and _unref functions - # makes sure we update the proper GstObject refcount - info.codeafter.append(' py_ret = pygobject_new((GObject *)ret);\n' - ' if (ret != NULL)\n' - ' g_object_unref((GObject *)ret);\n' - ' return py_ret;') - else: - info.codeafter.append(' /* pygobject_new handles NULL checking */\n' + - ' return pygobject_new((GObject *)ret);') - -class MiniObjectArg(ArgType): - # should change these checks to more typesafe versions that check - # a little further down in the class heirachy. - nulldflt = (' if ((PyObject *)py_%(name)s == Py_None)\n' - ' %(name)s = NULL;\n' - ' else if (py_%(name)s) && pygstminiobject_check(py_%(name)s, &Py%(type)s_Type))\n' - ' %(name)s = %(cast)s(py_%(name)s->obj);\n' - ' else if (py_%(name)s) {\n' - ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(type)s or None");\n' - ' return NULL;\n' - ' }\n') - null = (' if (py_%(name)s && pygstminiobject_check(py_%(name)s, &Py%(type)s_Type))\n' - ' %(name)s = %(cast)s(py_%(name)s->obj);\n' - ' else if ((PyObject *)py_%(name)s != Py_None) {\n' - ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(type)s or None");\n' - ' return NULL;\n' - ' }\n') - dflt = ' if (py_%(name)s)\n' \ - ' %(name)s = %(cast)s(py_%(name)s->obj);\n' - def __init__(self, objname, parent, typecode): - self.objname = objname - self.cast = string.replace(typecode, '_TYPE_', '_', 1) - self.parent = parent - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pnull: - if pdflt: - info.varlist.add(self.objname, '*' + pname + ' = ' + pdflt) - info.varlist.add('PyGstMiniObject', '*py_' + pname + ' = NULL') - info.codebefore.append(self.nulldflt % {'name':pname, - 'cast':self.cast, - 'type':self.objname}) - else: - info.varlist.add(self.objname, '*' + pname + ' = NULL') - info.varlist.add('PyGstMiniObject', '*py_' + pname) - info.codebefore.append(self.null % {'name':pname, - 'cast':self.cast, - 'type':self.objname}) - if ptype.endswith('*'): - typename = ptype[:-1] - try: - const, typename = typename.split('const-') - except ValueError: - const = '' - if typename != ptype: - info.arglist.append('(%s *) %s' % (ptype[:-1], pname)) - else: - info.arglist.append(pname) - - info.add_parselist('O', ['&py_' + pname], [pname]) - else: - if pdflt: - info.varlist.add(self.objname, '*' + pname + ' = ' + pdflt) - info.varlist.add('PyGstMiniObject', '*py_' + pname + ' = NULL') - info.codebefore.append(self.dflt % {'name':pname, - 'cast':self.cast}) - info.arglist.append(pname) - info.add_parselist('O', ['&Py%s_Type' % self.objname, - '&py_' + pname], [pname]) - else: - info.varlist.add('PyGstMiniObject', '*' + pname) - info.arglist.append('%s(%s->obj)' % (self.cast, pname)) - info.add_parselist('O!', ['&Py%s_Type' % self.objname, - '&' + pname], [pname]) - if keeprefcount: - info.codebefore.append(' gst_mini_object_ref(GST_MINI_OBJECT(%s->obj));\n' % pname) - def write_return(self, ptype, ownsreturn, info): - if ptype.endswith('*'): - typename = ptype[:-1] - try: - const, typename = typename.split('const-') - except ValueError: - const = '' - info.varlist.add(typename, '*ret') - if ownsreturn: - info.varlist.add('PyObject', '*py_ret') - info.codeafter.append(' py_ret = pygstminiobject_new((GstMiniObject *)ret);\n' - ' if (ret != NULL)\n' - ' gst_mini_object_unref((GstMiniObject *)ret);\n' - ' return py_ret;') - else: - info.codeafter.append(' /* pygobject_new handles NULL checking */\n' + - ' return pygstminiobject_new((GstMiniObject *)ret);') - -class BoxedArg(ArgType): - # haven't done support for default args. Is it needed? - check = (' if (pyg_boxed_check(py_%(name)s, %(typecode)s))\n' - ' %(name)s = pyg_boxed_get(py_%(name)s, %(typename)s);\n' - ' else {\n' - ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s");\n' - ' return NULL;\n' - ' }\n') - null = (' if (pyg_boxed_check(py_%(name)s, %(typecode)s))\n' - ' %(name)s = pyg_boxed_get(py_%(name)s, %(typename)s);\n' - ' else if (py_%(name)s != Py_None) {\n' - ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s or None");\n' - ' return NULL;\n' - ' }\n') - def __init__(self, ptype, typecode): - self.typename = ptype - self.typecode = typecode - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pnull: - info.varlist.add(self.typename, '*' + pname + ' = NULL') - info.varlist.add('PyObject', '*py_' + pname + ' = Py_None') - info.codebefore.append(self.null % {'name': pname, - 'typename': self.typename, - 'typecode': self.typecode}) - else: - info.varlist.add(self.typename, '*' + pname + ' = NULL') - info.varlist.add('PyObject', '*py_' + pname) - info.codebefore.append(self.check % {'name': pname, - 'typename': self.typename, - 'typecode': self.typecode}) - if ptype[-1] == '*': - typename = ptype[:-1] - if typename[:6] == 'const-': typename = typename[6:] - if typename != self.typename: - info.arglist.append('(%s *)%s' % (ptype[:-1], pname)) - else: - info.arglist.append(pname) - else: - info.arglist.append(pname) - info.add_parselist('O', ['&py_' + pname], [pname]) - ret_tmpl = ' /* pyg_boxed_new handles NULL checking */\n' \ - ' return pyg_boxed_new(%(typecode)s, %(ret)s, %(copy)s, TRUE);' - def write_return(self, ptype, ownsreturn, info): - if ptype[-1] == '*': - info.varlist.add(self.typename, '*ret') - ret = 'ret' - else: - info.varlist.add(self.typename, 'ret') - ret = '&ret' - ownsreturn = 0 # of course it can't own a ref to a local var ... - info.codeafter.append(self.ret_tmpl % - { 'typecode': self.typecode, - 'ret': ret, - 'copy': ownsreturn and 'FALSE' or 'TRUE'}) - -class CustomBoxedArg(ArgType): - # haven't done support for default args. Is it needed? - null = (' if (%(check)s(py_%(name)s))\n' - ' %(name)s = %(get)s(py_%(name)s);\n' - ' else if (py_%(name)s != Py_None) {\n' - ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(type)s or None");\n' - ' return NULL;\n' - ' }\n') - def __init__(self, ptype, pytype, getter, new): - self.pytype = pytype - self.getter = getter - self.checker = 'Py' + ptype + '_Check' - self.new = new - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pnull: - info.varlist.add(ptype[:-1], '*' + pname + ' = NULL') - info.varlist.add('PyObject', '*py_' + pname + ' = Py_None') - info.codebefore.append(self.null % {'name': pname, - 'get': self.getter, - 'check': self.checker, - 'type': ptype[:-1]}) - info.arglist.append(pname) - info.add_parselist('O', ['&py_' + pname], [pname]) - else: - info.varlist.add('PyObject', '*' + pname) - info.arglist.append(self.getter + '(' + pname + ')') - info.add_parselist('O!', ['&' + self.pytype, '&' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add(ptype[:-1], '*ret') - info.codeafter.append(' if (ret)\n' + - ' return ' + self.new + '(ret);\n' + - ' Py_INCREF(Py_None);\n' + - ' return Py_None;') - -class PointerArg(ArgType): - # haven't done support for default args. Is it needed? - check = (' if (pyg_pointer_check(py_%(name)s, %(typecode)s))\n' - ' %(name)s = pyg_pointer_get(py_%(name)s, %(typename)s);\n' - ' else {\n' - ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s");\n' - ' return NULL;\n' - ' }\n') - null = (' if (pyg_pointer_check(py_%(name)s, %(typecode)s))\n' - ' %(name)s = pyg_pointer_get(py_%(name)s, %(typename)s);\n' - ' else if (py_%(name)s != Py_None) {\n' - ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s or None");\n' - ' return NULL;\n' - ' }\n') - def __init__(self, ptype, typecode): - self.typename = ptype - self.typecode = typecode - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pnull: - info.varlist.add(self.typename, '*' + pname + ' = NULL') - info.varlist.add('PyObject', '*py_' + pname + ' = Py_None') - info.codebefore.append(self.null % {'name': pname, - 'typename': self.typename, - 'typecode': self.typecode}) - else: - info.varlist.add(self.typename, '*' + pname + ' = NULL') - info.varlist.add('PyObject', '*py_' + pname) - info.codebefore.append(self.check % {'name': pname, - 'typename': self.typename, - 'typecode': self.typecode}) - info.arglist.append(pname) - info.add_parselist('O', ['&py_' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - if ptype[-1] == '*': - info.varlist.add(self.typename, '*ret') - info.codeafter.append(' /* pyg_pointer_new handles NULL checking */\n' + - ' return pyg_pointer_new(' + self.typecode + ', ret);') - else: - info.varlist.add(self.typename, 'ret') - info.codeafter.append(' /* pyg_pointer_new handles NULL checking */\n' + - ' return pyg_pointer_new(' + self.typecode + ', &ret);') - -class AtomArg(IntArg): - dflt = ' if (py_%(name)s) {\n' \ - ' %(name)s = pygdk_atom_from_pyobject(py_%(name)s);\n' \ - ' if (PyErr_Occurred())\n' \ - ' return NULL;\n' \ - ' }\n' - atom = (' %(name)s = pygdk_atom_from_pyobject(py_%(name)s);\n' - ' if (PyErr_Occurred())\n' - ' return NULL;\n') - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pdflt: - info.varlist.add('GdkAtom', pname + ' = ' + pdflt) - info.varlist.add('PyObject', '*py_' + pname + ' = NULL') - info.codebefore.append(self.dflt % {'name': pname}) - else: - info.varlist.add('GdkAtom', pname) - info.varlist.add('PyObject', '*py_' + pname + ' = NULL') - info.codebefore.append(self.atom % {'name': pname}) - info.arglist.append(pname) - info.add_parselist('O', ['&py_' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add('GdkAtom', 'ret') - info.varlist.add('PyObject *', 'py_ret') - info.varlist.add('gchar *', 'name') - info.codeafter.append(' name = gdk_atom_name(ret);\n' - ' py_ret = PyString_FromString(name);\n' - ' g_free(name);\n' - ' return py_ret;') - -class GTypeArg(ArgType): - gtype = (' if ((%(name)s = pyg_type_from_object(py_%(name)s)) == 0)\n' - ' return NULL;\n') - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - info.varlist.add('GType', pname) - info.varlist.add('PyObject', '*py_' + pname + ' = NULL') - info.codebefore.append(self.gtype % {'name': pname}) - info.arglist.append(pname) - info.add_parselist('O', ['&py_' + pname], [pname]) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add('GType', 'ret') - info.codeafter.append(' return pyg_type_wrapper_new(ret);') - -# simple GError handler. -class GErrorArg(ArgType): - handleerror = (' if (pyg_error_check(&%(name)s))\n' - ' return NULL;\n') - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - info.varlist.add('GError', '*' + pname + ' = NULL') - info.arglist.append('&' + pname) - info.codeafter.append(self.handleerror % { 'name': pname }) - -class GtkTreePathArg(ArgType): - # haven't done support for default args. Is it needed? - normal = (' %(name)s = pygtk_tree_path_from_pyobject(py_%(name)s);\n' - ' if (!%(name)s) {\n' - ' PyErr_SetString(PyExc_TypeError, "could not convert %(name)s to a GtkTreePath");\n' - ' return NULL;\n' - ' }\n') - null = (' if (py_%(name)s != Py_None) {\n' - ' %(name)s = pygtk_tree_path_from_pyobject(py_%(name)s);\n' - ' if (!%(name)s) {\n' - ' PyErr_SetString(PyExc_TypeError, "could not convert %(name)s to a GtkTreePath");\n' - ' return NULL;\n' - ' }\n' - ' }\n') - freepath = (' if (%(name)s)\n' - ' gtk_tree_path_free(%(name)s);\n') - def __init__(self): - pass - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pnull: - info.varlist.add('GtkTreePath', '*' + pname + ' = NULL') - info.varlist.add('PyObject', '*py_' + pname + ' = Py_None') - info.codebefore.append(self.null % {'name': pname}) - info.arglist.append(pname) - info.add_parselist('O', ['&py_' + pname], [pname]) - else: - info.varlist.add('GtkTreePath', '*' + pname) - info.varlist.add('PyObject', '*py_' + pname) - info.codebefore.append(self.normal % {'name': pname}) - info.arglist.append(pname) - info.add_parselist('O', ['&py_' + pname], [pname]) - info.codeafter.append(self.freepath % {'name': pname}) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add('GtkTreePath', '*ret') - if ownsreturn: - info.codeafter.append(' if (ret) {\n' - ' PyObject *py_ret = pygtk_tree_path_to_pyobject(ret);\n' - ' gtk_tree_path_free(ret);\n' - ' return py_ret;\n' - ' }\n' - ' Py_INCREF(Py_None);\n' - ' return Py_None;') - else: - info.codeafter.append(' if (ret) {\n' - ' PyObject *py_ret = pygtk_tree_path_to_pyobject(ret);\n' - ' return py_ret;\n' - ' }\n' - ' Py_INCREF(Py_None);\n' - ' return Py_None;') - -class GdkRectanglePtrArg(ArgType): - normal = (' if (!pygdk_rectangle_from_pyobject(py_%(name)s, &%(name)s))\n' - ' return NULL;\n') - null = (' if (py_%(name)s == Py_None)\n' - ' %(name)s = NULL;\n' - ' else if (pygdk_rectangle_from_pyobject(py_%(name)s, &%(name)s_rect))\n' - ' %(name)s = &%(name)s_rect;\n' - ' else\n' - ' return NULL;\n') - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - if pnull: - info.varlist.add('GdkRectangle', pname + '_rect = { 0, 0, 0, 0 }') - info.varlist.add('GdkRectangle', '*' + pname) - info.varlist.add('PyObject', '*py_' + pname + ' = Py_None') - info.add_parselist('O', ['&py_' + pname], [pname]) - info.arglist.append(pname) - info.codebefore.append(self.null % {'name': pname}) - else: - info.varlist.add('GdkRectangle', pname + ' = { 0, 0, 0, 0 }') - info.varlist.add('PyObject', '*py_' + pname) - info.add_parselist('O', ['&py_' + pname], [pname]) - info.arglist.append('&' + pname) - info.codebefore.append(self.normal % {'name': pname}) - -class GdkRectangleArg(ArgType): - def write_return(self, ptype, ownsreturn, info): - info.varlist.add('GdkRectangle', 'ret') - info.codeafter.append(' return pyg_boxed_new(GDK_TYPE_RECTANGLE, &ret, TRUE, TRUE);') - -class PyObjectArg(ArgType): - def write_param(self, ptype, pname, pdflt, pnull, keeprefcount, info): - info.varlist.add('PyObject', '*' + pname) - info.add_parselist('O', ['&' + pname], [pname]) - info.arglist.append(pname) - def write_return(self, ptype, ownsreturn, info): - info.varlist.add("PyObject", "*ret") - if ownsreturn: - info.codeafter.append(' if (ret) {\n' - ' return ret;\n' - ' }\n' - ' Py_INCREF(Py_None);\n' - ' return Py_None;') - else: - info.codeafter.append(' if (!ret) ret = Py_None;\n' - ' Py_INCREF(ret);\n' - ' return ret;') - -class ArgMatcher: - def __init__(self): - self.argtypes = {} - self.reverse_argtypes = {} - self.reverse_rettypes = {} - - def register(self, ptype, handler): - self.argtypes[ptype] = handler - def register_reverse(self, ptype, handler): - self.reverse_argtypes[ptype] = handler - def register_reverse_ret(self, ptype, handler): - self.reverse_rettypes[ptype] = handler - - def register_enum(self, ptype, typecode): - if typecode is None: - typecode = "G_TYPE_NONE" - self.register(ptype, EnumArg(ptype, typecode)) - def register_flag(self, ptype, typecode): - if typecode is None: - typecode = "G_TYPE_NONE" - self.register(ptype, FlagsArg(ptype, typecode)) - def register_object(self, ptype, parent, typecode): - oa = ObjectArg(ptype, parent, typecode) - self.register(ptype, oa) # in case I forget the * in the .defs - self.register(ptype+'*', oa) - self.register('const-'+ptype+'*', oa) - if ptype == 'GdkPixmap': - # hack to handle GdkBitmap synonym. - self.register('GdkBitmap', oa) - self.register('GdkBitmap*', oa) - def register_miniobject(self, ptype, parent, typecode): - oa = MiniObjectArg(ptype, parent, typecode) - self.register(ptype, oa) # in case I forget the * in the .defs - self.register(ptype+'*', oa) - def register_boxed(self, ptype, typecode): - if self.argtypes.has_key(ptype): return - arg = BoxedArg(ptype, typecode) - self.register(ptype, arg) - self.register(ptype+'*', arg) - self.register('const-'+ptype+'*', arg) - def register_custom_boxed(self, ptype, pytype, getter, new): - arg = CustomBoxedArg(ptype, pytype, getter, new) - self.register(ptype+'*', arg) - self.register('const-'+ptype+'*', arg) - def register_pointer(self, ptype, typecode): - arg = PointerArg(ptype, typecode) - self.register(ptype, arg) - self.register(ptype+'*', arg) - self.register('const-'+ptype+'*', arg) - - def get(self, ptype): - try: - return self.argtypes[ptype] - except KeyError: - if ptype[:8] == 'GdkEvent' and ptype[-1] == '*': - return self.argtypes['GdkEvent*'] - raise - def _get_reverse_common(self, ptype, registry): - props = dict(c_type=ptype) - try: - return registry[ptype], props - except KeyError: - try: - handler = self.argtypes[ptype] - except KeyError: - if ptype.startswith('GdkEvent') and ptype.endswith('*'): - handler = self.argtypes['GdkEvent*'] - else: - raise - if isinstance(handler, ObjectArg): - return registry['GObject*'], props - elif isinstance(handler, EnumArg): - props['typecode'] = handler.typecode - props['enumname'] = handler.enumname - return registry['GEnum'], props - elif isinstance(handler, FlagsArg): - props['typecode'] = handler.typecode - props['flagname'] = handler.flagname - return registry['GFlags'], props - elif isinstance(handler, BoxedArg): - props['typecode'] = handler.typecode - props['typename'] = handler.typename - return registry['GBoxed'], props - else: - raise - def get_reverse(self, ptype): - return self._get_reverse_common(ptype, self.reverse_argtypes) - def get_reverse_ret(self, ptype): - return self._get_reverse_common(ptype, self.reverse_rettypes) - - def object_is_a(self, otype, parent): - if otype == None: return 0 - if otype == parent: return 1 - if not self.argtypes.has_key(otype): return 0 - return self.object_is_a(self.get(otype).parent, parent) - -matcher = ArgMatcher() - -arg = NoneArg() -matcher.register(None, arg) -matcher.register('none', arg) - -arg = StringArg() -matcher.register('char*', arg) -matcher.register('gchar*', arg) -matcher.register('const-char*', arg) -matcher.register('char-const*', arg) -matcher.register('const-gchar*', arg) -matcher.register('gchar-const*', arg) -matcher.register('string', arg) -matcher.register('static_string', arg) - -arg = UCharArg() -matcher.register('unsigned-char*', arg) -matcher.register('const-guchar*', arg) -matcher.register('guchar*', arg) - -arg = CharArg() -matcher.register('char', arg) -matcher.register('gchar', arg) -matcher.register('guchar', arg) - -arg = GUniCharArg() -matcher.register('gunichar', arg) - -arg = IntArg() -matcher.register('int', arg) -matcher.register('gint', arg) -matcher.register('short', arg) -matcher.register('gshort', arg) -matcher.register('gushort', arg) -matcher.register('gsize', SizeArg()) -matcher.register('gssize', SSizeArg()) -matcher.register('guint8', arg) -matcher.register('gint8', arg) -matcher.register('guint16', arg) -matcher.register('gint16', arg) -matcher.register('gint32', arg) -matcher.register('GTime', arg) - -arg = LongArg() -matcher.register('long', arg) -matcher.register('glong', arg) - -arg = UIntArg() -matcher.register('guint', arg) - -arg = BoolArg() -matcher.register('gboolean', arg) - -arg = TimeTArg() -matcher.register('time_t', arg) - -matcher.register('guint32', UInt32Arg()) - -arg = ULongArg() -matcher.register('gulong', arg) - -arg = Int64Arg() -matcher.register('gint64', arg) -matcher.register('long-long', arg) - -arg = UInt64Arg() -matcher.register('guint64', arg) -matcher.register('unsigned-long-long', arg) - -arg = DoubleArg() -matcher.register('double', arg) -matcher.register('gdouble', arg) -matcher.register('float', arg) -matcher.register('gfloat', arg) - -arg = FileArg() -matcher.register('FILE*', arg) - -# enums, flags, objects - -matcher.register('GdkAtom', AtomArg()) - -matcher.register('GType', GTypeArg()) -matcher.register('GtkType', GTypeArg()) - -matcher.register('GError**', GErrorArg()) -matcher.register('GtkTreePath*', GtkTreePathArg()) -matcher.register('GdkRectangle*', GdkRectanglePtrArg()) -matcher.register('GtkAllocation*', GdkRectanglePtrArg()) -matcher.register('GdkRectangle', GdkRectangleArg()) -matcher.register('PyObject*', PyObjectArg()) - -matcher.register('GdkNativeWindow', ULongArg()) - -matcher.register_object('GObject', None, 'G_TYPE_OBJECT') -matcher.register_miniobject('GstMiniObject', None, 'GST_TYPE_MINI_OBJECT') - -del arg diff --git a/bindings/python/codegen/code-coverage.py b/bindings/python/codegen/code-coverage.py deleted file mode 100755 index fd15034..0000000 --- a/bindings/python/codegen/code-coverage.py +++ /dev/null @@ -1,42 +0,0 @@ -from __future__ import generators -import sys, os - -def read_symbols(file, type=None, dynamic=0): - if dynamic: - cmd = 'nm -D %s' % file - else: - cmd = 'nm %s' % file - for line in os.popen(cmd, 'r'): - if line[0] != ' ': # has an address as first bit of line - while line[0] != ' ': - line = line[1:] - while line[0] == ' ': - line = line[1:] - # we should be up to "type symbolname" now - sym_type = line[0] - symbol = line[1:].strip() - - if not type or type == sym_type: - yield symbol - -def main(): - if len(sys.argv) != 3: - sys.stderr.write('usage: coverage-check library.so wrapper.so\n') - sys.exit(1) - library = sys.argv[1] - wrapper = sys.argv[2] - - # first create a dict with all referenced symbols in the wrapper - # should really be a set, but a dict will do ... - wrapper_symbols = {} - for symbol in read_symbols(wrapper, type='U', dynamic=1): - wrapper_symbols[symbol] = 1 - - # now go through the library looking for matches on the defined symbols: - for symbol in read_symbols(library, type='T', dynamic=1): - if symbol[0] == '_': continue - if symbol not in wrapper_symbols: - print symbol - -if __name__ == '__main__': - main() diff --git a/bindings/python/codegen/codegen.py b/bindings/python/codegen/codegen.py deleted file mode 100644 index 8f20bf7..0000000 --- a/bindings/python/codegen/codegen.py +++ /dev/null @@ -1,1572 +0,0 @@ -import getopt -import keyword -import os -import string -import sys - -import argtypes -import definitions -import defsparser -import override -import reversewrapper - -class Coverage(object): - def __init__(self, name): - self.name = name - self.wrapped = 0 - self.not_wrapped = 0 - - def declare_wrapped(self): - self.wrapped += 1 - - def declare_not_wrapped(self): - self.not_wrapped += 1 - - def printstats(self): - total = self.wrapped + self.not_wrapped - fd = sys.stderr - if total: - fd.write("***INFO*** The coverage of %s is %.2f%% (%i/%i)\n" % - (self.name, - float(self.wrapped*100)/total, - self.wrapped, - total)) - else: - fd.write("***INFO*** There are no declared %s." % self.name) - -functions_coverage = Coverage("global functions") -methods_coverage = Coverage("methods") -vproxies_coverage = Coverage("virtual proxies") -vaccessors_coverage = Coverage("virtual accessors") -iproxies_coverage = Coverage("interface proxies") - -def exc_info(): - #traceback.print_exc() - etype, value, tb = sys.exc_info() - ret = "" - try: - sval = str(value) - if etype == KeyError: - ret = "No ArgType for %s" % (sval,) - else: - ret = sval - finally: - del etype, value, tb - return ret - -def fixname(name): - if keyword.iskeyword(name): - return name + '_' - return name - -class FileOutput: - '''Simple wrapper for file object, that makes writing #line - statements easier.''' # " - def __init__(self, fp, filename=None): - self.fp = fp - self.lineno = 1 - if filename: - self.filename = filename - else: - self.filename = self.fp.name - # handle writing to the file, and keep track of the line number ... - def write(self, str): - self.fp.write(str) - self.lineno = self.lineno + string.count(str, '\n') - def writelines(self, sequence): - for line in sequence: - self.write(line) - def close(self): - self.fp.close() - def flush(self): - self.fp.flush() - - def setline(self, linenum, filename): - '''writes out a #line statement, for use by the C - preprocessor.''' # " - self.write('#line %d "%s"\n' % (linenum, filename)) - def resetline(self): - '''resets line numbering to the original file''' - self.setline(self.lineno + 1, self.filename) - -class Wrapper: - type_tmpl = ( - 'PyTypeObject Py%(typename)s_Type = {\n' - ' PyObject_HEAD_INIT(NULL)\n' - ' 0, /* ob_size */\n' - ' "%(classname)s", /* tp_name */\n' - ' sizeof(%(tp_basicsize)s), /* tp_basicsize */\n' - ' 0, /* tp_itemsize */\n' - ' /* methods */\n' - ' (destructor)%(tp_dealloc)s, /* tp_dealloc */\n' - ' (printfunc)0, /* tp_print */\n' - ' (getattrfunc)%(tp_getattr)s, /* tp_getattr */\n' - ' (setattrfunc)%(tp_setattr)s, /* tp_setattr */\n' - ' (cmpfunc)%(tp_compare)s, /* tp_compare */\n' - ' (reprfunc)%(tp_repr)s, /* tp_repr */\n' - ' (PyNumberMethods*)%(tp_as_number)s, /* tp_as_number */\n' - ' (PySequenceMethods*)%(tp_as_sequence)s, /* tp_as_sequence */\n' - ' (PyMappingMethods*)%(tp_as_mapping)s, /* tp_as_mapping */\n' - ' (hashfunc)%(tp_hash)s, /* tp_hash */\n' - ' (ternaryfunc)%(tp_call)s, /* tp_call */\n' - ' (reprfunc)%(tp_str)s, /* tp_str */\n' - ' (getattrofunc)%(tp_getattro)s, /* tp_getattro */\n' - ' (setattrofunc)%(tp_setattro)s, /* tp_setattro */\n' - ' (PyBufferProcs*)%(tp_as_buffer)s, /* tp_as_buffer */\n' - ' %(tp_flags)s, /* tp_flags */\n' - ' %(tp_doc)s, /* Documentation string */\n' - ' (traverseproc)%(tp_traverse)s, /* tp_traverse */\n' - ' (inquiry)%(tp_clear)s, /* tp_clear */\n' - ' (richcmpfunc)%(tp_richcompare)s, /* tp_richcompare */\n' - ' %(tp_weaklistoffset)s, /* tp_weaklistoffset */\n' - ' (getiterfunc)%(tp_iter)s, /* tp_iter */\n' - ' (iternextfunc)%(tp_iternext)s, /* tp_iternext */\n' - ' (struct PyMethodDef*)%(tp_methods)s, /* tp_methods */\n' - ' (struct PyMemberDef*)0, /* tp_members */\n' - ' (struct PyGetSetDef*)%(tp_getset)s, /* tp_getset */\n' - ' NULL, /* tp_base */\n' - ' NULL, /* tp_dict */\n' - ' (descrgetfunc)%(tp_descr_get)s, /* tp_descr_get */\n' - ' (descrsetfunc)%(tp_descr_set)s, /* tp_descr_set */\n' - ' %(tp_dictoffset)s, /* tp_dictoffset */\n' - ' (initproc)%(tp_init)s, /* tp_init */\n' - ' (allocfunc)%(tp_alloc)s, /* tp_alloc */\n' - ' (newfunc)%(tp_new)s, /* tp_new */\n' - ' (freefunc)%(tp_free)s, /* tp_free */\n' - ' (inquiry)%(tp_is_gc)s /* tp_is_gc */\n' - '};\n\n' - ) - - slots_list = [ - 'tp_getattr', 'tp_setattr', 'tp_getattro', 'tp_setattro', - 'tp_compare', 'tp_repr', - 'tp_as_number', 'tp_as_sequence', 'tp_as_mapping', 'tp_hash', - 'tp_call', 'tp_str', 'tp_as_buffer', 'tp_richcompare', 'tp_iter', - 'tp_iternext', 'tp_descr_get', 'tp_descr_set', 'tp_init', - 'tp_alloc', 'tp_new', 'tp_free', 'tp_is_gc', - 'tp_traverse', 'tp_clear', 'tp_dealloc', 'tp_flags', 'tp_doc' - ] - - getter_tmpl = ( - 'static PyObject *\n' - '%(funcname)s(PyObject *self, void *closure)\n' - '{\n' - '%(varlist)s' - ' ret = %(field)s;\n' - '%(codeafter)s\n' - '}\n\n' - ) - - parse_tmpl = ( - ' if (!PyArg_ParseTupleAndKeywords(args, kwargs,' - '"%(typecodes)s:%(name)s"%(parselist)s))\n' - ' return %(errorreturn)s;\n' - ) - - deprecated_tmpl = ( - ' if (PyErr_Warn(PyExc_DeprecationWarning, ' - '"%(deprecationmsg)s") < 0)\n' - ' return %(errorreturn)s;\n' - ) - - methdef_tmpl = ( - ' { "%(name)s", (PyCFunction)%(cname)s, %(flags)s,\n' - ' %(docstring)s },\n' - ) - - noconstructor = ( - 'static int\n' - 'pygobject_no_constructor(PyObject *self, PyObject *args, ' - 'PyObject *kwargs)\n' - '{\n' - ' gchar buf[512];\n' - '\n' - ' g_snprintf(buf, sizeof(buf), "%s is an abstract widget", ' - 'self->ob_type->tp_name);\n' - ' PyErr_SetString(PyExc_NotImplementedError, buf);\n' - ' return -1;\n' - '}\n\n' - ) - - function_tmpl = ( - 'static PyObject *\n' - '_wrap_%(cname)s(PyObject *self%(extraparams)s)\n' - '{\n' - '%(varlist)s' - '%(parseargs)s' - '%(codebefore)s' - ' %(begin_allow_threads)s\n' - ' %(setreturn)s%(cname)s(%(arglist)s);\n' - ' %(end_allow_threads)s\n' - '%(codeafter)s\n' - '}\n\n' - ) - - virtual_accessor_tmpl = ( - 'static PyObject *\n' - '_wrap_%(cname)s(PyObject *cls%(extraparams)s)\n' - '{\n' - ' gpointer klass;\n' - '%(varlist)s' - '%(parseargs)s' - '%(codebefore)s' - ' klass = g_type_class_ref(pyg_type_from_object(cls));\n' - ' if (%(class_cast_macro)s(klass)->%(virtual)s) {\n' - ' pyg_begin_allow_threads;\n' - ' %(setreturn)s%(class_cast_macro)s(klass)->' - '%(virtual)s(%(arglist)s);\n' - ' pyg_end_allow_threads;\n' - ' } else {\n' - ' PyErr_SetString(PyExc_NotImplementedError, ' - '"virtual method %(name)s not implemented");\n' - ' g_type_class_unref(klass);\n' - ' return NULL;\n' - ' }\n' - ' g_type_class_unref(klass);\n' - '%(codeafter)s\n' - '}\n\n' - ) - - # template for method calls - constructor_tmpl = None - method_tmpl = None - - def __init__(self, parser, objinfo, overrides, fp=FileOutput(sys.stdout)): - self.parser = parser - self.objinfo = objinfo - self.overrides = overrides - self.fp = fp - - def get_lower_name(self): - return string.lower(string.replace(self.objinfo.typecode, - '_TYPE_', '_', 1)) - - def get_field_accessor(self, fieldname): - raise NotImplementedError - - def get_initial_class_substdict(self): return {} - - def get_initial_constructor_substdict(self, constructor): - return { 'name': '%s.__init__' % self.objinfo.c_name, - 'errorreturn': '-1' } - def get_initial_method_substdict(self, method): - substdict = { 'name': '%s.%s' % (self.objinfo.c_name, method.name) } - substdict['begin_allow_threads'] = 'pyg_begin_allow_threads;' - substdict['end_allow_threads'] = 'pyg_end_allow_threads;' - return substdict - - def write_class(self): - if self.overrides.is_type_ignored(self.objinfo.c_name): - return - self.fp.write('\n/* ----------- %s ----------- */\n\n' % - self.objinfo.c_name) - substdict = self.get_initial_class_substdict() - if not substdict.has_key('tp_flags'): - substdict['tp_flags'] = 'Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE' - substdict['typename'] = self.objinfo.c_name - if self.overrides.modulename: - substdict['classname'] = '%s.%s' % (self.overrides.modulename, - self.objinfo.name) - else: - substdict['classname'] = self.objinfo.name - substdict['tp_doc'] = self.objinfo.docstring - - # Maybe this could be done in a nicer way, but I'll leave it as it is - # for now: -- Johan - if not self.overrides.slot_is_overriden('%s.tp_init' % - self.objinfo.c_name): - substdict['tp_init'] = self.write_constructor() - substdict['tp_methods'] = self.write_methods() - substdict['tp_getset'] = self.write_getsets() - - # handle slots ... - for slot in self.slots_list: - - slotname = '%s.%s' % (self.objinfo.c_name, slot) - slotfunc = '_wrap_%s_%s' % (self.get_lower_name(), slot) - if slot[:6] == 'tp_as_': - slotfunc = '&' + slotfunc - if self.overrides.slot_is_overriden(slotname): - data = self.overrides.slot_override(slotname) - self.write_function(slotname, data) - substdict[slot] = slotfunc - else: - if not substdict.has_key(slot): - substdict[slot] = '0' - - self.fp.write(self.type_tmpl % substdict) - - self.write_virtuals() - - def write_function_wrapper(self, function_obj, template, - handle_return=0, is_method=0, kwargs_needed=0, - substdict=None): - '''This function is the guts of all functions that generate - wrappers for functions, methods and constructors.''' - if not substdict: substdict = {} - - info = argtypes.WrapperInfo() - - substdict.setdefault('errorreturn', 'NULL') - - # for methods, we want the leading comma - if is_method: - info.arglist.append('') - - if function_obj.varargs: - raise ValueError, "varargs functions not supported" - - for param in function_obj.params: - if param.pdflt and '|' not in info.parsestr: - info.add_parselist('|', [], []) - handler = argtypes.matcher.get(param.ptype) - handler.write_param(param.ptype, param.pname, param.pdflt, - param.pnull, param.keeprefcount, info) - - substdict['setreturn'] = '' - if handle_return: - if function_obj.ret not in ('none', None): - substdict['setreturn'] = 'ret = ' - handler = argtypes.matcher.get(function_obj.ret) - handler.write_return(function_obj.ret, - function_obj.caller_owns_return, info) - - if function_obj.deprecated != None: - deprecated = self.deprecated_tmpl % { - 'deprecationmsg': function_obj.deprecated, - 'errorreturn': substdict['errorreturn'] } - else: - deprecated = '' - - # if name isn't set, set it to function_obj.name - substdict.setdefault('name', function_obj.name) - - substdict['begin_allow_threads'] = 'pyg_begin_allow_threads;' - substdict['end_allow_threads'] = 'pyg_end_allow_threads;' - - if self.objinfo: - substdict['typename'] = self.objinfo.c_name - substdict.setdefault('cname', function_obj.c_name) - substdict['varlist'] = info.get_varlist() - substdict['typecodes'] = info.parsestr - substdict['parselist'] = info.get_parselist() - substdict['arglist'] = info.get_arglist() - substdict['codebefore'] = deprecated + ( - string.replace(info.get_codebefore(), - 'return NULL', 'return ' + substdict['errorreturn']) - ) - substdict['codeafter'] = ( - string.replace(info.get_codeafter(), - 'return NULL', - 'return ' + substdict['errorreturn'])) - - if info.parsestr or kwargs_needed: - substdict['parseargs'] = self.parse_tmpl % substdict - substdict['extraparams'] = ', PyObject *args, PyObject *kwargs' - flags = 'METH_VARARGS|METH_KEYWORDS' - - # prepend the keyword list to the variable list - substdict['varlist'] = info.get_kwlist() + substdict['varlist'] - else: - substdict['parseargs'] = '' - substdict['extraparams'] = '' - flags = 'METH_NOARGS' - - return template % substdict, flags - - def write_constructor(self): - initfunc = '0' - constructor = self.parser.find_constructor(self.objinfo,self.overrides) - if not constructor: - return self.write_default_constructor() - - funcname = constructor.c_name - try: - if self.overrides.is_overriden(funcname): - data = self.overrides.override(funcname) - self.write_function(funcname, data) - self.objinfo.has_new_constructor_api = ( - self.objinfo.typecode in - self.overrides.newstyle_constructors) - else: - # ok, a hack to determine if we should use - # new-style constructores :P - property_based = getattr(self, - 'write_property_based_constructor', - None) - if property_based: - if (len(constructor.params) == 0 or - isinstance(constructor.params[0], - definitions.Property)): - # write_property_based_constructor is only - # implemented in GObjectWrapper - return self.write_property_based_constructor( - constructor) - else: - sys.stderr.write( - "Warning: generating old-style constructor for:" + - constructor.c_name + '\n') - - # write constructor from template ... - code = self.write_function_wrapper(constructor, - self.constructor_tmpl, - handle_return=0, is_method=0, kwargs_needed=1, - substdict=self.get_initial_constructor_substdict( - constructor))[0] - self.fp.write(code) - initfunc = '_wrap_' + funcname - except: - sys.stderr.write('Could not write constructor for %s: %s\n' - % (self.objinfo.c_name, exc_info())) - - initfunc = self.write_noconstructor() - return initfunc - - def write_noconstructor(self): - # this is a hack ... - if not hasattr(self.overrides, 'no_constructor_written'): - self.fp.write(self.noconstructor) - self.overrides.no_constructor_written = 1 - initfunc = 'pygobject_no_constructor' - return initfunc - - def write_default_constructor(self): - return self.write_noconstructor() - - def get_methflags(self, funcname): - if self.overrides.wants_kwargs(funcname): - flags = 'METH_VARARGS|METH_KEYWORDS' - elif self.overrides.wants_noargs(funcname): - flags = 'METH_NOARGS' - elif self.overrides.wants_onearg(funcname): - flags = 'METH_O' - else: - flags = 'METH_VARARGS' - if self.overrides.is_staticmethod(funcname): - flags += '|METH_STATIC' - elif self.overrides.is_classmethod(funcname): - flags += '|METH_CLASS' - return flags - - def write_function(self, funcname, data): - lineno, filename = self.overrides.getstartline(funcname) - self.fp.setline(lineno, filename) - self.fp.write(data) - self.fp.resetline() - self.fp.write('\n\n') - - def _get_class_virtual_substdict(self, meth, cname, parent): - substdict = self.get_initial_method_substdict(meth) - substdict['virtual'] = substdict['name'].split('.')[1] - substdict['cname'] = cname - substdict['class_cast_macro'] = parent.typecode.replace( - '_TYPE_', '_', 1) + "_CLASS" - substdict['typecode'] = self.objinfo.typecode - substdict['cast'] = string.replace(parent.typecode, '_TYPE_', '_', 1) - return substdict - - def write_methods(self): - methods = [] - klass = self.objinfo.c_name - # First, get methods from the defs files - for meth in self.parser.find_methods(self.objinfo): - method_name = meth.c_name - if self.overrides.is_ignored(method_name): - continue - try: - if self.overrides.is_overriden(method_name): - if not self.overrides.is_already_included(method_name): - data = self.overrides.override(method_name) - self.write_function(method_name, data) - - methflags = self.get_methflags(method_name) - else: - # write constructor from template ... - code, methflags = self.write_function_wrapper(meth, - self.method_tmpl, handle_return=1, is_method=1, - substdict=self.get_initial_method_substdict(meth)) - self.fp.write(code) - methods.append(self.methdef_tmpl % - { 'name': fixname(meth.name), - 'cname': '_wrap_' + method_name, - 'flags': methflags, - 'docstring': meth.docstring }) - methods_coverage.declare_wrapped() - except: - methods_coverage.declare_not_wrapped() - sys.stderr.write('Could not write method %s.%s: %s\n' - % (klass, meth.name, exc_info())) - - # Now try to see if there are any defined in the override - for method_name in self.overrides.get_defines_for(klass): - c_name = override.class2cname(klass, method_name) - if self.overrides.is_already_included(method_name): - continue - - try: - data = self.overrides.define(klass, method_name) - self.write_function(method_name, data) - methflags = self.get_methflags(method_name) - - methods.append(self.methdef_tmpl % - { 'name': method_name, - 'cname': '_wrap_' + c_name, - 'flags': methflags, - 'docstring': meth.docstring }) - methods_coverage.declare_wrapped() - except: - methods_coverage.declare_not_wrapped() - sys.stderr.write('Could not write method %s.%s: %s\n' - % (klass, meth.name, exc_info())) - - # Add GObject virtual method accessors, for chaining to parent - # virtuals from subclasses - methods += self.write_virtual_accessors() - - if methods: - methoddefs = '_Py%s_methods' % self.objinfo.c_name - # write the PyMethodDef structure - methods.append(' { NULL, NULL, 0, NULL }\n') - self.fp.write('static const PyMethodDef %s[] = {\n' % methoddefs) - self.fp.write(string.join(methods, '')) - self.fp.write('};\n\n') - else: - methoddefs = 'NULL' - return methoddefs - - def write_virtual_accessors(self): - klass = self.objinfo.c_name - methods = [] - for meth in self.parser.find_virtuals(self.objinfo): - method_name = self.objinfo.c_name + "__do_" + meth.name - if self.overrides.is_ignored(method_name): - continue - try: - if self.overrides.is_overriden(method_name): - if not self.overrides.is_already_included(method_name): - data = self.overrides.override(method_name) - self.write_function(method_name, data) - methflags = self.get_methflags(method_name) - else: - # temporarily add a 'self' parameter as first argument - meth.params.insert(0, definitions.Parameter( - ptype=(self.objinfo.c_name + '*'), - pname='self', pdflt=None, pnull=None)) - try: - # write method from template ... - code, methflags = self.write_function_wrapper( - meth, self.virtual_accessor_tmpl, - handle_return=True, is_method=False, - substdict=self._get_class_virtual_substdict( - meth, method_name, self.objinfo)) - self.fp.write(code) - finally: - del meth.params[0] - methods.append(self.methdef_tmpl % - { 'name': "do_" + fixname(meth.name), - 'cname': '_wrap_' + method_name, - 'flags': methflags + '|METH_CLASS', - 'docstring': 'NULL'}) - vaccessors_coverage.declare_wrapped() - except: - vaccessors_coverage.declare_not_wrapped() - sys.stderr.write( - 'Could not write virtual accessor method %s.%s: %s\n' - % (klass, meth.name, exc_info())) - return methods - - def write_virtuals(self): - ''' - Write _wrap_FooBar__proxy_do_zbr() reverse wrapers for - GObject virtuals - ''' - klass = self.objinfo.c_name - virtuals = [] - for meth in self.parser.find_virtuals(self.objinfo): - method_name = self.objinfo.c_name + "__proxy_do_" + meth.name - if self.overrides.is_ignored(method_name): - continue - try: - if self.overrides.is_overriden(method_name): - if not self.overrides.is_already_included(method_name): - data = self.overrides.override(method_name) - self.write_function(method_name, data) - else: - # write virtual proxy ... - ret, props = argtypes.matcher.get_reverse_ret(meth.ret) - wrapper = reversewrapper.ReverseWrapper( - '_wrap_' + method_name, is_static=True) - wrapper.set_return_type(ret(wrapper, **props)) - wrapper.add_parameter(reversewrapper.PyGObjectMethodParam( - wrapper, "self", method_name="do_" + meth.name, - c_type=(klass + ' *'))) - for param in meth.params: - handler, props = argtypes.matcher.get_reverse( - param.ptype) - props["direction"] = param.pdir - wrapper.add_parameter(handler(wrapper, - param.pname, **props)) - buf = reversewrapper.MemoryCodeSink() - wrapper.generate(buf) - self.fp.write(buf.flush()) - virtuals.append((fixname(meth.name), '_wrap_' + method_name)) - vproxies_coverage.declare_wrapped() - except (KeyError, ValueError): - vproxies_coverage.declare_not_wrapped() - virtuals.append((fixname(meth.name), None)) - sys.stderr.write('Could not write virtual proxy %s.%s: %s\n' - % (klass, meth.name, exc_info())) - if virtuals: - # Write a 'pygtk class init' function for this object, - # except when the object type is explicitly ignored (like - # GtkPlug and GtkSocket on win32). - if self.overrides.is_ignored(self.objinfo.typecode): - return - class_cast_macro = self.objinfo.typecode.replace( - '_TYPE_', '_', 1) + "_CLASS" - cast_macro = self.objinfo.typecode.replace('_TYPE_', '_', 1) - funcname = "__%s_class_init" % klass - self.objinfo.class_init_func = funcname - have_implemented_virtuals = not not [True - for name, cname in virtuals - if cname is not None] - self.fp.write( - ('\nstatic int\n' - '%(funcname)s(gpointer gclass, PyTypeObject *pyclass)\n' - '{\n') % vars()) - - if have_implemented_virtuals: - self.fp.write(' PyObject *o;\n') - self.fp.write( - ' %(klass)sClass *klass = ' - '%(class_cast_macro)s(gclass);\n' - ' PyObject *gsignals = ' - 'PyDict_GetItemString(pyclass->tp_dict, "__gsignals__");\n' - % vars()) - - for name, cname in virtuals: - do_name = 'do_' + name - if cname is None: - self.fp.write('\n /* overriding %(do_name)s ' - 'is currently not supported */\n' % vars()) - else: - self.fp.write(''' - o = PyObject_GetAttrString((PyObject *) pyclass, "%(do_name)s"); - if (o == NULL) - PyErr_Clear(); - else { - if (!PyObject_TypeCheck(o, &PyCFunction_Type) - && !(gsignals && PyDict_GetItemString(gsignals, "%(name)s"))) - klass->%(name)s = %(cname)s; - Py_DECREF(o); - } -''' % vars()) - self.fp.write(' return 0;\n}\n') - - def write_getsets(self): - lower_name = self.get_lower_name() - getsets_name = lower_name + '_getsets' - getterprefix = '_wrap_' + lower_name + '__get_' - setterprefix = '_wrap_' + lower_name + '__set_' - - # no overrides for the whole function. If no fields, - # don't write a func - if not self.objinfo.fields: - return '0' - getsets = [] - for ftype, cfname in self.objinfo.fields: - fname = cfname.replace('.', '_') - gettername = '0' - settername = '0' - attrname = self.objinfo.c_name + '.' + fname - if self.overrides.attr_is_overriden(attrname): - code = self.overrides.attr_override(attrname) - self.write_function(attrname, code) - if string.find(code, getterprefix + fname) >= 0: - gettername = getterprefix + fname - if string.find(code, setterprefix + fname) >= 0: - settername = setterprefix + fname - if gettername == '0': - try: - funcname = getterprefix + fname - info = argtypes.WrapperInfo() - handler = argtypes.matcher.get(ftype) - # for attributes, we don't own the "return value" - handler.write_return(ftype, 0, info) - self.fp.write(self.getter_tmpl % - { 'funcname': funcname, - 'varlist': info.varlist, - 'field': self.get_field_accessor(cfname), - 'codeafter': info.get_codeafter() }) - gettername = funcname - except: - sys.stderr.write( - "Could not write getter for %s.%s: %s\n" - % (self.objinfo.c_name, fname, exc_info())) - if gettername != '0' or settername != '0': - getsets.append(' { "%s", (getter)%s, (setter)%s },\n' % - (fixname(fname), gettername, settername)) - - if not getsets: - return '0' - self.fp.write('static const PyGetSetDef %s[] = {\n' % getsets_name) - for getset in getsets: - self.fp.write(getset) - self.fp.write(' { NULL, (getter)0, (setter)0 },\n') - self.fp.write('};\n\n') - - return getsets_name - - def write_functions(self, prefix): - self.fp.write('\n/* ----------- functions ----------- */\n\n') - functions = [] - - # First, get methods from the defs files - for func in self.parser.find_functions(): - funcname = func.c_name - if self.overrides.is_ignored(funcname): - continue - try: - if self.overrides.is_overriden(funcname): - data = self.overrides.override(funcname) - self.write_function(funcname, data) - - methflags = self.get_methflags(funcname) - else: - # write constructor from template ... - code, methflags = self.write_function_wrapper(func, - self.function_tmpl, handle_return=1, is_method=0) - self.fp.write(code) - functions.append(self.methdef_tmpl % - { 'name': func.name, - 'cname': '_wrap_' + funcname, - 'flags': methflags, - 'docstring': func.docstring }) - functions_coverage.declare_wrapped() - except: - functions_coverage.declare_not_wrapped() - sys.stderr.write('Could not write function %s: %s\n' - % (func.name, exc_info())) - - # Now try to see if there are any defined in the override - for funcname in self.overrides.get_functions(): - try: - data = self.overrides.function(funcname) - self.write_function(funcname, data) - methflags = self.get_methflags(funcname) - functions.append(self.methdef_tmpl % - { 'name': funcname, - 'cname': '_wrap_' + funcname, - 'flags': methflags, - 'docstring': 'NULL'}) - functions_coverage.declare_wrapped() - except: - functions_coverage.declare_not_wrapped() - sys.stderr.write('Could not write function %s: %s\n' - % (funcname, exc_info())) - - # write the PyMethodDef structure - functions.append(' { NULL, NULL, 0, NULL }\n') - - self.fp.write('const PyMethodDef ' + prefix + '_functions[] = {\n') - self.fp.write(string.join(functions, '')) - self.fp.write('};\n\n') - -class GObjectWrapper(Wrapper): - constructor_tmpl = ( - 'static int\n' - '_wrap_%(cname)s(PyGObject *self%(extraparams)s)\n' - '{\n' - '%(varlist)s' - '%(parseargs)s' - '%(codebefore)s' - ' self->obj = (GObject *)%(cname)s(%(arglist)s);\n' - '%(codeafter)s\n' - ' if (!self->obj) {\n' - ' PyErr_SetString(PyExc_RuntimeError, ' - '"could not create %(typename)s object");\n' - ' return -1;\n' - ' }\n' - '%(aftercreate)s' - ' pygobject_register_wrapper((PyObject *)self);\n' - ' return 0;\n' - '}\n\n' - ) - - method_tmpl = ( - 'static PyObject *\n' - '_wrap_%(cname)s(PyGObject *self%(extraparams)s)\n' - '{\n' - '%(varlist)s' - '%(parseargs)s' - '%(codebefore)s' - ' %(begin_allow_threads)s\n' - ' %(setreturn)s%(cname)s(%(cast)s(self->obj)%(arglist)s);\n' - ' %(end_allow_threads)s\n' - '%(codeafter)s\n' - '}\n\n' - ) - def __init__(self, parser, objinfo, overrides, fp=FileOutput(sys.stdout)): - Wrapper.__init__(self, parser, objinfo, overrides, fp) - if self.objinfo: - self.castmacro = string.replace(self.objinfo.typecode, - '_TYPE_', '_', 1) - - def get_initial_class_substdict(self): - return { 'tp_basicsize' : 'PyGObject', - 'tp_weaklistoffset' : 'offsetof(PyGObject, weakreflist)', - 'tp_dictoffset' : 'offsetof(PyGObject, inst_dict)' } - - def get_field_accessor(self, fieldname): - castmacro = string.replace(self.objinfo.typecode, '_TYPE_', '_', 1) - return '%s(pygobject_get(self))->%s' % (castmacro, fieldname) - - def get_initial_constructor_substdict(self, constructor): - substdict = Wrapper.get_initial_constructor_substdict(self, - constructor) - if not constructor.caller_owns_return: - substdict['aftercreate'] = " g_object_ref(self->obj);\n" - else: - substdict['aftercreate'] = '' - return substdict - - def get_initial_method_substdict(self, method): - substdict = Wrapper.get_initial_method_substdict(self, method) - substdict['cast'] = string.replace(self.objinfo.typecode, - '_TYPE_', '_', 1) - return substdict - - def write_default_constructor(self): - try: - parent = self.parser.find_object(self.objinfo.parent) - except ValueError: - parent = None - if parent is not None: - ## just like the constructor is inheritted, we should - # inherit the new API compatibility flag - self.objinfo.has_new_constructor_api = ( - parent.has_new_constructor_api) - elif self.objinfo.parent == 'GObject': - self.objinfo.has_new_constructor_api = True - return '0' - - def write_property_based_constructor(self, constructor): - self.objinfo.has_new_constructor_api = True - out = self.fp - print >> out, "static int" - print >> out, '_wrap_%s(PyGObject *self, PyObject *args,' \ - ' PyObject *kwargs)\n{' % constructor.c_name - if constructor.params: - s = " GType obj_type = pyg_type_from_object((PyObject *) self);" - print >> out, s - - def py_str_list_to_c(arg): - if arg: - return "{" + ", ".join( - map(lambda s: '"' + s + '"', arg)) + ", NULL }" - else: - return "{ NULL }" - - classname = '%s.%s' % (self.overrides.modulename, - self.objinfo.name) - - if constructor.params: - mandatory_arguments = [param for param in constructor.params - if not param.optional] - optional_arguments = [param for param in constructor.params - if param.optional] - arg_names = py_str_list_to_c( - [param.argname - for param in mandatory_arguments + optional_arguments]) - - prop_names = py_str_list_to_c( - [param.pname - for param in mandatory_arguments + optional_arguments]) - - print >> out, " GParameter params[%i];" % \ - len(constructor.params) - print >> out, " PyObject *parsed_args[%i] = {NULL, };" % \ - len(constructor.params) - print >> out, " char *arg_names[] = %s;" % arg_names - print >> out, " char *prop_names[] = %s;" % prop_names - print >> out, " guint nparams, i;" - print >> out - if constructor.deprecated is not None: - out.write( - ' if (PyErr_Warn(PyExc_DeprecationWarning, ' - '"%s") < 0)\n' % - constructor.deprecated) - print >> out, ' return -1;' - print >> out - out.write(" if (!PyArg_ParseTupleAndKeywords(args, kwargs, ") - template = '"' - if mandatory_arguments: - template += "O"*len(mandatory_arguments) - if optional_arguments: - template += "|" + "O"*len(optional_arguments) - template += ':%s.__init__"' % classname - print >> out, template, ", arg_names", - for i in range(len(constructor.params)): - print >> out, ", &parsed_args[%i]" % i, - - out.write( - "))\n" - " return -1;\n" - "\n" - " memset(params, 0, sizeof(GParameter)*%i);\n" - " if (!pyg_parse_constructor_args(obj_type, arg_names,\n" - " prop_names, params, \n" - " &nparams, parsed_args))\n" - " return -1;\n" - " pygobject_constructv(self, nparams, params);\n" - " for (i = 0; i < nparams; ++i)\n" - " g_value_unset(¶ms[i].value);\n" - % len(constructor.params)) - else: - out.write( - " static char* kwlist[] = { NULL };\n" - "\n") - - if constructor.deprecated is not None: - out.write( - ' if (PyErr_Warn(PyExc_DeprecationWarning, "%s") < 0)\n' - ' return -1;\n' - '\n' % constructor.deprecated) - - out.write( - ' if (!PyArg_ParseTupleAndKeywords(args, kwargs,\n' - ' ":%s.__init__",\n' - ' kwlist))\n' - ' return -1;\n' - '\n' - ' pygobject_constructv(self, 0, NULL);\n' % classname) - out.write( - ' if (!self->obj) {\n' - ' PyErr_SetString(\n' - ' PyExc_RuntimeError, \n' - ' "could not create %s object");\n' - ' return -1;\n' - ' }\n' % classname) - - if not constructor.caller_owns_return: - print >> out, " g_object_ref(self->obj);\n" - - out.write( - ' return 0;\n' - '}\n\n') - - return "_wrap_%s" % constructor.c_name - - -## TODO : Add GstMiniObjectWrapper(Wrapper) -class GstMiniObjectWrapper(Wrapper): - constructor_tmpl = ( - 'static int\n' - '_wrap_%(cname)s(PyGstMiniObject *self%(extraparams)s)\n' - '{\n' - '%(varlist)s' - '%(parseargs)s' - '%(codebefore)s' - ' self->obj = (GstMiniObject *)%(cname)s(%(arglist)s);\n' - '%(codeafter)s\n' - ' if (!self->obj) {\n' - ' PyErr_SetString(PyExc_RuntimeError, ' - '"could not create %(typename)s miniobject");\n' - ' return -1;\n' - ' }\n' - '%(aftercreate)s' - ' pygstminiobject_register_wrapper((PyObject *)self);\n' - ' return 0;\n' - '}\n\n' - ) - method_tmpl = ( - 'static PyObject *\n' - '_wrap_%(cname)s(PyGstMiniObject *self%(extraparams)s)\n' - '{\n' - '%(varlist)s' - '%(parseargs)s' - '%(codebefore)s' - ' %(begin_allow_threads)s\n' - ' %(setreturn)s%(cname)s(%(cast)s(self->obj)%(arglist)s);\n' - ' %(end_allow_threads)s\n' - '%(codeafter)s\n' - '}\n\n' - ) - def __init__(self, parser, objinfo, overrides, fp=FileOutput(sys.stdout)): - Wrapper.__init__(self, parser, objinfo, overrides, fp) - if self.objinfo: - self.castmacro = string.replace(self.objinfo.typecode, - '_TYPE_', '_', 1) - - def get_initial_class_substdict(self): - return { 'tp_basicsize' : 'PyGstMiniObject', - 'tp_weaklistoffset' : 'offsetof(PyGstMiniObject, weakreflist)', - 'tp_dictoffset' : 'offsetof(PyGstMiniObject, inst_dict)' } - - def get_field_accessor(self, fieldname): - castmacro = string.replace(self.objinfo.typecode, '_TYPE_', '_', 1) - return '%s(pygstminiobject_get(self))->%s' % (castmacro, fieldname) - - def get_initial_constructor_substdict(self, constructor): - substdict = Wrapper.get_initial_constructor_substdict(self, - constructor) - if not constructor.caller_owns_return: - substdict['aftercreate'] = " gst_mini_object_ref(self->obj);\n" - else: - substdict['aftercreate'] = '' - return substdict - - def get_initial_method_substdict(self, method): - substdict = Wrapper.get_initial_method_substdict(self, method) - substdict['cast'] = string.replace(self.objinfo.typecode, - '_TYPE_', '_', 1) - return substdict - - - -class GInterfaceWrapper(GObjectWrapper): - virtual_accessor_tmpl = ( - 'static PyObject *\n' - '_wrap_%(cname)s(PyObject *cls%(extraparams)s)\n' - '{\n' - ' %(vtable)s *iface;\n' - '%(varlist)s' - '%(parseargs)s' - '%(codebefore)s' - ' iface = g_type_interface_peek(' - 'g_type_class_peek(pyg_type_from_object(cls)), %(typecode)s);\n' - ' if (iface->%(virtual)s)\n' - ' %(setreturn)siface->%(virtual)s(%(arglist)s);\n' - ' else {\n' - ' PyErr_SetString(PyExc_NotImplementedError, ' - '"interface method %(name)s not implemented");\n' - ' return NULL;\n' - ' }\n' - '%(codeafter)s\n' - '}\n\n' - ) - - def get_initial_class_substdict(self): - return { 'tp_basicsize' : 'PyObject', - 'tp_weaklistoffset' : '0', - 'tp_dictoffset' : '0'} - - def write_constructor(self): - # interfaces have no constructors ... - return '0' - def write_getsets(self): - # interfaces have no fields ... - return '0' - - def _get_class_virtual_substdict(self, meth, cname, parent): - substdict = self.get_initial_method_substdict(meth) - substdict['virtual'] = substdict['name'].split('.')[1] - substdict['cname'] = cname - substdict['typecode'] = self.objinfo.typecode - substdict['vtable'] = self.objinfo.vtable - return substdict - - def write_virtuals(self): - ## Now write reverse method wrappers, which let python code - ## implement interface methods. - # First, get methods from the defs files - klass = self.objinfo.c_name - proxies = [] - for meth in self.parser.find_virtuals(self.objinfo): - method_name = self.objinfo.c_name + "__proxy_do_" + meth.name - if self.overrides.is_ignored(method_name): - continue - try: - if self.overrides.is_overriden(method_name): - if not self.overrides.is_already_included(method_name): - data = self.overrides.override(method_name) - self.write_function(method_name, data) - else: - # write proxy ... - ret, props = argtypes.matcher.get_reverse_ret(meth.ret) - wrapper = reversewrapper.ReverseWrapper( - '_wrap_' + method_name, is_static=True) - wrapper.set_return_type(ret(wrapper, **props)) - wrapper.add_parameter(reversewrapper.PyGObjectMethodParam( - wrapper, "self", method_name="do_" + meth.name, - c_type=(klass + ' *'))) - for param in meth.params: - handler, props = argtypes.matcher.get_reverse( - param.ptype) - props["direction"] = param.pdir - wrapper.add_parameter( - handler(wrapper, param.pname, **props)) - buf = reversewrapper.MemoryCodeSink() - wrapper.generate(buf) - self.fp.write(buf.flush()) - proxies.append((fixname(meth.name), '_wrap_' + method_name)) - iproxies_coverage.declare_wrapped() - except (KeyError, ValueError): - iproxies_coverage.declare_not_wrapped() - proxies.append((fixname(meth.name), None)) - sys.stderr.write('Could not write interface proxy %s.%s: %s\n' - % (klass, meth.name, exc_info())) - - if not proxies: - return - - # Make sure we have at least one proxy function - if not [cname for name,cname in proxies if not cname is None]: - return - - ## Write an interface init function for this object - funcname = "__%s__interface_init" % klass - vtable = self.objinfo.vtable - self.fp.write( - '\nstatic void\n' - '%(funcname)s(%(vtable)s *iface, PyTypeObject *pytype)\n' - '{\n' - ' %(vtable)s *parent_iface = ' - 'g_type_interface_peek_parent(iface);\n' - ' PyObject *py_method;\n' - '\n' - % vars()) - - for name, cname in proxies: - do_name = 'do_' + name - if cname is None: - continue - - self.fp.write(( - ' py_method = pytype? PyObject_GetAttrString(' - '(PyObject *) pytype, "%(do_name)s") : NULL;\n' - ' if (py_method && !PyObject_TypeCheck(py_method, ' - '&PyCFunction_Type)) {\n' - ' iface->%(name)s = %(cname)s;\n' - ' } else {\n' - ' PyErr_Clear();\n' - ' if (parent_iface) {\n' - ' iface->%(name)s = parent_iface->%(name)s;\n' - ' }\n' - ' Py_XDECREF(py_method);\n' - ' }\n' - ) % vars()) - self.fp.write('}\n\n') - interface_info = "__%s__iinfo" % klass - self.fp.write(''' -static const GInterfaceInfo %s = { - (GInterfaceInitFunc) %s, - NULL, - NULL -}; -''' % (interface_info, funcname)) - self.objinfo.interface_info = interface_info - -class GBoxedWrapper(Wrapper): - constructor_tmpl = ( - 'static int\n' - '_wrap_%(cname)s(PyGBoxed *self%(extraparams)s)\n' - '{\n' \ - '%(varlist)s' - '%(parseargs)s' - '%(codebefore)s' - ' self->gtype = %(typecode)s;\n' - ' self->free_on_dealloc = FALSE;\n' - ' self->boxed = %(cname)s(%(arglist)s);\n' - '%(codeafter)s\n' - ' if (!self->boxed) {\n' - ' PyErr_SetString(PyExc_RuntimeError, ' - '"could not create %(typename)s object");\n' - ' return -1;\n' - ' }\n' - ' self->free_on_dealloc = TRUE;\n' - ' return 0;\n' - '}\n\n' - ) - - method_tmpl = ( - 'static PyObject *\n' - '_wrap_%(cname)s(PyObject *self%(extraparams)s)\n' - '{\n' - '%(varlist)s' - '%(parseargs)s' - '%(codebefore)s' - ' %(begin_allow_threads)s\n' - ' %(setreturn)s%(cname)s(pyg_boxed_get(self, ' - '%(typename)s)%(arglist)s);\n' - ' %(end_allow_threads)s\n' - '%(codeafter)s\n' - '}\n\n' - ) - - def get_initial_class_substdict(self): - return { 'tp_basicsize' : 'PyGBoxed', - 'tp_weaklistoffset' : '0', - 'tp_dictoffset' : '0' } - - def get_field_accessor(self, fieldname): - return 'pyg_boxed_get(self, %s)->%s' % (self.objinfo.c_name, fieldname) - - def get_initial_constructor_substdict(self, constructor): - substdict = Wrapper.get_initial_constructor_substdict( - self, constructor) - substdict['typecode'] = self.objinfo.typecode - return substdict - -class GPointerWrapper(GBoxedWrapper): - constructor_tmpl = ( - 'static int\n' - '_wrap_%(cname)s(PyGPointer *self%(extraparams)s)\n' - '{\n' - '%(varlist)s' - '%(parseargs)s' - '%(codebefore)s' - ' self->gtype = %(typecode)s;\n' - ' self->pointer = %(cname)s(%(arglist)s);\n' - '%(codeafter)s\n' - ' if (!self->pointer) {\n' - ' PyErr_SetString(PyExc_RuntimeError, ' - '"could not create %(typename)s object");\n' - ' return -1;\n' - ' }\n' - ' return 0;\n' - '}\n\n' - ) - - method_tmpl = ( - 'static PyObject *\n' - '_wrap_%(cname)s(PyObject *self%(extraparams)s)\n' - '{\n' - '%(varlist)s' - '%(parseargs)s' - '%(codebefore)s' - ' %(setreturn)s%(cname)s(pyg_pointer_get(self, ' - '%(typename)s)%(arglist)s);\n' - '%(codeafter)s\n' - '}\n\n' - ) - - def get_initial_class_substdict(self): - return { 'tp_basicsize' : 'PyGPointer', - 'tp_weaklistoffset' : '0', - 'tp_dictoffset' : '0' } - - def get_field_accessor(self, fieldname): - return 'pyg_pointer_get(self, %s)->%s' % (self.objinfo.c_name, - fieldname) - - def get_initial_constructor_substdict(self, constructor): - substdict = Wrapper.get_initial_constructor_substdict( - self, constructor) - substdict['typecode'] = self.objinfo.typecode - return substdict - -def write_headers(data, fp): - fp.write('/* -- THIS FILE IS GENERATED - DO NOT EDIT */') - fp.write('/* -*- Mode: C; c-basic-offset: 4 -*- */\n\n') - fp.write('#include <Python.h>\n\n\n') - fp.write(data) - fp.resetline() - fp.write('\n\n') - -def write_body(data, fp): - fp.write(data) - fp.resetline() - fp.write('\n\n') - -def write_imports(overrides, fp): - fp.write('/* ---------- types from other modules ---------- */\n') - for module, pyname, cname in overrides.get_imports(): - fp.write('static PyTypeObject *_%s;\n' % cname) - fp.write('#define %s (*_%s)\n' % (cname, cname)) - fp.write('\n\n') - -def write_type_declarations(parser, fp): - fp.write('/* ---------- forward type declarations ---------- */\n') - for obj in parser.boxes: - fp.write('PyTypeObject Py' + obj.c_name + '_Type;\n') - for obj in parser.objects: - fp.write('PyTypeObject Py' + obj.c_name + '_Type;\n') - for obj in parser.miniobjects: - fp.write('PyTypeObject Py' + obj.c_name + '_Type;\n') - for interface in parser.interfaces: - fp.write('PyTypeObject Py' + interface.c_name + '_Type;\n') - fp.write('\n') - - -def sort_parent_children(objects): - objects = list(objects) - modified = True - while modified: - modified = False - parent_index = None - child_index = None - for i, obj in enumerate(objects): - if obj.parent == 'GObject': - continue - if obj.parent not in [info.c_name for info in objects[:i]]: - for j, info in enumerate(objects[i+1:]): - if info.c_name == obj.parent: - parent_index = i + 1 + j - child_index = i - break - else: - continue - break - if child_index is not None and parent_index is not None: - if child_index != parent_index: - objects.insert(child_index, objects.pop(parent_index)) - modified = True - return objects - -def write_classes(parser, overrides, fp): - ## Sort the objects, so that we generate code for the parent types - ## before their children. - objects = sort_parent_children(parser.objects) - for klass, items in ((GBoxedWrapper, parser.boxes), - (GPointerWrapper, parser.pointers), - (GObjectWrapper, objects), - (GstMiniObjectWrapper, parser.miniobjects), - (GInterfaceWrapper, parser.interfaces)): - for item in items: - instance = klass(parser, item, overrides, fp) - instance.write_class() - fp.write('\n') - -def write_enums(parser, overrides, prefix, fp=sys.stdout): - if not parser.enums: - return - fp.write('\n/* ----------- enums and flags ----------- */\n\n') - fp.write( - 'void\n' + prefix + - '_add_constants(PyObject *module, const gchar *strip_prefix)\n{\n') - - for enum in parser.enums: - if overrides.is_type_ignored(enum.c_name): - continue - if enum.typecode is None: - for nick, value in enum.values: - fp.write( - ' PyModule_AddIntConstant(module, ' - '(char *) pyg_constant_strip_prefix("%s", strip_prefix), %s);\n' - % (value, value)) - else: - if enum.deftype == 'enum': - fp.write(' pyg_enum_add(module, "%s", strip_prefix, %s);\n' - % (enum.name, enum.typecode)) - else: - fp.write(' pyg_flags_add(module, "%s", strip_prefix, %s);\n' - % (enum.name, enum.typecode)) - - fp.write('\n') - fp.write(' if (PyErr_Occurred())\n') - fp.write(' PyErr_Print();\n') - fp.write('}\n\n') - -def write_extension_init(overrides, prefix, fp): - fp.write('/* initialise stuff extension classes */\n') - fp.write('void\n' + prefix + '_register_classes(PyObject *d)\n{\n') - imports = overrides.get_imports()[:] - if imports: - bymod = {} - for module, pyname, cname in imports: - bymod.setdefault(module, []).append((pyname, cname)) - fp.write(' PyObject *module;\n\n') - for module in bymod: - fp.write( - ' if ((module = PyImport_ImportModule("%s")) != NULL) {\n' - % module) - fp.write( - ' PyObject *moddict = PyModule_GetDict(module);\n\n') - for pyname, cname in bymod[module]: - fp.write( - ' _%s = (PyTypeObject *)PyDict_GetItemString(' - 'moddict, "%s");\n' % (cname, pyname)) - fp.write(' if (_%s == NULL) {\n' % cname) - fp.write(' PyErr_SetString(PyExc_ImportError,\n') - fp.write(' "cannot import name %s from %s");\n' - % (pyname, module)) - fp.write(' return;\n') - fp.write(' }\n') - fp.write(' } else {\n') - fp.write(' PyErr_SetString(PyExc_ImportError,\n') - fp.write(' "could not import %s");\n' % module) - fp.write(' return;\n') - fp.write(' }\n') - fp.write('\n') - fp.write(overrides.get_init() + '\n') - fp.resetline() - -def write_registers(parser, overrides, fp): - for boxed in parser.boxes: - if overrides.is_type_ignored(boxed.c_name): - continue - fp.write(' pyg_register_boxed(d, "' + boxed.name + - '", ' + boxed.typecode + - ', &Py' + boxed.c_name + - '_Type);\n') - for pointer in parser.pointers: - if overrides.is_type_ignored(pointer.c_name): - continue - fp.write(' pyg_register_pointer(d, "' + pointer.name + - '", ' + pointer.typecode + - ', &Py' + pointer.c_name + '_Type);\n') - for interface in parser.interfaces: - if overrides.is_type_ignored(interface.c_name): - continue - fp.write(' pyg_register_interface(d, "' + interface.name + - '", '+ interface.typecode + ', &Py' + interface.c_name + - '_Type);\n') - if interface.interface_info is not None: - fp.write(' pyg_register_interface_info(%s, &%s);\n' % - (interface.typecode, interface.interface_info)) - - objects = parser.objects[:] - pos = 0 - while pos < len(objects): - parent = objects[pos].parent - for i in range(pos+1, len(objects)): - if objects[i].c_name == parent: - objects.insert(i+1, objects[pos]) - del objects[pos] - break - else: - pos = pos + 1 - for obj in objects: - if overrides.is_type_ignored(obj.c_name): - continue - bases = [] - if obj.parent != None: - bases.append(obj.parent) - bases = bases + obj.implements - if bases: - fp.write(' pygobject_register_class(d, "' + obj.c_name + - '", ' + obj.typecode + ', &Py' + obj.c_name + - '_Type, Py_BuildValue("(' + 'O' * len(bases) + ')", ' + - string.join(map(lambda s: '&Py'+s+'_Type', bases), ', ') + - '));\n') - else: - fp.write(' pygobject_register_class(d, "' + obj.c_name + - '", ' + obj.typecode + ', &Py' + obj.c_name + - '_Type, NULL);\n') - if obj.has_new_constructor_api: - fp.write(' pyg_set_object_has_new_constructor(%s);\n' % - obj.typecode) - else: - print >> sys.stderr, ( - "Warning: Constructor for %s needs to be updated to new API\n" - " See http://live.gnome.org/PyGTK_2fWhatsNew28" - "#update-constructors") % obj.c_name - if obj.class_init_func is not None: - fp.write(' pyg_register_class_init(%s, %s);\n' % - (obj.typecode, obj.class_init_func)) - #TODO: register mini-objects - miniobjects = parser.miniobjects[:] - for obj in miniobjects: - bases = [] - if obj.parent != None: - bases.append(obj.parent) - bases = bases + obj.implements - if bases: - fp.write(' pygstminiobject_register_class(d, "' + obj.c_name + - '", ' + obj.typecode + ', &Py' + obj.c_name + - '_Type, Py_BuildValue("(' + 'O' * len(bases) + ')", ' + - string.join(map(lambda s: '&Py'+s+'_Type', bases), ', ') + - '));\n') - else: - fp.write(' pygstminiobject_register_class(d, "' + obj.c_name + - '", ' + obj.typecode + ', &Py' + obj.c_name + - '_Type, NULL);\n') - - fp.write('}\n') - -def write_source(parser, overrides, prefix, fp=FileOutput(sys.stdout)): - write_headers(overrides.get_headers(), fp) - write_imports(overrides, fp) - write_type_declarations(parser, fp) - write_body(overrides.get_body(), fp) - write_classes(parser, overrides, fp) - - wrapper = Wrapper(parser, None, overrides, fp) - wrapper.write_functions(prefix) - - write_enums(parser, overrides, prefix, fp) - write_extension_init(overrides, prefix, fp) - write_registers(parser, overrides, fp) - -def register_types(parser): - for boxed in parser.boxes: - argtypes.matcher.register_boxed(boxed.c_name, boxed.typecode) - for pointer in parser.pointers: - argtypes.matcher.register_pointer(pointer.c_name, pointer.typecode) - for obj in parser.objects: - argtypes.matcher.register_object(obj.c_name, obj.parent, obj.typecode) - for obj in parser.miniobjects: - argtypes.matcher.register_miniobject(obj.c_name, obj.parent, obj.typecode) - for obj in parser.interfaces: - argtypes.matcher.register_object(obj.c_name, None, obj.typecode) - for enum in parser.enums: - if enum.deftype == 'flags': - argtypes.matcher.register_flag(enum.c_name, enum.typecode) - else: - argtypes.matcher.register_enum(enum.c_name, enum.typecode) - -usage = 'usage: codegen.py [-o overridesfile] [-p prefix] defsfile' -def main(argv): - o = override.Overrides() - prefix = 'pygtk' - outfilename = None - errorfilename = None - extendpath = [] - opts, args = getopt.getopt(argv[1:], "o:p:r:t:D:x", - ["override=", "prefix=", "register=", "outfilename=", - "load-types=", "errorfilename=", "extendpath="]) - defines = {} # -Dkey[=val] options - - for opt, arg in opts: - if opt in ('-x', '--extendpath'): - extendpath.append(arg) - extendpath.insert(0, os.getcwd()) - o = override.Overrides(path=extendpath) - - for opt, arg in opts: - if opt in ('-o', '--override'): - o = override.Overrides(arg, path=extendpath) - elif opt in ('-p', '--prefix'): - prefix = arg - elif opt in ('-r', '--register'): - # Warning: user has to make sure all -D options appear before -r - p = defsparser.DefsParser(arg, defines) - p.startParsing() - register_types(p) - del p - elif opt == '--outfilename': - outfilename = arg - elif opt == '--errorfilename': - errorfilename = arg - elif opt in ('-t', '--load-types'): - globals = {} - execfile(arg, globals) - elif opt == '-D': - nameval = arg.split('=') - try: - defines[nameval[0]] = nameval[1] - except IndexError: - defines[nameval[0]] = None - if len(args) < 1: - print >> sys.stderr, usage - return 1 - if errorfilename: - sys.stderr = open(errorfilename, "w") - p = defsparser.DefsParser(args[0], defines) - if not outfilename: - outfilename = os.path.splitext(args[0])[0] + '.c' - - p.startParsing() - - register_types(p) - write_source(p, o, prefix, FileOutput(sys.stdout, outfilename)) - - functions_coverage.printstats() - methods_coverage.printstats() - vproxies_coverage.printstats() - vaccessors_coverage.printstats() - iproxies_coverage.printstats() - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/bindings/python/codegen/definitions.py b/bindings/python/codegen/definitions.py deleted file mode 100644 index 911c8dd..0000000 --- a/bindings/python/codegen/definitions.py +++ /dev/null @@ -1,607 +0,0 @@ -# -*- Mode: Python; py-indent-offset: 4 -*- -import copy -import sys - -def get_valid_scheme_definitions(defs): - return [x for x in defs if isinstance(x, tuple) and len(x) >= 2] - -def unescape(s): - s = s.replace('\r\n', '\\r\\n').replace('\t', '\\t') - return s.replace('\r', '\\r').replace('\n', '\\n') - -def make_docstring(lines): - return "(char *) " + '\n'.join(['"%s"' % unescape(s) for s in lines]) - -# New Parameter class, wich emulates a tuple for compatibility reasons -class Parameter(object): - def __init__(self, ptype, pname, pdflt, pnull, pdir=None, keeprefcount = False): - self.ptype = ptype - self.pname = pname - self.pdflt = pdflt - self.pnull = pnull - self.pdir = pdir - self.keeprefcount = keeprefcount - - def __len__(self): return 4 - def __getitem__(self, i): - return (self.ptype, self.pname, self.pdflt, self.pnull)[i] - - def merge(self, old): - if old.pdflt is not None: - self.pdflt = old.pdflt - if old.pnull is not None: - self.pnull = old.pnull - -# Parameter for property based constructors -class Property(object): - def __init__(self, pname, optional, argname): - self.pname = pname - self.optional = optional - self.argname = argname - - def merge(self, old): - if old.optional is not None: - self.optional = old.optional - if old.argname is not None: - self.argname = old.argname - - -class Definition: - docstring = "NULL" - def __init__(self, *args): - """Create a new defs object of this type. The arguments are the - components of the definition""" - raise RuntimeError, "this is an abstract class" - def merge(self, old): - """Merge in customisations from older version of definition""" - raise RuntimeError, "this is an abstract class" - def write_defs(self, fp=sys.stdout): - """write out this definition in defs file format""" - raise RuntimeError, "this is an abstract class" - - def guess_return_value_ownership(self): - "return 1 if caller owns return value" - if getattr(self, 'is_constructor_of', False): - self.caller_owns_return = True - elif self.ret in ('char*', 'gchar*', 'string'): - self.caller_owns_return = True - else: - self.caller_owns_return = False - - -class ObjectDef(Definition): - def __init__(self, name, *args): - self.name = name - self.module = None - self.parent = None - self.c_name = None - self.typecode = None - self.fields = [] - self.implements = [] - self.class_init_func = None - self.has_new_constructor_api = False - for arg in get_valid_scheme_definitions(args): - if arg[0] == 'in-module': - self.module = arg[1] - elif arg[0] == 'docstring': - self.docstring = make_docstring(arg[1:]) - elif arg[0] == 'parent': - self.parent = arg[1] - elif arg[0] == 'c-name': - self.c_name = arg[1] - elif arg[0] == 'gtype-id': - self.typecode = arg[1] - elif arg[0] == 'fields': - for parg in arg[1:]: - self.fields.append((parg[0], parg[1])) - elif arg[0] == 'implements': - self.implements.append(arg[1]) - def merge(self, old): - # currently the .h parser doesn't try to work out what fields of - # an object structure should be public, so we just copy the list - # from the old version ... - self.fields = old.fields - self.implements = old.implements - def write_defs(self, fp=sys.stdout): - fp.write('(define-object ' + self.name + '\n') - if self.module: - fp.write(' (in-module "' + self.module + '")\n') - if self.parent != (None, None): - fp.write(' (parent "' + self.parent + '")\n') - for interface in self.implements: - fp.write(' (implements "' + interface + '")\n') - if self.c_name: - fp.write(' (c-name "' + self.c_name + '")\n') - if self.typecode: - fp.write(' (gtype-id "' + self.typecode + '")\n') - if self.fields: - fp.write(' (fields\n') - for (ftype, fname) in self.fields: - fp.write(' \'("' + ftype + '" "' + fname + '")\n') - fp.write(' )\n') - fp.write(')\n\n') - -class MiniObjectDef(Definition): - def __init__(self, name, *args): - self.name = name - self.module = None - self.parent = None - self.c_name = None - self.typecode = None - self.fields = [] - self.implements = [] - for arg in args: - if type(arg) != type(()) or len(arg) < 2: - continue - if arg[0] == 'in-module': - self.module = arg[1] - elif arg[0] == 'parent': - self.parent = arg[1] - elif arg[0] == 'c-name': - self.c_name = arg[1] - elif arg[0] == 'gtype-id': - self.typecode = arg[1] - elif arg[0] == 'fields': - for parg in arg[1:]: - self.fields.append((parg[0], parg[1])) - elif arg[0] == 'implements': - self.implements.append(arg[1]) - def merge(self, old): - # currently the .h parser doesn't try to work out what fields of - # an object structure should be public, so we just copy the list - # from the old version ... - self.fields = old.fields - self.implements = old.implements - def write_defs(self, fp=sys.stdout): - fp.write('(define-object ' + self.name + '\n') - if self.module: - fp.write(' (in-module "' + self.module + '")\n') - if self.parent != (None, None): - fp.write(' (parent "' + self.parent + '")\n') - for interface in self.implements: - fp.write(' (implements "' + interface + '")\n') - if self.c_name: - fp.write(' (c-name "' + self.c_name + '")\n') - if self.typecode: - fp.write(' (gtype-id "' + self.typecode + '")\n') - if self.fields: - fp.write(' (fields\n') - for (ftype, fname) in self.fields: - fp.write(' \'("' + ftype + '" "' + fname + '")\n') - fp.write(' )\n') - fp.write(')\n\n') - - -class InterfaceDef(Definition): - def __init__(self, name, *args): - self.name = name - self.module = None - self.c_name = None - self.typecode = None - self.vtable = None - self.fields = [] - self.interface_info = None - for arg in get_valid_scheme_definitions(args): - if arg[0] == 'in-module': - self.module = arg[1] - elif arg[0] == 'docstring': - self.docstring = make_docstring(arg[1:]) - elif arg[0] == 'c-name': - self.c_name = arg[1] - elif arg[0] == 'gtype-id': - self.typecode = arg[1] - elif arg[0] == 'vtable': - self.vtable = arg[1] - if self.vtable is None: - self.vtable = self.c_name + "Iface" - def write_defs(self, fp=sys.stdout): - fp.write('(define-interface ' + self.name + '\n') - if self.module: - fp.write(' (in-module "' + self.module + '")\n') - if self.c_name: - fp.write(' (c-name "' + self.c_name + '")\n') - if self.typecode: - fp.write(' (gtype-id "' + self.typecode + '")\n') - fp.write(')\n\n') - -class EnumDef(Definition): - def __init__(self, name, *args): - self.deftype = 'enum' - self.name = name - self.in_module = None - self.c_name = None - self.typecode = None - self.values = [] - for arg in get_valid_scheme_definitions(args): - if arg[0] == 'in-module': - self.in_module = arg[1] - elif arg[0] == 'c-name': - self.c_name = arg[1] - elif arg[0] == 'gtype-id': - self.typecode = arg[1] - elif arg[0] == 'values': - for varg in arg[1:]: - self.values.append((varg[0], varg[1])) - def merge(self, old): - pass - def write_defs(self, fp=sys.stdout): - fp.write('(define-' + self.deftype + ' ' + self.name + '\n') - if self.in_module: - fp.write(' (in-module "' + self.in_module + '")\n') - fp.write(' (c-name "' + self.c_name + '")\n') - fp.write(' (gtype-id "' + self.typecode + '")\n') - if self.values: - fp.write(' (values\n') - for name, val in self.values: - fp.write(' \'("' + name + '" "' + val + '")\n') - fp.write(' )\n') - fp.write(')\n\n') - -class FlagsDef(EnumDef): - def __init__(self, *args): - apply(EnumDef.__init__, (self,) + args) - self.deftype = 'flags' - -class BoxedDef(Definition): - def __init__(self, name, *args): - self.name = name - self.module = None - self.c_name = None - self.typecode = None - self.copy = None - self.release = None - self.fields = [] - for arg in get_valid_scheme_definitions(args): - if arg[0] == 'in-module': - self.module = arg[1] - elif arg[0] == 'c-name': - self.c_name = arg[1] - elif arg[0] == 'gtype-id': - self.typecode = arg[1] - elif arg[0] == 'copy-func': - self.copy = arg[1] - elif arg[0] == 'release-func': - self.release = arg[1] - elif arg[0] == 'fields': - for parg in arg[1:]: - self.fields.append((parg[0], parg[1])) - def merge(self, old): - # currently the .h parser doesn't try to work out what fields of - # an object structure should be public, so we just copy the list - # from the old version ... - self.fields = old.fields - def write_defs(self, fp=sys.stdout): - fp.write('(define-boxed ' + self.name + '\n') - if self.module: - fp.write(' (in-module "' + self.module + '")\n') - if self.c_name: - fp.write(' (c-name "' + self.c_name + '")\n') - if self.typecode: - fp.write(' (gtype-id "' + self.typecode + '")\n') - if self.copy: - fp.write(' (copy-func "' + self.copy + '")\n') - if self.release: - fp.write(' (release-func "' + self.release + '")\n') - if self.fields: - fp.write(' (fields\n') - for (ftype, fname) in self.fields: - fp.write(' \'("' + ftype + '" "' + fname + '")\n') - fp.write(' )\n') - fp.write(')\n\n') - -class PointerDef(Definition): - def __init__(self, name, *args): - self.name = name - self.module = None - self.c_name = None - self.typecode = None - self.fields = [] - for arg in get_valid_scheme_definitions(args): - if arg[0] == 'in-module': - self.module = arg[1] - elif arg[0] == 'c-name': - self.c_name = arg[1] - elif arg[0] == 'gtype-id': - self.typecode = arg[1] - elif arg[0] == 'fields': - for parg in arg[1:]: - self.fields.append((parg[0], parg[1])) - def merge(self, old): - # currently the .h parser doesn't try to work out what fields of - # an object structure should be public, so we just copy the list - # from the old version ... - self.fields = old.fields - def write_defs(self, fp=sys.stdout): - fp.write('(define-pointer ' + self.name + '\n') - if self.module: - fp.write(' (in-module "' + self.module + '")\n') - if self.c_name: - fp.write(' (c-name "' + self.c_name + '")\n') - if self.typecode: - fp.write(' (gtype-id "' + self.typecode + '")\n') - if self.fields: - fp.write(' (fields\n') - for (ftype, fname) in self.fields: - fp.write(' \'("' + ftype + '" "' + fname + '")\n') - fp.write(' )\n') - fp.write(')\n\n') - -class MethodDefBase(Definition): - def __init__(self, name, *args): - dump = 0 - self.name = name - self.ret = None - self.caller_owns_return = None - self.unblock_threads = None - self.c_name = None - self.typecode = None - self.of_object = None - self.params = [] # of form (type, name, default, nullok) - self.varargs = 0 - self.deprecated = None - for arg in get_valid_scheme_definitions(args): - if arg[0] == 'of-object': - self.of_object = arg[1] - elif arg[0] == 'docstring': - self.docstring = make_docstring(arg[1:]) - elif arg[0] == 'c-name': - self.c_name = arg[1] - elif arg[0] == 'gtype-id': - self.typecode = arg[1] - elif arg[0] == 'return-type': - self.ret = arg[1] - elif arg[0] == 'caller-owns-return': - self.caller_owns_return = arg[1] in ('t', '#t') - elif arg[0] == 'unblock-threads': - self.unblock_threads = arg[1] in ('t', '#t') - elif arg[0] == 'parameters': - for parg in arg[1:]: - ptype = parg[0] - pname = parg[1] - pdflt = None - pnull = 0 - pdir = None - keeprefcount = False - for farg in parg[2:]: - assert isinstance(farg, tuple) - if farg[0] == 'default': - pdflt = farg[1] - elif farg[0] == 'null-ok': - pnull = 1 - elif farg[0] == 'direction': - pdir = farg[1] - elif farg[0] == 'keep-refcount': - keeprefcount = True - self.params.append(Parameter(ptype, pname, pdflt, pnull, pdir, - keeprefcount=keeprefcount)) - elif arg[0] == 'varargs': - self.varargs = arg[1] in ('t', '#t') - elif arg[0] == 'deprecated': - self.deprecated = arg[1] - else: - sys.stderr.write("Warning: %s argument unsupported.\n" - % (arg[0])) - dump = 1 - if dump: - self.write_defs(sys.stderr) - - if self.caller_owns_return is None and self.ret is not None: - self.guess_return_value_ownership() - - def merge(self, old, parmerge): - self.caller_owns_return = old.caller_owns_return - self.varargs = old.varargs - # here we merge extra parameter flags accross to the new object. - if not parmerge: - self.params = copy.deepcopy(old.params) - return - for i in range(len(self.params)): - ptype, pname, pdflt, pnull = self.params[i] - for p2 in old.params: - if p2[1] == pname: - self.params[i] = (ptype, pname, p2[2], p2[3]) - break - def _write_defs(self, fp=sys.stdout): - if self.of_object != (None, None): - fp.write(' (of-object "' + self.of_object + '")\n') - if self.c_name: - fp.write(' (c-name "' + self.c_name + '")\n') - if self.typecode: - fp.write(' (gtype-id "' + self.typecode + '")\n') - if self.caller_owns_return: - fp.write(' (caller-owns-return #t)\n') - if self.unblock_threads: - fp.write(' (unblock_threads #t)\n') - if self.ret: - fp.write(' (return-type "' + self.ret + '")\n') - if self.deprecated: - fp.write(' (deprecated "' + self.deprecated + '")\n') - if self.params: - fp.write(' (parameters\n') - for ptype, pname, pdflt, pnull in self.params: - fp.write(' \'("' + ptype + '" "' + pname +'"') - if pdflt: fp.write(' (default "' + pdflt + '")') - if pnull: fp.write(' (null-ok)') - fp.write(')\n') - fp.write(' )\n') - if self.varargs: - fp.write(' (varargs #t)\n') - fp.write(')\n\n') - - -class MethodDef(MethodDefBase): - def __init__(self, name, *args): - MethodDefBase.__init__(self, name, *args) - for item in ('c_name', 'of_object'): - if self.__dict__[item] == None: - self.write_defs(sys.stderr) - raise RuntimeError, "definition missing required %s" % (item,) - - def write_defs(self, fp=sys.stdout): - fp.write('(define-method ' + self.name + '\n') - self._write_defs(fp) - -class VirtualDef(MethodDefBase): - def write_defs(self, fp=sys.stdout): - fp.write('(define-virtual ' + self.name + '\n') - self._write_defs(fp) - -class FunctionDef(Definition): - def __init__(self, name, *args): - dump = 0 - self.name = name - self.in_module = None - self.is_constructor_of = None - self.ret = None - self.caller_owns_return = None - self.unblock_threads = None - self.c_name = None - self.typecode = None - self.params = [] # of form (type, name, default, nullok) - self.varargs = 0 - self.deprecated = None - for arg in get_valid_scheme_definitions(args): - if arg[0] == 'in-module': - self.in_module = arg[1] - elif arg[0] == 'docstring': - self.docstring = make_docstring(arg[1:]) - elif arg[0] == 'is-constructor-of': - self.is_constructor_of = arg[1] - elif arg[0] == 'c-name': - self.c_name = arg[1] - elif arg[0] == 'gtype-id': - self.typecode = arg[1] - elif arg[0] == 'return-type': - self.ret = arg[1] - elif arg[0] == 'caller-owns-return': - self.caller_owns_return = arg[1] in ('t', '#t') - elif arg[0] == 'unblock-threads': - self.unblock_threads = arg[1] in ('t', '#t') - elif arg[0] == 'parameters': - for parg in arg[1:]: - ptype = parg[0] - pname = parg[1] - pdflt = None - pnull = 0 - keeprefcount = False - for farg in parg[2:]: - if farg[0] == 'default': - pdflt = farg[1] - elif farg[0] == 'null-ok': - pnull = 1 - elif farg[0] == 'keep-refcount': - keeprefcount = True - self.params.append(Parameter(ptype, pname, pdflt, pnull, - keeprefcount = keeprefcount)) - elif arg[0] == 'properties': - if self.is_constructor_of is None: - print >> sys.stderr, "Warning: (properties ...) "\ - "is only valid for constructors" - for prop in arg[1:]: - pname = prop[0] - optional = False - argname = pname - for farg in prop[1:]: - if farg[0] == 'optional': - optional = True - elif farg[0] == 'argname': - argname = farg[1] - self.params.append(Property(pname, optional, argname)) - elif arg[0] == 'varargs': - self.varargs = arg[1] in ('t', '#t') - elif arg[0] == 'deprecated': - self.deprecated = arg[1] - else: - sys.stderr.write("Warning: %s argument unsupported\n" - % (arg[0],)) - dump = 1 - if dump: - self.write_defs(sys.stderr) - - if self.caller_owns_return is None and self.ret is not None: - self.guess_return_value_ownership() - for item in ('c_name',): - if self.__dict__[item] == None: - self.write_defs(sys.stderr) - raise RuntimeError, "definition missing required %s" % (item,) - - _method_write_defs = MethodDef.__dict__['write_defs'] - - def merge(self, old, parmerge): - self.caller_owns_return = old.caller_owns_return - self.varargs = old.varargs - if not parmerge: - self.params = copy.deepcopy(old.params) - return - # here we merge extra parameter flags accross to the new object. - def merge_param(param): - for old_param in old.params: - if old_param.pname == param.pname: - if isinstance(old_param, Property): - # h2def never scans Property's, therefore if - # we have one it was manually written, so we - # keep it. - return copy.deepcopy(old_param) - else: - param.merge(old_param) - return param - raise RuntimeError, "could not find %s in old_parameters %r" % ( - param.pname, [p.pname for p in old.params]) - try: - self.params = map(merge_param, self.params) - except RuntimeError: - # parameter names changed and we can't find a match; it's - # safer to keep the old parameter list untouched. - self.params = copy.deepcopy(old.params) - - if not self.is_constructor_of: - try: - self.is_constructor_of = old.is_constructor_of - except AttributeError: - pass - if isinstance(old, MethodDef): - self.name = old.name - # transmogrify from function into method ... - self.write_defs = self._method_write_defs - self.of_object = old.of_object - del self.params[0] - def write_defs(self, fp=sys.stdout): - fp.write('(define-function ' + self.name + '\n') - if self.in_module: - fp.write(' (in-module "' + self.in_module + '")\n') - if self.is_constructor_of: - fp.write(' (is-constructor-of "' + self.is_constructor_of +'")\n') - if self.c_name: - fp.write(' (c-name "' + self.c_name + '")\n') - if self.typecode: - fp.write(' (gtype-id "' + self.typecode + '")\n') - if self.caller_owns_return: - fp.write(' (caller-owns-return #t)\n') - if self.unblock_threads: - fp.write(' (unblock-threads #t)\n') - if self.ret: - fp.write(' (return-type "' + self.ret + '")\n') - if self.deprecated: - fp.write(' (deprecated "' + self.deprecated + '")\n') - if self.params: - if isinstance(self.params[0], Parameter): - fp.write(' (parameters\n') - for ptype, pname, pdflt, pnull in self.params: - fp.write(' \'("' + ptype + '" "' + pname +'"') - if pdflt: fp.write(' (default "' + pdflt + '")') - if pnull: fp.write(' (null-ok)') - fp.write(')\n') - fp.write(' )\n') - elif isinstance(self.params[0], Property): - fp.write(' (properties\n') - for prop in self.params: - fp.write(' \'("' + prop.pname +'"') - if prop.optional: fp.write(' (optional)') - fp.write(')\n') - fp.write(' )\n') - else: - assert False, "strange parameter list %r" % self.params[0] - if self.varargs: - fp.write(' (varargs #t)\n') - - fp.write(')\n\n') diff --git a/bindings/python/codegen/defsparser.py b/bindings/python/codegen/defsparser.py deleted file mode 100644 index e24a969..0000000 --- a/bindings/python/codegen/defsparser.py +++ /dev/null @@ -1,143 +0,0 @@ -# -*- Mode: Python; py-indent-offset: 4 -*- -import os, sys -import scmexpr -from definitions import BoxedDef, EnumDef, FlagsDef, FunctionDef, \ - InterfaceDef, MethodDef, ObjectDef, MiniObjectDef, PointerDef, \ - VirtualDef - -class IncludeParser(scmexpr.Parser): - """A simple parser that follows include statements automatically""" - def include(self, filename): - if not os.path.isabs(filename): - filename = os.path.join(os.path.dirname(self.filename), filename) - - # set self.filename to the include name, to handle recursive includes - oldfile = self.filename - self.filename = filename - self.startParsing() - self.filename = oldfile - -class DefsParser(IncludeParser): - def __init__(self, arg, defines={}): - IncludeParser.__init__(self, arg) - self.objects = [] - self.miniobjects = [] - self.interfaces = [] - self.enums = [] # enums and flags - self.boxes = [] # boxed types - self.pointers = [] # pointer types - self.functions = [] # functions and methods - self.virtuals = [] # virtual methods - self.c_name = {} # hash of c names of functions - self.methods = {} # hash of methods of particular objects - self.defines = defines # -Dfoo=bar options, as dictionary - - def define_object(self, *args): - odef = apply(ObjectDef, args) - self.objects.append(odef) - self.c_name[odef.c_name] = odef - # TODO: define_mini_object - def define_miniobject(self, *args): - odef = apply(MiniObjectDef, args) - self.miniobjects.append(odef) - self.c_name[odef.c_name] = odef - def define_interface(self, *args): - idef = apply(InterfaceDef, args) - self.interfaces.append(idef) - self.c_name[idef.c_name] = idef - def define_enum(self, *args): - edef = apply(EnumDef, args) - self.enums.append(edef) - self.c_name[edef.c_name] = edef - def define_flags(self, *args): - fdef = apply(FlagsDef, args) - self.enums.append(fdef) - self.c_name[fdef.c_name] = fdef - def define_boxed(self, *args): - bdef = apply(BoxedDef, args) - self.boxes.append(bdef) - self.c_name[bdef.c_name] = bdef - def define_pointer(self, *args): - pdef = apply(PointerDef, args) - self.pointers.append(pdef) - self.c_name[pdef.c_name] = pdef - def define_function(self, *args): - fdef = apply(FunctionDef, args) - self.functions.append(fdef) - self.c_name[fdef.c_name] = fdef - def define_method(self, *args): - mdef = apply(MethodDef, args) - self.functions.append(mdef) - self.c_name[mdef.c_name] = mdef - def define_virtual(self, *args): - vdef = apply(VirtualDef, args) - self.virtuals.append(vdef) - def merge(self, old, parmerge): - for obj in self.objects: - if old.c_name.has_key(obj.c_name): - obj.merge(old.c_name[obj.c_name]) - for f in self.functions: - if old.c_name.has_key(f.c_name): - f.merge(old.c_name[f.c_name], parmerge) - - def printMissing(self, old): - for obj in self.objects: - if not old.c_name.has_key(obj.c_name): - obj.write_defs() - for f in self.functions: - if not old.c_name.has_key(f.c_name): - f.write_defs() - - def write_defs(self, fp=sys.stdout): - for obj in self.objects: - obj.write_defs(fp) - # TODO: Add miniobject - for obj in self.miniobjects: - obj.write_defs(fp) - for enum in self.enums: - enum.write_defs(fp) - for boxed in self.boxes: - boxed.write_defs(fp) - for pointer in self.pointers: - pointer.write_defs(fp) - for func in self.functions: - func.write_defs(fp) - - def find_object(self, c_name): - for obj in self.objects: - if obj.c_name == c_name: - return obj - else: - raise ValueError, 'object not found' - - def find_constructor(self, obj, overrides): - for func in self.functions: - if isinstance(func, FunctionDef) and \ - func.is_constructor_of == obj.c_name and \ - not overrides.is_ignored(func.c_name): - return func - - def find_methods(self, obj): - objname = obj.c_name - return filter(lambda func, on=objname: isinstance(func, MethodDef) and - func.of_object == on, self.functions) - - def find_virtuals(self, obj): - objname = obj.c_name - retval = filter(lambda func, on=objname: isinstance(func, VirtualDef) and - func.of_object == on, self.virtuals) - return retval - - def find_functions(self): - return filter(lambda func: isinstance(func, FunctionDef) and - not func.is_constructor_of, self.functions) - - def ifdef(self, *args): - if args[0] in self.defines: - for arg in args[1:]: - self.handle(arg) - - def ifndef(self, *args): - if args[0] not in self.defines: - for arg in args[1:]: - self.handle(arg) diff --git a/bindings/python/codegen/docextract.py b/bindings/python/codegen/docextract.py deleted file mode 100644 index e6c6505..0000000 --- a/bindings/python/codegen/docextract.py +++ /dev/null @@ -1,185 +0,0 @@ -# -*- Mode: Python; py-indent-offset: 4 -*- -'''Simple module for extracting GNOME style doc comments from C -sources, so I can use them for other purposes.''' - -import sys, os, string, re - -__all__ = ['extract'] - -class FunctionDoc: - def __init__(self): - self.name = None - self.params = [] - self.description = '' - self.ret = '' - def set_name(self, name): - self.name = name - def add_param(self, name, description): - if name == '...': - name = 'Varargs' - self.params.append((name, description)) - def append_to_last_param(self, extra): - self.params[-1] = (self.params[-1][0], self.params[-1][1] + extra) - def append_to_named_param(self, name, extra): - for i in range(len(self.params)): - if self.params[i][0] == name: - self.params[i] = (name, self.params[i][1] + extra) - return - # fall through to adding extra parameter ... - self.add_param(name, extra) - def append_description(self, extra): - self.description = self.description + extra - def append_return(self, extra): - self.ret = self.ret + extra - - def get_param_description(self, name): - for param, description in self.params: - if param == name: - return description - else: - return '' - -comment_start_pat = re.compile(r'^\s*/\*\*\s') -comment_end_pat = re.compile(r'^\s*\*+/') -comment_line_lead = re.compile(r'^\s*\*\s*') -funcname_pat = re.compile(r'^(\w+)\s*:?') -return_pat = re.compile(r'^(returns:|return\s+value:|returns\s*)(.*\n?)$', - re.IGNORECASE) -param_pat = re.compile(r'^@(\S+)\s*:(.*\n?)$') - -def parse_file(fp, doc_dict): - line = fp.readline() - in_comment_block = 0 - while line: - if not in_comment_block: - if comment_start_pat.match(line): - in_comment_block = 1 - cur_doc = FunctionDoc() - in_description = 0 - in_return = 0 - line = fp.readline() - continue - - # we are inside a comment block ... - if comment_end_pat.match(line): - if not cur_doc.name: - sys.stderr.write("no function name found in doc comment\n") - else: - doc_dict[cur_doc.name] = cur_doc - in_comment_block = 0 - line = fp.readline() - continue - - # inside a comment block, and not the end of the block ... - line = comment_line_lead.sub('', line) - if not line: line = '\n' - - if not cur_doc.name: - match = funcname_pat.match(line) - if match: - cur_doc.set_name(match.group(1)) - elif in_return: - match = return_pat.match(line) - if match: - # assume the last return statement was really part of the - # description - return_start = match.group(1) - cur_doc.ret = match.group(2) - cur_doc.description = cur_doc.description + return_start + \ - cur_doc.ret - else: - cur_doc.append_return(line) - elif in_description: - if line[:12] == 'Description:': - line = line[12:] - match = return_pat.match(line) - if match: - in_return = 1 - return_start = match.group(1) - cur_doc.append_return(match.group(2)) - else: - cur_doc.append_description(line) - elif line == '\n': - # end of parameters - in_description = 1 - else: - match = param_pat.match(line) - if match: - param = match.group(1) - desc = match.group(2) - if param == 'returns': - cur_doc.ret = desc - else: - cur_doc.add_param(param, desc) - else: - # must be continuation - try: - if param == 'returns': - cur_doc.append_return(line) - else: - cur_doc.append_to_last_param(line) - except: - sys.stderr.write('something weird while reading param\n') - line = fp.readline() - -def parse_dir(dir, doc_dict): - for file in os.listdir(dir): - if file in ('.', '..'): continue - path = os.path.join(dir, file) - if os.path.isdir(path): - parse_dir(path, doc_dict) - if len(file) > 2 and file[-2:] == '.c': - parse_file(open(path, 'r'), doc_dict) - -def extract(dirs, doc_dict=None): - if not doc_dict: doc_dict = {} - for dir in dirs: - parse_dir(dir, doc_dict) - return doc_dict - -tmpl_section_pat = re.compile(r'^<!-- ##### (\w+) (\w+) ##### -->$') -def parse_tmpl(fp, doc_dict): - cur_doc = None - - line = fp.readline() - while line: - match = tmpl_section_pat.match(line) - if match: - cur_doc = None # new input shouldn't affect the old doc dict - sect_type = match.group(1) - sect_name = match.group(2) - - if sect_type == 'FUNCTION': - cur_doc = doc_dict.get(sect_name) - if not cur_doc: - cur_doc = FunctionDoc() - cur_doc.set_name(sect_name) - doc_dict[sect_name] = cur_doc - elif line == '<!-- # Unused Parameters # -->\n': - cur_doc = None # don't worry about unused params. - elif cur_doc: - if line[:10] == '@Returns: ': - if string.strip(line[10:]): - cur_doc.append_return(line[10:]) - elif line[0] == '@': - pos = string.find(line, ':') - if pos >= 0: - cur_doc.append_to_named_param(line[1:pos], line[pos+1:]) - else: - cur_doc.append_description(line) - else: - cur_doc.append_description(line) - - line = fp.readline() - -def extract_tmpl(dirs, doc_dict=None): - if not doc_dict: doc_dict = {} - for dir in dirs: - for file in os.listdir(dir): - if file in ('.', '..'): continue - path = os.path.join(dir, file) - if os.path.isdir(path): - continue - if len(file) > 2 and file[-2:] == '.sgml': - parse_tmpl(open(path, 'r'), doc_dict) - return doc_dict diff --git a/bindings/python/codegen/docgen.py b/bindings/python/codegen/docgen.py deleted file mode 100644 index 6905a14..0000000 --- a/bindings/python/codegen/docgen.py +++ /dev/null @@ -1,752 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: Python; py-indent-offset: 4 -*- -import sys, os, string, re, getopt - -import defsparser -import definitions -import override -import docextract - -class Node: - def __init__(self, name, interfaces=[]): - self.name = name - self.interfaces = interfaces - self.subclasses = [] - def add_child(self, node): - self.subclasses.append(node) - -def build_object_tree(parser): - # reorder objects so that parent classes come first ... - objects = parser.objects[:] - pos = 0 - while pos < len(objects): - parent = objects[pos].parent - for i in range(pos+1, len(objects)): - if objects[i].c_name == parent: - objects.insert(i+1, objects[pos]) - del objects[pos] - break - else: - pos = pos + 1 - - root = Node(None) - nodes = { None: root } - for obj_def in objects: - print obj_def.name - parent_node = nodes[obj_def.parent] - node = Node(obj_def.c_name, obj_def.implements) - parent_node.add_child(node) - nodes[node.name] = node - - if parser.interfaces: - interfaces = Node('gobject.GInterface') - root.add_child(interfaces) - nodes[interfaces.name] = interfaces - for obj_def in parser.interfaces: - node = Node(obj_def.c_name) - interfaces.add_child(node) - nodes[node.name] = node - - if parser.boxes: - boxed = Node('gobject.GBoxed') - root.add_child(boxed) - nodes[boxed.name] = boxed - for obj_def in parser.boxes: - node = Node(obj_def.c_name) - boxed.add_child(node) - nodes[node.name] = node - - if parser.pointers: - pointers = Node('gobject.GPointer') - root.add_child(pointers) - nodes[pointers.name] = pointers - for obj_def in parser.pointers: - node = Node(obj_def.c_name) - pointers.add_child(node) - nodes[node.name] = node - - return root - -class DocWriter: - def __init__(self): - # parse the defs file - self.parser = defsparser.DefsParser(()) - self.overrides = override.Overrides() - self.classmap = {} - self.docs = {} - - def add_sourcedirs(self, source_dirs): - self.docs = docextract.extract(source_dirs, self.docs) - def add_tmpldirs(self, tmpl_dirs): - self.docs = docextract.extract_tmpl(tmpl_dirs, self.docs) - - def add_docs(self, defs_file, overrides_file, module_name): - '''parse information about a given defs file''' - self.parser.filename = defs_file - self.parser.startParsing(defs_file) - if overrides_file: - self.overrides.handle_file(overrides_file) - - for obj in self.parser.objects: - if not self.classmap.has_key(obj.c_name): - self.classmap[obj.c_name] = '%s.%s' % (module_name, obj.name) - for obj in self.parser.interfaces: - if not self.classmap.has_key(obj.c_name): - self.classmap[obj.c_name] = '%s.%s' % (module_name, obj.name) - for obj in self.parser.boxes: - if not self.classmap.has_key(obj.c_name): - self.classmap[obj.c_name] = '%s.%s' % (module_name, obj.name) - for obj in self.parser.pointers: - if not self.classmap.has_key(obj.c_name): - self.classmap[obj.c_name] = '%s.%s' % (module_name, obj.name) - - def pyname(self, name): - return self.classmap.get(name, name) - - def __compare(self, obja, objb): - return cmp(self.pyname(obja.c_name), self.pyname(objb.c_name)) - def output_docs(self, output_prefix): - files = [] - - # class hierarchy - hierarchy = build_object_tree(self.parser) - filename = self.create_filename('hierarchy', output_prefix) - fp = open(filename, 'w') - self.write_full_hierarchy(hierarchy, fp) - fp.close() - - obj_defs = self.parser.objects + self.parser.interfaces + \ - self.parser.boxes + self.parser.pointers - obj_defs.sort(self.__compare) - for obj_def in obj_defs: - filename = self.create_filename(obj_def.c_name, output_prefix) - fp = open(filename, 'w') - if isinstance(obj_def, definitions.ObjectDef): - self.output_object_docs(obj_def, fp) - elif isinstance(obj_def, definitions.InterfaceDef): - self.output_interface_docs(obj_def, fp) - elif isinstance(obj_def, definitions.BoxedDef): - self.output_boxed_docs(obj_def, fp) - elif isinstance(obj_def, definitions.PointerDef): - self.output_boxed_docs(obj_def, fp) - fp.close() - files.append((os.path.basename(filename), obj_def)) - - if files: - filename = self.create_toc_filename(output_prefix) - fp = open(filename, 'w') - self.output_toc(files, fp) - fp.close() - - def output_object_docs(self, obj_def, fp=sys.stdout): - self.write_class_header(obj_def.c_name, fp) - - self.write_heading('Synopsis', fp) - self.write_synopsis(obj_def, fp) - self.close_section(fp) - - # construct the inheritence hierarchy ... - ancestry = [ (obj_def.c_name, obj_def.implements) ] - try: - parent = obj_def.parent - while parent != None: - if parent == 'GObject': - ancestry.append(('GObject', [])) - parent = None - else: - parent_def = self.parser.find_object(parent) - ancestry.append((parent_def.c_name, parent_def.implements)) - parent = parent_def.parent - except ValueError: - pass - ancestry.reverse() - self.write_heading('Ancestry', fp) - self.write_hierarchy(obj_def.c_name, ancestry, fp) - self.close_section(fp) - - constructor = self.parser.find_constructor(obj_def, self.overrides) - if constructor: - self.write_heading('Constructor', fp) - self.write_constructor(constructor, - self.docs.get(constructor.c_name, None), - fp) - self.close_section(fp) - - methods = self.parser.find_methods(obj_def) - methods = filter(lambda meth, self=self: - not self.overrides.is_ignored(meth.c_name), methods) - if methods: - self.write_heading('Methods', fp) - for method in methods: - self.write_method(method, self.docs.get(method.c_name, None), fp) - self.close_section(fp) - - self.write_class_footer(obj_def.c_name, fp) - - def output_interface_docs(self, int_def, fp=sys.stdout): - self.write_class_header(int_def.c_name, fp) - - self.write_heading('Synopsis', fp) - self.write_synopsis(int_def, fp) - self.close_section(fp) - - methods = self.parser.find_methods(int_def) - methods = filter(lambda meth, self=self: - not self.overrides.is_ignored(meth.c_name), methods) - if methods: - self.write_heading('Methods', fp) - for method in methods: - self.write_method(method, self.docs.get(method.c_name, None), fp) - self.close_section(fp) - - self.write_class_footer(int_def.c_name, fp) - - def output_boxed_docs(self, box_def, fp=sys.stdout): - self.write_class_header(box_def.c_name, fp) - - self.write_heading('Synopsis', fp) - self.write_synopsis(box_def, fp) - self.close_section(fp) - - constructor = self.parser.find_constructor(box_def, self.overrides) - if constructor: - self.write_heading('Constructor', fp) - self.write_constructor(constructor, - self.docs.get(constructor.c_name, None), - fp) - self.close_section(fp) - - methods = self.parser.find_methods(box_def) - methods = filter(lambda meth, self=self: - not self.overrides.is_ignored(meth.c_name), methods) - if methods: - self.write_heading('Methods', fp) - for method in methods: - self.write_method(method, self.docs.get(method.c_name, None), fp) - self.close_section(fp) - - self.write_class_footer(box_def.c_name, fp) - - def output_toc(self, files, fp=sys.stdout): - fp.write('TOC\n\n') - for filename, obj_def in files: - fp.write(obj_def.c_name + ' - ' + filename + '\n') - - # override the following to create a more complex output format - def create_filename(self, obj_name, output_prefix): - '''Create output filename for this particular object''' - return output_prefix + '-' + string.lower(obj_name) + '.txt' - def create_toc_filename(self, output_prefix): - return self.create_filename(self, 'docs', output_prefix) - - def write_full_hierarchy(self, hierarchy, fp): - def handle_node(node, fp, indent=''): - for child in node.subclasses: - fp.write(indent + node.name) - if node.interfaces: - fp.write(' (implements ') - fp.write(string.join(node.interfaces, ', ')) - fp.write(')\n') - else: - fp.write('\n') - handle_node(child, fp, indent + ' ') - handle_node(hierarchy, fp) - - # these need to handle default args ... - def create_constructor_prototype(self, func_def): - return func_def.is_constructor_of + '(' + \ - string.join(map(lambda x: x[1], func_def.params), ', ') + \ - ')' - def create_function_prototype(self, func_def): - return func_def.name + '(' + \ - string.join(map(lambda x: x[1], func_def.params), ', ') + \ - ')' - def create_method_prototype(self, meth_def): - return meth_def.of_object + '.' + \ - meth_def.name + '(' + \ - string.join(map(lambda x: x[1], meth_def.params), ', ') + \ - ')' - - def write_class_header(self, obj_name, fp): - fp.write('Class %s\n' % obj_name) - fp.write('======%s\n\n' % ('=' * len(obj_name))) - def write_class_footer(self, obj_name, fp): - pass - def write_heading(self, text, fp): - fp.write('\n' + text + '\n' + ('-' * len(text)) + '\n') - def close_section(self, fp): - pass - def write_synopsis(self, obj_def, fp): - fp.write('class %s' % obj_def.c_name) - if isinstance(obj_def, definitions.ObjectDef): - bases = [] - if obj_def.parent: bases.append(obj_def.parent) - bases = bases = obj_def.implements - if bases: - fp.write('(%s)' % string.join(bases, ', ')) - fp.write(':\n') - - constructor = self.parser.find_constructor(obj_def, self.overrides) - if constructor: - prototype = self.create_constructor_prototype(constructor) - fp.write(' def %s\n' % prototype) - methods = self.parser.find_methods(obj_def) - methods = filter(lambda meth, self=self: - not self.overrides.is_ignored(meth.c_name), methods) - for meth in methods: - prototype = self.create_method_prototype(meth) - fp.write(' def %s\n' % prototype) - - def write_hierarchy(self, obj_name, ancestry, fp): - indent = '' - for name, interfaces in ancestry: - fp.write(indent + '+-- ' + name) - if interfaces: - fp.write(' (implements ') - fp.write(string.join(interfaces, ', ')) - fp.write(')\n') - else: - fp.write('\n') - indent = indent + ' ' - fp.write('\n') - def write_constructor(self, func_def, func_doc, fp): - prototype = self.create_constructor_prototype(func_def) - fp.write(prototype + '\n\n') - for type, name, dflt, null in func_def.params: - if func_doc: - descr = func_doc.get_param_description(name) - else: - descr = 'a ' + type - fp.write(' ' + name + ': ' + descr + '\n') - if func_def.ret and func_def.ret != 'none': - if func_doc and func_doc.ret: - descr = func_doc.ret - else: - descr = 'a ' + func_def.ret - fp.write(' Returns: ' + descr + '\n') - if func_doc and func_doc.description: - fp.write(func_doc.description) - fp.write('\n\n\n') - def write_method(self, meth_def, func_doc, fp): - prototype = self.create_method_prototype(meth_def) - fp.write(prototype + '\n\n') - for type, name, dflt, null in meth_def.params: - if func_doc: - descr = func_doc.get_param_description(name) - else: - descr = 'a ' + type - fp.write(' ' + name + ': ' + descr + '\n') - if meth_def.ret and meth_def.ret != 'none': - if func_doc and func_doc.ret: - descr = func_doc.ret - else: - descr = 'a ' + meth_def.ret - fp.write(' Returns: ' + descr + '\n') - if func_doc and func_doc.description: - fp.write('\n') - fp.write(func_doc.description) - fp.write('\n\n') - -class DocbookDocWriter(DocWriter): - def __init__(self, use_xml=0): - DocWriter.__init__(self) - self.use_xml = use_xml - - def create_filename(self, obj_name, output_prefix): - '''Create output filename for this particular object''' - stem = output_prefix + '-' + string.lower(obj_name) - if self.use_xml: - return stem + '.xml' - else: - return stem + '.sgml' - def create_toc_filename(self, output_prefix): - if self.use_xml: - return self.create_filename('classes', output_prefix) - else: - return self.create_filename('docs', output_prefix) - - # make string -> reference translation func - __transtable = [ '-' ] * 256 - for digit in '0123456789': - __transtable[ord(digit)] = digit - for letter in 'abcdefghijklmnopqrstuvwxyz': - __transtable[ord(letter)] = letter - __transtable[ord(string.upper(letter))] = letter - __transtable = string.join(__transtable, '') - - def make_class_ref(self, obj_name): - return 'class-' + string.translate(obj_name, self.__transtable) - def make_method_ref(self, meth_def): - return 'method-' + string.translate(meth_def.of_object, - self.__transtable) + \ - '--' + string.translate(meth_def.name, self.__transtable) - - __function_pat = re.compile(r'(\w+)\s*\(\)') - def __format_function(self, match): - info = self.parser.c_name.get(match.group(1), None) - if info: - if isinstance(info, defsparser.FunctionDef): - if info.is_constructor_of is not None: - # should have a link here - return '<function>%s()</function>' % \ - self.pyname(info.is_constructor_of) - else: - return '<function>' + info.name + '()</function>' - if isinstance(info, defsparser.MethodDef): - return '<link linkend="' + self.make_method_ref(info) + \ - '"><function>' + self.pyname(info.of_object) + '.' + \ - info.name + '()</function></link>' - # fall through through - return '<function>' + match.group(1) + '()</function>' - __parameter_pat = re.compile(r'\@(\w+)') - def __format_param(self, match): - return '<parameter>' + match.group(1) + '</parameter>' - __constant_pat = re.compile(r'\%(-?\w+)') - def __format_const(self, match): - return '<literal>' + match.group(1) + '</literal>' - __symbol_pat = re.compile(r'#([\w-]+)') - def __format_symbol(self, match): - info = self.parser.c_name.get(match.group(1), None) - if info: - if isinstance(info, defsparser.FunctionDef): - if info.is_constructor_of is not None: - # should have a link here - return '<methodname>' + self.pyname(info.is_constructor_of) + \ - '</methodname>' - else: - return '<function>' + info.name + '</function>' - if isinstance(info, defsparser.MethodDef): - return '<link linkend="' + self.make_method_ref(info) + \ - '"><methodname>' + self.pyname(info.of_object) + '.' + \ - info.name + '</methodname></link>' - if isinstance(info, defsparser.ObjectDef) or \ - isinstance(info, defsparser.InterfaceDef) or \ - isinstance(info, defsparser.BoxedDef) or \ - isinstance(info, defsparser.PointerDef): - return '<link linkend="' + self.make_class_ref(info.c_name) + \ - '"><classname>' + self.pyname(info.c_name) + \ - '</classname></link>' - # fall through through - return '<literal>' + match.group(1) + '</literal>' - - def reformat_text(self, text, singleline=0): - # replace special strings ... - text = self.__function_pat.sub(self.__format_function, text) - text = self.__parameter_pat.sub(self.__format_param, text) - text = self.__constant_pat.sub(self.__format_const, text) - text = self.__symbol_pat.sub(self.__format_symbol, text) - - # don't bother with <para> expansion for single line text. - if singleline: return text - - lines = string.split(string.strip(text), '\n') - for index in range(len(lines)): - if string.strip(lines[index]) == '': - lines[index] = '</para>\n<para>' - continue - lines.insert(0, '<para>') - lines.append('</para>') - return string.join(lines, '\n') - - # write out hierarchy - def write_full_hierarchy(self, hierarchy, fp): - def handle_node(node, fp, indent=''): - if node.name: - fp.write('%s<link linkend="%s">%s</link>' % - (indent, self.make_class_ref(node.name), - self.pyname(node.name))) - if node.interfaces: - fp.write(' (implements ') - for i in range(len(node.interfaces)): - fp.write('<link linkend="%s">%s</link>' % - (self.make_class_ref(node.interfaces[i]), - self.pyname(node.interfaces[i]))) - if i != len(node.interfaces) - 1: - fp.write(', ') - fp.write(')\n') - else: - fp.write('\n') - - indent = indent + ' ' - node.subclasses.sort(lambda a,b: - cmp(self.pyname(a.name), self.pyname(b.name))) - for child in node.subclasses: - handle_node(child, fp, indent) - if self.use_xml: - fp.write('<?xml version="1.0" standalone="no"?>\n') - fp.write('<!DOCTYPE synopsis PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"\n') - fp.write(' "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">\n') - fp.write('<synopsis>') - handle_node(hierarchy, fp) - fp.write('</synopsis>\n') - - # these need to handle default args ... - def create_constructor_prototype(self, func_def): - sgml = [ '<constructorsynopsis language="python">\n'] - sgml.append(' <methodname>__init__</methodname>\n') - for type, name, dflt, null in func_def.params: - sgml.append(' <methodparam><parameter>') - sgml.append(name) - sgml.append('</parameter>') - if dflt: - sgml.append('<initializer>') - sgml.append(dflt) - sgml.append('</initializer>') - sgml.append('</methodparam>\n') - if not func_def.params: - sgml.append(' <methodparam></methodparam>') - sgml.append(' </constructorsynopsis>') - return string.join(sgml, '') - def create_function_prototype(self, func_def): - sgml = [ '<funcsynopsis language="python">\n <funcprototype>\n'] - sgml.append(' <funcdef><function>') - sgml.append(func_def.name) - sgml.append('</function></funcdef>\n') - for type, name, dflt, null in func_def.params: - sgml.append(' <paramdef><parameter>') - sgml.append(name) - sgml.append('</parameter>') - if dflt: - sgml.append('<initializer>') - sgml.append(dflt) - sgml.append('</initializer>') - sgml.append('</paramdef>\n') - if not func_def.params: - sgml.append(' <paramdef></paramdef') - sgml.append(' </funcprototype>\n </funcsynopsis>') - return string.join(sgml, '') - def create_method_prototype(self, meth_def, addlink=0): - sgml = [ '<methodsynopsis language="python">\n'] - sgml.append(' <methodname>') - if addlink: - sgml.append('<link linkend="%s">' % self.make_method_ref(meth_def)) - sgml.append(self.pyname(meth_def.name)) - if addlink: - sgml.append('</link>') - sgml.append('</methodname>\n') - for type, name, dflt, null in meth_def.params: - sgml.append(' <methodparam><parameter>') - sgml.append(name) - sgml.append('</parameter>') - if dflt: - sgml.append('<initializer>') - sgml.append(dflt) - sgml.append('</initializer>') - sgml.append('</methodparam>\n') - if not meth_def.params: - sgml.append(' <methodparam></methodparam>') - sgml.append(' </methodsynopsis>') - return string.join(sgml, '') - - def write_class_header(self, obj_name, fp): - if self.use_xml: - fp.write('<?xml version="1.0" standalone="no"?>\n') - fp.write('<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"\n') - fp.write(' "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">\n') - fp.write('<refentry id="' + self.make_class_ref(obj_name) + '">\n') - fp.write(' <refmeta>\n') - fp.write(' <refentrytitle>%s</refentrytitle>\n' - % self.pyname(obj_name)) - fp.write(' <manvolnum>3</manvolnum>\n') - fp.write(' <refmiscinfo>PyGTK Docs</refmiscinfo>\n') - fp.write(' </refmeta>\n\n') - fp.write(' <refnamediv>\n') - fp.write(' <refname>%s</refname><refpurpose></refpurpose>\n' - % self.pyname(obj_name)) - fp.write(' </refnamediv>\n\n') - def write_class_footer(self, obj_name, fp): - fp.write('</refentry>\n') - def write_heading(self, text, fp): - fp.write(' <refsect1>\n') - fp.write(' <title>' + text + '</title>\n\n') - def close_section(self, fp): - fp.write(' </refsect1>\n') - - def write_synopsis(self, obj_def, fp): - fp.write('<classsynopsis language="python">\n') - fp.write(' <ooclass><classname>%s</classname></ooclass>\n' - % self.pyname(obj_def.c_name)) - if isinstance(obj_def, definitions.ObjectDef): - if obj_def.parent: - fp.write(' <ooclass><classname><link linkend="%s">%s' - '</link></classname></ooclass>\n' - % (self.make_class_ref(obj_def.parent), - self.pyname(obj_def.parent))) - for base in obj_def.implements: - fp.write(' <ooclass><classname><link linkend="%s">%s' - '</link></classname></ooclass>\n' - % (self.make_class_ref(base), self.pyname(base))) - elif isinstance(obj_def, definitions.InterfaceDef): - fp.write(' <ooclass><classname>gobject.GInterface' - '</classname></ooclass>\n') - elif isinstance(obj_def, definitions.BoxedDef): - fp.write(' <ooclass><classname>gobject.GBoxed' - '</classname></ooclass>\n') - elif isinstance(obj_def, definitions.PointerDef): - fp.write(' <ooclass><classname>gobject.GPointer' - '</classname></ooclass>\n') - - constructor = self.parser.find_constructor(obj_def, self.overrides) - if constructor: - fp.write('%s\n' % self.create_constructor_prototype(constructor)) - methods = self.parser.find_methods(obj_def) - methods = filter(lambda meth, self=self: - not self.overrides.is_ignored(meth.c_name), methods) - for meth in methods: - fp.write('%s\n' % self.create_method_prototype(meth, addlink=1)) - fp.write('</classsynopsis>\n\n') - - def write_hierarchy(self, obj_name, ancestry, fp): - fp.write('<synopsis>') - indent = '' - for name, interfaces in ancestry: - fp.write(indent + '+-- <link linkend="' + - self.make_class_ref(name) + '">'+ self.pyname(name) + '</link>') - if interfaces: - fp.write(' (implements ') - for i in range(len(interfaces)): - fp.write('<link linkend="%s">%s</link>' % - (self.make_class_ref(interfaces[i]), - self.pyname(interfaces[i]))) - if i != len(interfaces) - 1: - fp.write(', ') - fp.write(')\n') - else: - fp.write('\n') - indent = indent + ' ' - fp.write('</synopsis>\n\n') - - def write_params(self, params, ret, func_doc, fp): - if not params and (not ret or ret == 'none'): - return - fp.write(' <variablelist>\n') - for type, name, dflt, null in params: - if func_doc: - descr = string.strip(func_doc.get_param_description(name)) - else: - descr = 'a ' + type - fp.write(' <varlistentry>\n') - fp.write(' <term><parameter>%s</parameter> :</term>\n' % name) - fp.write(' <listitem><simpara>%s</simpara></listitem>\n' % - self.reformat_text(descr, singleline=1)) - fp.write(' </varlistentry>\n') - if ret and ret != 'none': - if func_doc and func_doc.ret: - descr = string.strip(func_doc.ret) - else: - descr = 'a ' + ret - fp.write(' <varlistentry>\n') - fp.write(' <term><emphasis>Returns</emphasis> :</term>\n') - fp.write(' <listitem><simpara>%s</simpara></listitem>\n' % - self.reformat_text(descr, singleline=1)) - fp.write(' </varlistentry>\n') - fp.write(' </variablelist>\n') - - def write_constructor(self, func_def, func_doc, fp): - prototype = self.create_constructor_prototype(func_def) - fp.write('<programlisting>%s</programlisting>\n' % prototype) - self.write_params(func_def.params, func_def.ret, func_doc, fp) - - if func_doc and func_doc.description: - fp.write(self.reformat_text(func_doc.description)) - fp.write('\n\n\n') - - def write_method(self, meth_def, func_doc, fp): - fp.write(' <refsect2 id="' + self.make_method_ref(meth_def) + '">\n') - fp.write(' <title>' + self.pyname(meth_def.of_object) + '.' + - meth_def.name + '</title>\n\n') - prototype = self.create_method_prototype(meth_def) - fp.write('<programlisting>%s</programlisting>\n' % prototype) - self.write_params(meth_def.params, meth_def.ret, func_doc, fp) - if func_doc and func_doc.description: - fp.write(self.reformat_text(func_doc.description)) - fp.write(' </refsect2>\n\n\n') - - def output_toc(self, files, fp=sys.stdout): - if self.use_xml: - fp.write('<?xml version="1.0" standalone="no"?>\n') - fp.write('<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"\n') - fp.write(' "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">\n') - #for filename, obj_def in files: - # fp.write(' <!ENTITY ' + string.translate(obj_def.c_name, - # self.__transtable) + - # ' SYSTEM "' + filename + '" >\n') - #fp.write(']>\n\n') - - #fp.write('<reference id="class-reference">\n') - #fp.write(' <title>Class Documentation</title>\n') - #for filename, obj_def in files: - # fp.write('&' + string.translate(obj_def.c_name, - # self.__transtable) + ';\n') - #fp.write('</reference>\n') - - fp.write('<reference id="class-reference" xmlns:xi="http://www.w3.org/2001/XInclude">\n') - fp.write(' <title>Class Reference</title>\n') - for filename, obj_def in files: - fp.write(' <xi:include href="%s"/>\n' % filename) - fp.write('</reference>\n') - else: - fp.write('<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.1.2//EN" [\n') - for filename, obj_def in files: - fp.write(' <!ENTITY ' + string.translate(obj_def.c_name, - self.__transtable) + - ' SYSTEM "' + filename + '" >\n') - fp.write(']>\n\n') - - fp.write('<book id="index">\n\n') - fp.write(' <bookinfo>\n') - fp.write(' <title>PyGTK Docs</title>\n') - fp.write(' <authorgroup>\n') - fp.write(' <author>\n') - fp.write(' <firstname>James</firstname>\n') - fp.write(' <surname>Henstridge</surname>\n') - fp.write(' </author>\n') - fp.write(' </authorgroup>\n') - fp.write(' </bookinfo>\n\n') - - fp.write(' <chapter id="class-hierarchy">\n') - fp.write(' <title>Class Hierarchy</title>\n') - fp.write(' <para>Not done yet</para>\n') - fp.write(' </chapter>\n\n') - - fp.write(' <reference id="class-reference">\n') - fp.write(' <title>Class Documentation</title>\n') - for filename, obj_def in files: - fp.write('&' + string.translate(obj_def.c_name, - self.__transtable) + ';\n') - - fp.write(' </reference>\n') - fp.write('</book>\n') - -if __name__ == '__main__': - try: - opts, args = getopt.getopt(sys.argv[1:], "d:s:o:", - ["defs-file=", "override=", "source-dir=", - "output-prefix="]) - except getopt.error, e: - sys.stderr.write('docgen.py: %s\n' % e) - sys.stderr.write( - 'usage: docgen.py -d file.defs [-s /src/dir] [-o output-prefix]\n') - sys.exit(1) - defs_file = None - overrides_file = None - source_dirs = [] - output_prefix = 'docs' - for opt, arg in opts: - if opt in ('-d', '--defs-file'): - defs_file = arg - if opt in ('--override',): - overrides_file = arg - elif opt in ('-s', '--source-dir'): - source_dirs.append(arg) - elif opt in ('-o', '--output-prefix'): - output_prefix = arg - if len(args) != 0 or not defs_file: - sys.stderr.write( - 'usage: docgen.py -d file.defs [-s /src/dir] [-o output-prefix]\n') - sys.exit(1) - - d = DocbookDocWriter() - d.add_sourcedirs(source_dirs) - d.add_docs(defs_file, overrides_file, 'gtk') - d.output_docs(output_prefix) diff --git a/bindings/python/codegen/fileprefix.override b/bindings/python/codegen/fileprefix.override deleted file mode 100644 index 4e280c5..0000000 --- a/bindings/python/codegen/fileprefix.override +++ /dev/null @@ -1,12 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4 -*- */ -%% -headers -/* include any required headers here */ -%% -init - /* include any code here that needs to be executed before the - * extension classes get initialised */ -%% - -/* you should add appropriate ignore, ignore-glob and - * override sections here */ diff --git a/bindings/python/codegen/fileprefixmodule.c b/bindings/python/codegen/fileprefixmodule.c deleted file mode 100644 index 4361d64..0000000 --- a/bindings/python/codegen/fileprefixmodule.c +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4 -*- */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include <Python.h> -#include <pygtk.h> - -/* include any extra headers needed here */ - -void prefix_register_classes(PyObject *d); -extern PyMethodDef prefix_functions[]; - -DL_EXPORT(void) -initmodule(void) -{ - PyObject *m, *d; - - /* perform any initialisation required by the library here */ - - m = Py_InitModule("module", prefix_functions); - d = PyModule_GetDict(m); - - init_pygtk(); - - prefix_register_classes(d); - - /* add anything else to the module dictionary (such as constants) */ - - if (PyErr_Occurred()) - Py_FatalError("could not initialise module module"); -} diff --git a/bindings/python/codegen/h2def.py b/bindings/python/codegen/h2def.py deleted file mode 100755 index d4b2135..0000000 --- a/bindings/python/codegen/h2def.py +++ /dev/null @@ -1,536 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: Python; py-indent-offset: 4 -*- -# Search through a header file looking for function prototypes. -# For each prototype, generate a scheme style definition. -# GPL'ed -# Toby D. Reeves <toby@max.rl.plh.af.mil> -# -# Modified by James Henstridge <james@daa.com.au> to output stuff in -# Havoc's new defs format. Info on this format can be seen at: -# http://www.gnome.org/mailing-lists/archives/gtk-devel-list/2000-January/0085.shtml -# Updated to be PEP-8 compatible and refactored to use OOP - -import getopt -import os -import re -import string -import sys - -import defsparser - -# ------------------ Create typecodes from typenames --------- - -_upperstr_pat1 = re.compile(r'([^A-Z])([A-Z])') -_upperstr_pat2 = re.compile(r'([A-Z][A-Z])([A-Z][0-9a-z])') -_upperstr_pat3 = re.compile(r'^([A-Z])([A-Z])') - -def to_upper_str(name): - """Converts a typename to the equivalent upercase and underscores - name. This is used to form the type conversion macros and enum/flag - name variables""" - name = _upperstr_pat1.sub(r'\1_\2', name) - name = _upperstr_pat2.sub(r'\1_\2', name) - name = _upperstr_pat3.sub(r'\1_\2', name, count=1) - return string.upper(name) - -def typecode(typename): - """create a typecode (eg. GTK_TYPE_WIDGET) from a typename""" - return string.replace(to_upper_str(typename), '_', '_TYPE_', 1) - - -# ------------------ Find object definitions ----------------- - -def strip_comments(buf): - parts = [] - lastpos = 0 - while 1: - pos = string.find(buf, '/*', lastpos) - if pos >= 0: - parts.append(buf[lastpos:pos]) - pos = string.find(buf, '*/', pos) - if pos >= 0: - lastpos = pos + 2 - else: - break - else: - parts.append(buf[lastpos:]) - break - return string.join(parts, '') - -obj_name_pat = "[A-Z][a-z]*[A-Z][A-Za-z0-9]*" - -split_prefix_pat = re.compile('([A-Z]+[a-z]*)([A-Za-z0-9]+)') - -def find_obj_defs(buf, objdefs=[]): - """ - Try to find object definitions in header files. - """ - - # filter out comments from buffer. - buf = strip_comments(buf) - - maybeobjdefs = [] # contains all possible objects from file - - # first find all structures that look like they may represent a GtkObject - pat = re.compile("struct _(" + obj_name_pat + ")\s*{\s*" + - "(" + obj_name_pat + ")\s+", re.MULTILINE) - pos = 0 - while pos < len(buf): - m = pat.search(buf, pos) - if not m: break - maybeobjdefs.append((m.group(1), m.group(2))) - pos = m.end() - - # handle typedef struct { ... } style struct defs. - pat = re.compile("typedef struct\s+[_\w]*\s*{\s*" + - "(" + obj_name_pat + ")\s+[^}]*}\s*" + - "(" + obj_name_pat + ")\s*;", re.MULTILINE) - pos = 0 - while pos < len(buf): - m = pat.search(buf, pos) - if not m: break - maybeobjdefs.append((m.group(2), m.group(2))) - pos = m.end() - - # now find all structures that look like they might represent a class: - pat = re.compile("struct _(" + obj_name_pat + ")Class\s*{\s*" + - "(" + obj_name_pat + ")Class\s+", re.MULTILINE) - pos = 0 - while pos < len(buf): - m = pat.search(buf, pos) - if not m: break - t = (m.group(1), m.group(2)) - # if we find an object structure together with a corresponding - # class structure, then we have probably found a GtkObject subclass. - if t in maybeobjdefs: - objdefs.append(t) - pos = m.end() - - pat = re.compile("typedef struct\s+[_\w]*\s*{\s*" + - "(" + obj_name_pat + ")Class\s+[^}]*}\s*" + - "(" + obj_name_pat + ")Class\s*;", re.MULTILINE) - pos = 0 - while pos < len(buf): - m = pat.search(buf, pos) - if not m: break - t = (m.group(2), m.group(1)) - # if we find an object structure together with a corresponding - # class structure, then we have probably found a GtkObject subclass. - if t in maybeobjdefs: - objdefs.append(t) - pos = m.end() - - # now find all structures that look like they might represent - # a class inherited from GTypeInterface: - pat = re.compile("struct _(" + obj_name_pat + ")Class\s*{\s*" + - "GTypeInterface\s+", re.MULTILINE) - pos = 0 - while pos < len(buf): - m = pat.search(buf, pos) - if not m: break - t = (m.group(1), '') - t2 = (m.group(1)+'Class', 'GTypeInterface') - # if we find an object structure together with a corresponding - # class structure, then we have probably found a GtkObject subclass. - if t2 in maybeobjdefs: - objdefs.append(t) - pos = m.end() - - # now find all structures that look like they might represent - # an Iface inherited from GTypeInterface: - pat = re.compile("struct _(" + obj_name_pat + ")Iface\s*{\s*" + - "GTypeInterface\s+", re.MULTILINE) - pos = 0 - while pos < len(buf): - m = pat.search(buf, pos) - if not m: break - t = (m.group(1), '') - t2 = (m.group(1)+'Iface', 'GTypeInterface') - # if we find an object structure together with a corresponding - # class structure, then we have probably found a GtkObject subclass. - if t2 in maybeobjdefs: - objdefs.append(t) - pos = m.end() - -def sort_obj_defs(objdefs): - objdefs.sort() # not strictly needed, but looks nice - pos = 0 - while pos < len(objdefs): - klass,parent = objdefs[pos] - for i in range(pos+1, len(objdefs)): - # parent below subclass ... reorder - if objdefs[i][0] == parent: - objdefs.insert(i+1, objdefs[pos]) - del objdefs[pos] - break - else: - pos = pos + 1 - return objdefs - -# ------------------ Find enum definitions ----------------- - -def find_enum_defs(buf, enums=[]): - # strip comments - # bulk comments - buf = strip_comments(buf) - - buf = re.sub('\n', ' ', buf) - - enum_pat = re.compile(r'enum\s*{([^}]*)}\s*([A-Z][A-Za-z]*)(\s|;)') - splitter = re.compile(r'\s*,\s', re.MULTILINE) - pos = 0 - while pos < len(buf): - m = enum_pat.search(buf, pos) - if not m: break - - name = m.group(2) - vals = m.group(1) - isflags = string.find(vals, '<<') >= 0 - entries = [] - for val in splitter.split(vals): - if not string.strip(val): continue - entries.append(string.split(val)[0]) - if name != 'GdkCursorType': - enums.append((name, isflags, entries)) - - pos = m.end() - -# ------------------ Find function definitions ----------------- - -def clean_func(buf): - """ - Ideally would make buf have a single prototype on each line. - Actually just cuts out a good deal of junk, but leaves lines - where a regex can figure prototypes out. - """ - # bulk comments - buf = strip_comments(buf) - - # compact continued lines - pat = re.compile(r"""\\\n""", re.MULTILINE) - buf = pat.sub('', buf) - - # Preprocess directives - pat = re.compile(r"""^[#].*?$""", re.MULTILINE) - buf = pat.sub('', buf) - - #typedefs, stucts, and enums - pat = re.compile(r"""^(typedef|struct|enum)(\s|.|\n)*?;\s*""", - re.MULTILINE) - buf = pat.sub('', buf) - - #strip DECLS macros - pat = re.compile(r"""G_BEGIN_DECLS|BEGIN_LIBGTOP_DECLS""", re.MULTILINE) - buf = pat.sub('', buf) - - #extern "C" - pat = re.compile(r"""^\s*(extern)\s+\"C\"\s+{""", re.MULTILINE) - buf = pat.sub('', buf) - - #multiple whitespace - pat = re.compile(r"""\s+""", re.MULTILINE) - buf = pat.sub(' ', buf) - - #clean up line ends - pat = re.compile(r""";\s*""", re.MULTILINE) - buf = pat.sub('\n', buf) - buf = buf.lstrip() - - #associate *, &, and [] with type instead of variable - #pat = re.compile(r'\s+([*|&]+)\s*(\w+)') - pat = re.compile(r' \s* ([*|&]+) \s* (\w+)', re.VERBOSE) - buf = pat.sub(r'\1 \2', buf) - pat = re.compile(r'\s+ (\w+) \[ \s* \]', re.VERBOSE) - buf = pat.sub(r'[] \1', buf) - - # make return types that are const work. - buf = string.replace(buf, 'G_CONST_RETURN ', 'const-') - buf = string.replace(buf, 'const ', 'const-') - - return buf - -proto_pat=re.compile(r""" -(?P<ret>(-|\w|\&|\*)+\s*) # return type -\s+ # skip whitespace -(?P<func>\w+)\s*[(] # match the function name until the opening ( -\s*(?P<args>.*?)\s*[)] # group the function arguments -""", re.IGNORECASE|re.VERBOSE) -#""" -arg_split_pat = re.compile("\s*,\s*") - -get_type_pat = re.compile(r'(const-)?([A-Za-z0-9]+)\*?\s+') -pointer_pat = re.compile('.*\*$') -func_new_pat = re.compile('(\w+)_new$') - -class DefsWriter: - def __init__(self, fp=None, prefix=None, verbose=False, - defsfilter=None): - if not fp: - fp = sys.stdout - - self.fp = fp - self.prefix = prefix - self.verbose = verbose - - self._enums = {} - self._objects = {} - self._functions = {} - if defsfilter: - filter = defsparser.DefsParser(defsfilter) - filter.startParsing() - for func in filter.functions + filter.methods.values(): - self._functions[func.c_name] = func - for obj in filter.objects + filter.boxes + filter.interfaces: - self._objects[obj.c_name] = func - for obj in filter.enums: - self._enums[obj.c_name] = func - - def write_def(self, deffile): - buf = open(deffile).read() - - self.fp.write('\n;; From %s\n\n' % os.path.basename(deffile)) - self._define_func(buf) - self.fp.write('\n') - - def write_enum_defs(self, enums, fp=None): - if not fp: - fp = self.fp - - fp.write(';; Enumerations and flags ...\n\n') - trans = string.maketrans(string.uppercase + '_', - string.lowercase + '-') - filter = self._enums - for cname, isflags, entries in enums: - if filter: - if cname in filter: - continue - name = cname - module = None - m = split_prefix_pat.match(cname) - if m: - module = m.group(1) - name = m.group(2) - if isflags: - fp.write('(define-flags ' + name + '\n') - else: - fp.write('(define-enum ' + name + '\n') - if module: - fp.write(' (in-module "' + module + '")\n') - fp.write(' (c-name "' + cname + '")\n') - fp.write(' (gtype-id "' + typecode(cname) + '")\n') - prefix = entries[0] - for ent in entries: - # shorten prefix til we get a match ... - # and handle GDK_FONT_FONT, GDK_FONT_FONTSET case - while ent[:len(prefix)] != prefix or len(prefix) >= len(ent): - prefix = prefix[:-1] - prefix_len = len(prefix) - fp.write(' (values\n') - for ent in entries: - fp.write(' \'("%s" "%s")\n' % - (string.translate(ent[prefix_len:], trans), ent)) - fp.write(' )\n') - fp.write(')\n\n') - - def write_obj_defs(self, objdefs, fp=None): - if not fp: - fp = self.fp - - fp.write(';; -*- scheme -*-\n') - fp.write('; object definitions ...\n') - - filter = self._objects - for klass, parent in objdefs: - if filter: - if klass in filter: - continue - m = split_prefix_pat.match(klass) - cmodule = None - cname = klass - if m: - cmodule = m.group(1) - cname = m.group(2) - fp.write('(define-object ' + cname + '\n') - if cmodule: - fp.write(' (in-module "' + cmodule + '")\n') - if parent: - fp.write(' (parent "' + parent + '")\n') - fp.write(' (c-name "' + klass + '")\n') - fp.write(' (gtype-id "' + typecode(klass) + '")\n') - # should do something about accessible fields - fp.write(')\n\n') - - def _define_func(self, buf): - buf = clean_func(buf) - buf = string.split(buf,'\n') - filter = self._functions - for p in buf: - if not p: - continue - m = proto_pat.match(p) - if m == None: - if self.verbose: - sys.stderr.write('No match:|%s|\n' % p) - continue - func = m.group('func') - if func[0] == '_': - continue - if filter: - if func in filter: - continue - ret = m.group('ret') - args = m.group('args') - args = arg_split_pat.split(args) - for i in range(len(args)): - spaces = string.count(args[i], ' ') - if spaces > 1: - args[i] = string.replace(args[i], ' ', '-', spaces - 1) - - self._write_func(func, ret, args) - - def _write_func(self, name, ret, args): - if len(args) >= 1: - # methods must have at least one argument - munged_name = name.replace('_', '') - m = get_type_pat.match(args[0]) - if m: - obj = m.group(2) - if munged_name[:len(obj)] == obj.lower(): - self._write_method(obj, name, ret, args) - return - - if self.prefix: - l = len(self.prefix) - if name[:l] == self.prefix and name[l] == '_': - fname = name[l+1:] - else: - fname = name - else: - fname = name - - # it is either a constructor or normal function - self.fp.write('(define-function ' + fname + '\n') - self.fp.write(' (c-name "' + name + '")\n') - - # Hmmm... Let's asume that a constructor function name - # ends with '_new' and it returns a pointer. - m = func_new_pat.match(name) - if pointer_pat.match(ret) and m: - cname = '' - for s in m.group(1).split ('_'): - cname += s.title() - if cname != '': - self.fp.write(' (is-constructor-of "' + cname + '")\n') - - self._write_return(ret) - self._write_arguments(args) - - def _write_method(self, obj, name, ret, args): - regex = string.join(map(lambda x: x+'_?', string.lower(obj)),'') - mname = re.sub(regex, '', name, 1) - if self.prefix: - l = len(self.prefix) + 1 - if mname[:l] == self.prefix and mname[l+1] == '_': - mname = mname[l+1:] - self.fp.write('(define-method ' + mname + '\n') - self.fp.write(' (of-object "' + obj + '")\n') - self.fp.write(' (c-name "' + name + '")\n') - self._write_return(ret) - self._write_arguments(args[1:]) - - def _write_return(self, ret): - if ret != 'void': - self.fp.write(' (return-type "' + ret + '")\n') - else: - self.fp.write(' (return-type "none")\n') - - def _write_arguments(self, args): - is_varargs = 0 - has_args = len(args) > 0 - for arg in args: - if arg == '...': - is_varargs = 1 - elif arg in ('void', 'void '): - has_args = 0 - if has_args: - self.fp.write(' (parameters\n') - for arg in args: - if arg != '...': - tupleArg = tuple(string.split(arg)) - if len(tupleArg) == 2: - self.fp.write(' \'("%s" "%s")\n' % tupleArg) - self.fp.write(' )\n') - if is_varargs: - self.fp.write(' (varargs #t)\n') - self.fp.write(')\n\n') - -# ------------------ Main function ----------------- - -def main(args): - verbose = False - onlyenums = False - onlyobjdefs = False - separate = False - modulename = None - defsfilter = None - opts, args = getopt.getopt(args[1:], 'vs:m:f:', - ['onlyenums', 'onlyobjdefs', - 'modulename=', 'separate=', - 'defsfilter=']) - for o, v in opts: - if o == '-v': - verbose = True - if o == '--onlyenums': - onlyenums = True - if o == '--onlyobjdefs': - onlyobjdefs = True - if o in ('-s', '--separate'): - separate = v - if o in ('-m', '--modulename'): - modulename = v - if o in ('-f', '--defsfilter'): - defsfilter = v - - if not args[0:1]: - print 'Must specify at least one input file name' - return -1 - - # read all the object definitions in - objdefs = [] - enums = [] - for filename in args: - buf = open(filename).read() - find_obj_defs(buf, objdefs) - find_enum_defs(buf, enums) - objdefs = sort_obj_defs(objdefs) - - if separate: - methods = file(separate + '.defs', 'w') - types = file(separate + '-types.defs', 'w') - - dw = DefsWriter(methods, prefix=modulename, verbose=verbose, - defsfilter=defsfilter) - dw.write_obj_defs(objdefs, types) - dw.write_enum_defs(enums, types) - print "Wrote %s-types.defs" % separate - - for filename in args: - dw.write_def(filename) - print "Wrote %s.defs" % separate - else: - dw = DefsWriter(prefix=modulename, verbose=verbose, - defsfilter=defsfilter) - - if onlyenums: - dw.write_enum_defs(enums) - elif onlyobjdefs: - dw.write_obj_defs(objdefs) - else: - dw.write_obj_defs(objdefs) - dw.write_enum_defs(enums) - - for filename in args: - dw.write_def(filename) - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/bindings/python/codegen/mergedefs.py b/bindings/python/codegen/mergedefs.py deleted file mode 100755 index 773e499..0000000 --- a/bindings/python/codegen/mergedefs.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: Python; py-indent-offset: 4 -*- - -import optparse - -import defsparser - -parser = optparse.OptionParser( - usage="usage: %prog [options] generated-defs old-defs") -parser.add_option("-p", "--merge-parameters", - help="Merge changes in function/methods parameter lists", - action="store_true", dest="parmerge", default=False) -(options, args) = parser.parse_args() - -if len(args) != 2: - parser.error("wrong number of arguments") - -newp = defsparser.DefsParser(args[0]) -oldp = defsparser.DefsParser(args[1]) - -newp.startParsing() -oldp.startParsing() - -newp.merge(oldp, options.parmerge) - -newp.write_defs() diff --git a/bindings/python/codegen/mkskel.py b/bindings/python/codegen/mkskel.py deleted file mode 100755 index 61f520b..0000000 --- a/bindings/python/codegen/mkskel.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: Python; py-indent-offset: 4 -*- - -import sys, os, getopt - -module_init_template = \ -'/* -*- Mode: C; c-basic-offset: 4 -*- */\n' + \ -'#ifdef HAVE_CONFIG_H\n' + \ -'# include "config.h"\n' + \ -'#endif\n' + \ -'#include <Python.h>\n' + \ -'#include <pygtk.h>\n' + \ -'\n' + \ -'/* include any extra headers needed here */\n' + \ -'\n' + \ -'void %(prefix)s_register_classes(PyObject *d);\n' + \ -'extern PyMethodDef %(prefix)s_functions[];\n' + \ -'\n' + \ -'DL_EXPORT(void)\n' + \ -'init%(module)s(void)\n' + \ -'{\n' + \ -' PyObject *m, *d;\n' + \ -'\n' + \ -' /* perform any initialisation required by the library here */\n' + \ -'\n' + \ -' m = Py_InitModule("%(module)s", %(prefix)s_functions);\n' + \ -' d = PyModule_GetDict(m);\n' + \ -'\n' + \ -' init_pygtk();\n' + \ -'\n' + \ -' %(prefix)s_register_classes(d);\n' + \ -'\n' + \ -' /* add anything else to the module dictionary (such as constants) */\n' +\ -'\n' + \ -' if (PyErr_Occurred())\n' + \ -' Py_FatalError("could not initialise module %(module)s");\n' + \ -'}\n' - -override_template = \ -'/* -*- Mode: C; c-basic-offset: 4 -*- */\n' + \ -'%%%%\n' + \ -'headers\n' + \ -'/* include any required headers here */\n' + \ -'%%%%\n' + \ -'init\n' + \ -' /* include any code here that needs to be executed before the\n' + \ -' * extension classes get initialised */\n' + \ -'%%%%\n' + \ -'\n' + \ -'/* you should add appropriate ignore, ignore-glob and\n' + \ -' * override sections here */\n' - -def open_with_backup(file): - if os.path.exists(file): - try: - os.rename(file, file+'~') - except OSError: - # fail silently if we can't make a backup - pass - return open(file, 'w') - -def write_skels(fileprefix, prefix, module): - fp = open_with_backup(fileprefix+'module.c') - fp.write(module_init_template % { 'prefix': prefix, 'module': module }) - fp.close() - fp = open_with_backup(fileprefix+'.override') - fp.write(override_template % { 'prefix': prefix, 'module': module }) - fp.close() - -if __name__ == '__main__': - opts, args = getopt.getopt(sys.argv[1:], 'f:p:m:h', - ['file-prefix=', 'prefix=', 'module=', 'help']) - fileprefix = None - prefix = None - module = None - for opt, arg in opts: - if opt in ('-f', '--file-prefix'): - fileprefix = arg - elif opt in ('-p', '--prefix'): - prefix = arg - elif opt in ('-m', '--module'): - module = arg - elif opt in ('-h', '--help'): - print 'usage: mkskel.py -f fileprefix -p prefix -m module' - sys.exit(0) - if not fileprefix or not prefix or not module: - print 'usage: mkskel.py -f fileprefix -p prefix -m module' - sys.exit(1) - write_skels(fileprefix, prefix, module) diff --git a/bindings/python/codegen/override.py b/bindings/python/codegen/override.py deleted file mode 100644 index 2e8c6a4..0000000 --- a/bindings/python/codegen/override.py +++ /dev/null @@ -1,288 +0,0 @@ -# -*- Mode: Python; py-indent-offset: 4 -*- - -# this file contains code for loading up an override file. The override file -# provides implementations of functions where the code generator could not -# do its job correctly. - -import fnmatch -import os -import re -import string -import sys - -def class2cname(klass, method): - c_name = '' - for c in klass: - if c.isupper(): - c_name += '_' + c.lower() - else: - c_name += c - return c_name[1:] + '_' + method - -import_pat = re.compile(r'\s*import\s+(\S+)\.([^\s.]+)\s+as\s+(\S+)') - -class Overrides: - def __init__(self, filename=None, path=[]): - self.modulename = None - self.ignores = {} - self.glob_ignores = [] - self.type_ignores = {} - self.overrides = {} - self.overridden = {} - self.kwargs = {} - self.noargs = {} - self.onearg = {} - self.staticmethod = {} - self.classmethod = {} - self.startlines = {} - self.override_attrs = {} - self.override_slots = {} - self.headers = '' - self.body = '' - self.init = '' - self.imports = [] - self.defines = {} - self.functions = {} - self.newstyle_constructors = {} - self.path = [os.path.abspath(x) for x in path] - if filename: - self.handle_file(filename) - - def handle_file(self, filename): - oldpath = os.getcwd() - - fp = None - for path in self.path: - os.chdir(oldpath) - os.chdir(path) - try: - fp = open(filename, 'r') - break - except: - os.chdir(oldpath) - if not fp: - raise Exception, "Couldn't find file %s" % filename - - dirname = path - - if dirname != oldpath: - os.chdir(dirname) - - # read all the components of the file ... - bufs = [] - startline = 1 - lines = [] - line = fp.readline() - linenum = 1 - while line: - if line == '%%\n' or line == '%%': - if lines: - bufs.append((string.join(lines, ''), startline)) - startline = linenum + 1 - lines = [] - else: - lines.append(line) - line = fp.readline() - linenum = linenum + 1 - if lines: - bufs.append((string.join(lines, ''), startline)) - if not bufs: return - - for buf, startline in bufs: - self.__parse_override(buf, startline, filename) - - os.chdir(oldpath) - - def __parse_override(self, buffer, startline, filename): - pos = string.find(buffer, '\n') - if pos >= 0: - line = buffer[:pos] - rest = buffer[pos+1:] - else: - line = buffer ; rest = '' - words = string.split(line) - command = words[0] - if (command == 'ignore' or - command == 'ignore-' + sys.platform): - "ignore/ignore-platform [functions..]" - for func in words[1:]: - self.ignores[func] = 1 - for func in string.split(rest): - self.ignores[func] = 1 - elif (command == 'ignore-glob' or - command == 'ignore-glob-' + sys.platform): - "ignore-glob/ignore-glob-platform [globs..]" - for func in words[1:]: - self.glob_ignores.append(func) - for func in string.split(rest): - self.glob_ignores.append(func) - elif (command == 'ignore-type' or - command == 'ignore-type-' + sys.platform): - "ignore-type/ignore-type-platform [typenames..]" - for typename in words[1:]: - self.type_ignores[typename] = 1 - for typename in string.split(rest): - self.type_ignores[typename] = 1 - elif command == 'override': - "override function/method [kwargs|noargs|onearg] [staticmethod|classmethod]" - func = words[1] - if 'kwargs' in words[1:]: - self.kwargs[func] = 1 - elif 'noargs' in words[1:]: - self.noargs[func] = 1 - elif 'onearg' in words[1:]: - self.onearg[func] = True - - if 'staticmethod' in words[1:]: - self.staticmethod[func] = True - elif 'classmethod' in words[1:]: - self.classmethod[func] = True - if func in self.overrides: - raise RuntimeError("Function %s is being overridden more than once" % (func,)) - self.overrides[func] = rest - self.startlines[func] = (startline + 1, filename) - elif command == 'override-attr': - "override-slot Class.attr" - attr = words[1] - self.override_attrs[attr] = rest - self.startlines[attr] = (startline + 1, filename) - elif command == 'override-slot': - "override-slot Class.slot" - slot = words[1] - self.override_slots[slot] = rest - self.startlines[slot] = (startline + 1, filename) - elif command == 'headers': - "headers" - self.headers = '%s\n#line %d "%s"\n%s' % \ - (self.headers, startline + 1, filename, rest) - elif command == 'body': - "body" - self.body = '%s\n#line %d "%s"\n%s' % \ - (self.body, startline + 1, filename, rest) - elif command == 'init': - "init" - self.init = '%s\n#line %d "%s"\n%s' % \ - (self.init, startline + 1, filename, rest) - elif command == 'modulename': - "modulename name" - self.modulename = words[1] - elif command == 'include': - "include filename" - for filename in words[1:]: - self.handle_file(filename) - for filename in string.split(rest): - self.handle_file(filename) - elif command == 'import': - "import module1 [\n module2, \n module3 ...]" - for line in string.split(buffer, '\n'): - match = import_pat.match(line) - if match: - self.imports.append(match.groups()) - elif command == 'define': - "define funcname [kwargs|noargs|onearg] [classmethod|staticmethod]" - "define Class.method [kwargs|noargs|onearg] [classmethod|staticmethod]" - func = words[1] - klass = None - if func.find('.') != -1: - klass, func = func.split('.', 1) - - if not self.defines.has_key(klass): - self.defines[klass] = {} - self.defines[klass][func] = rest - else: - self.functions[func] = rest - - if 'kwargs' in words[1:]: - self.kwargs[func] = 1 - elif 'noargs' in words[1:]: - self.noargs[func] = 1 - elif 'onearg' in words[1:]: - self.onearg[func] = 1 - - if 'staticmethod' in words[1:]: - self.staticmethod[func] = True - elif 'classmethod' in words[1:]: - self.classmethod[func] = True - - self.startlines[func] = (startline + 1, filename) - - elif command == 'new-constructor': - "new-constructor GType" - gtype, = words[1:] - self.newstyle_constructors[gtype] = True - - def is_ignored(self, name): - if self.ignores.has_key(name): - return 1 - for glob in self.glob_ignores: - if fnmatch.fnmatchcase(name, glob): - return 1 - return 0 - - def is_type_ignored(self, name): - return name in self.type_ignores - - def is_overriden(self, name): - return self.overrides.has_key(name) - - def is_already_included(self, name): - return self.overridden.has_key(name) - - def override(self, name): - self.overridden[name] = 1 - return self.overrides[name] - - def define(self, klass, name): - self.overridden[class2cname(klass, name)] = 1 - return self.defines[klass][name] - - def function(self, name): - return self.functions[name] - - def getstartline(self, name): - return self.startlines[name] - - def wants_kwargs(self, name): - return self.kwargs.has_key(name) - - def wants_noargs(self, name): - return self.noargs.has_key(name) - - def wants_onearg(self, name): - return self.onearg.has_key(name) - - def is_staticmethod(self, name): - return self.staticmethod.has_key(name) - - def is_classmethod(self, name): - return self.classmethod.has_key(name) - - def attr_is_overriden(self, attr): - return self.override_attrs.has_key(attr) - - def attr_override(self, attr): - return self.override_attrs[attr] - - def slot_is_overriden(self, slot): - return self.override_slots.has_key(slot) - - def slot_override(self, slot): - return self.override_slots[slot] - - def get_headers(self): - return self.headers - - def get_body(self): - return self.body - - def get_init(self): - return self.init - - def get_imports(self): - return self.imports - - def get_defines_for(self, klass): - return self.defines.get(klass, {}) - - def get_functions(self): - return self.functions diff --git a/bindings/python/codegen/reversewrapper.py b/bindings/python/codegen/reversewrapper.py deleted file mode 100644 index f528828..0000000 --- a/bindings/python/codegen/reversewrapper.py +++ /dev/null @@ -1,771 +0,0 @@ -### -*- python -*- -### Code to generate "Reverse Wrappers", i.e. C->Python wrappers -### (C) 2004 Gustavo Carneiro <gjc@gnome.org> -import argtypes -import os - -DEBUG_MODE = ('PYGTK_CODEGEN_DEBUG' in os.environ) - -def join_ctype_name(ctype, name): - '''Joins a C type and a variable name into a single string''' - if ctype[-1] != '*': - return " ".join((ctype, name)) - else: - return "".join((ctype, name)) - - -class CodeSink(object): - def __init__(self): - self.indent_level = 0 # current indent level - self.indent_stack = [] # previous indent levels - - def _format_code(self, code): - assert isinstance(code, str) - l = [] - for line in code.split('\n'): - l.append(' '*self.indent_level + line) - if l[-1]: - l.append('') - return '\n'.join(l) - - def writeln(self, line=''): - raise NotImplementedError - - def indent(self, level=4): - '''Add a certain ammount of indentation to all lines written - from now on and until unindent() is called''' - self.indent_stack.append(self.indent_level) - self.indent_level += level - - def unindent(self): - '''Revert indentation level to the value before last indent() call''' - self.indent_level = self.indent_stack.pop() - - -class FileCodeSink(CodeSink): - def __init__(self, fp): - CodeSink.__init__(self) - assert isinstance(fp, file) - self.fp = fp - - def writeln(self, line=''): - self.fp.write(self._format_code(line)) - -class MemoryCodeSink(CodeSink): - def __init__(self): - CodeSink.__init__(self) - self.lines = [] - - def writeln(self, line=''): - self.lines.append(self._format_code(line)) - - def flush_to(self, sink): - assert isinstance(sink, CodeSink) - for line in self.lines: - sink.writeln(line.rstrip()) - self.lines = [] - - def flush(self): - l = [] - for line in self.lines: - l.append(self._format_code(line)) - self.lines = [] - return "".join(l) - -class ReverseWrapper(object): - '''Object that generates a C->Python wrapper''' - def __init__(self, cname, is_static=True): - assert isinstance(cname, str) - - self.cname = cname - ## function object we will call, or object whose method we will call - self.called_pyobj = None - ## name of method of self.called_pyobj we will call - self.method_name = None - self.is_static = is_static - - self.parameters = [] - self.declarations = MemoryCodeSink() - self.post_return_code = MemoryCodeSink() - self.body = MemoryCodeSink() - self.cleanup_actions = [] - self.pyargv_items = [] - self.pyargv_optional_items = [] - self.pyret_parse_items = [] # list of (format_spec, parameter) - - def set_call_target(self, called_pyobj, method_name=None): - assert called_pyobj is not None - assert self.called_pyobj is None - self.called_pyobj = called_pyobj - self.method_name = method_name - - def set_return_type(self, return_type): - assert isinstance(return_type, ReturnType) - self.return_type = return_type - - def add_parameter(self, param): - assert isinstance(param, Parameter) - self.parameters.append(param) - - def add_declaration(self, decl_code): - self.declarations.writeln(decl_code) - - def add_pyargv_item(self, variable, optional=False): - if optional: - self.pyargv_optional_items.append(variable) - else: - self.pyargv_items.append(variable) - - def add_pyret_parse_item(self, format_specifier, parameter, prepend=False): - if prepend: - self.pyret_parse_items.insert(0, (format_specifier, parameter)) - else: - self.pyret_parse_items.append((format_specifier, parameter)) - - def write_code(self, code, - cleanup=None, - failure_expression=None, - failure_cleanup=None, - failure_exception=None, - code_sink=None): - '''Add a chunk of code with cleanup and error handling - - This method is to be used by TypeHandlers when generating code - - Keywork arguments: - code -- code to add - cleanup -- code to cleanup any dynamic resources created by @code - (except in case of failure) (default None) - failure_expression -- C boolean expression to indicate - if anything failed (default None) - failure_cleanup -- code to cleanup any dynamic resources - created by @code in case of failure (default None) - failure_exception -- code to raise an exception in case of - failure (which will be immediately - printed and cleared), (default None) - code_sink -- "code sink" to use; by default, - ReverseWrapper.body is used, which writes the - main body of the wrapper, before calling the - python method. Alternatively, - ReverseWrapper.after_pyret_parse can be used, to - write code after the PyArg_ParseTuple that - parses the python method return value. - ''' - if code_sink is None: - code_sink = self.body - if code is not None: - code_sink.writeln(code) - if failure_expression is not None: - code_sink.writeln("if (%s) {" % (failure_expression,)) - code_sink.indent() - if failure_exception is None: - code_sink.writeln("if (PyErr_Occurred())") - code_sink.indent() - code_sink.writeln("PyErr_Print();") - code_sink.unindent() - else: - code_sink.writeln(failure_exception) - code_sink.writeln("PyErr_Print();") - if failure_cleanup is not None: - code_sink.writeln(failure_cleanup) - for cleanup_action in self.cleanup_actions: - code_sink.writeln(cleanup_action) - self.return_type.write_error_return() - code_sink.unindent() - code_sink.writeln("}") - if cleanup is not None: - self.cleanup_actions.insert(0, cleanup) - - def generate(self, sink): - '''Generate the code into a CodeSink object''' - assert isinstance(sink, CodeSink) - - if DEBUG_MODE: - self.declarations.writeln("/* begin declarations */") - self.body.writeln("/* begin main body */") - self.post_return_code.writeln("/* begin post-return code */") - - self.add_declaration("PyGILState_STATE __py_state;") - self.write_code(code="__py_state = pyg_gil_state_ensure();", - cleanup="pyg_gil_state_release(__py_state);") - - for param in self.parameters: - param.convert_c2py() - - assert self.called_pyobj is not None,\ - "Parameters failed to provide a target function or method." - - if self.is_static: - sink.writeln('static %s' % self.return_type.get_c_type()) - else: - sink.writeln(self.return_type.get_c_type()) - c_proto_params = map(Parameter.format_for_c_proto, self.parameters) - sink.writeln("%s(%s)\n{" % (self.cname, ", ".join(c_proto_params))) - - self.return_type.write_decl() - self.add_declaration("PyObject *py_retval;") - - ## Handle number of arguments - if self.pyargv_items: - self.add_declaration("PyObject *py_args;") - py_args = "py_args" - if self.pyargv_optional_items: - self.add_declaration("int argc = %i;" % len(self.pyargv_items)) - argc = "argc" - for arg in self.pyargv_optional_items: - self.body.writeln("if (%s)" % arg) - self.body.indent() - self.body.writeln("++argc;") - self.body.unindent() - else: - argc = str(len(self.pyargv_items)) - else: - if self.pyargv_optional_items: - self.add_declaration("PyObject *py_args;") - py_args = "py_args" - self.add_declaration("int argc = 0;") - argc = "argc" - for arg in self.pyargv_optional_items: - self.body.writeln("if (%s)" % arg) - self.body.indent() - self.body.writeln("++argc;") - self.body.unindent() - else: - py_args = "NULL" - argc = None - - self.body.writeln() - - if py_args != "NULL": - self.write_code("py_args = PyTuple_New(%s);" % argc, - cleanup="Py_DECREF(py_args);") - pos = 0 - for arg in self.pyargv_items: - try: # try to remove the Py_DECREF cleanup action, if we can - self.cleanup_actions.remove("Py_DECREF(%s);" % arg) - except ValueError: # otherwise we have to Py_INCREF.. - self.body.writeln("Py_INCREF(%s);" % arg) - self.body.writeln("PyTuple_SET_ITEM(%s, %i, %s);" % (py_args, pos, arg)) - pos += 1 - for arg in self.pyargv_optional_items: - self.body.writeln("if (%s) {" % arg) - self.body.indent() - try: # try to remove the Py_DECREF cleanup action, if we can - self.cleanup_actions.remove("Py_XDECREF(%s);" % arg) - except ValueError: # otherwise we have to Py_INCREF.. - self.body.writeln("Py_INCREF(%s);" % arg) - self.body.writeln("PyTuple_SET_ITEM(%s, %i, %s);" % (py_args, pos, arg)) - self.body.unindent() - self.body.writeln("}") - pos += 1 - - self.body.writeln() - - ## Call the python method - if self.method_name is None: - self.write_code("py_retval = PyObject_Call(%s, %s);" - % (self.called_pyobj, py_args), - cleanup="Py_DECREF(py_retval);", - failure_expression="!py_retval") - else: - self.add_declaration("PyObject *py_method;") - self.write_code("py_method = PyObject_GetAttrString(%s, \"%s\");" - % (self.called_pyobj, self.method_name), - cleanup="Py_DECREF(py_method);", - failure_expression="!py_method") - self.write_code("py_retval = PyObject_CallObject(py_method, %s);" - % (py_args,), - cleanup="Py_DECREF(py_retval);", - failure_expression="!py_retval") - - ## -- Handle the return value -- - - ## we need to check if the return_type object is prepared to cooperate with multiple return values - len_before = len(self.pyret_parse_items) - self.return_type.write_conversion() - len_after = len(self.pyret_parse_items) - assert (self.return_type.get_c_type() == 'void' - or not (len_before == len_after and len_after > 0)),\ - ("Bug in reverse wrappers: return type handler %s" - " is not prepared to cooperate multiple return values") % (type(self.return_type),) - - sink.indent() - - if len(self.pyret_parse_items) == 1: - ## if retval is one item only, pack it in a tuple so we - ## can use PyArg_ParseTuple as usual.. - self.write_code('py_retval = Py_BuildValue("(N)", py_retval);') - if len(self.pyret_parse_items) > 0: - ## Parse return values using PyArg_ParseTuple - self.write_code(code=None, failure_expression=( - '!PyArg_ParseTuple(py_retval, "%s", %s)' % ( - "".join([format for format, param in self.pyret_parse_items]), - ", ".join([param for format, param in self.pyret_parse_items])))) - - if DEBUG_MODE: - self.declarations.writeln("/* end declarations */") - self.declarations.flush_to(sink) - sink.writeln() - if DEBUG_MODE: - self.body.writeln("/* end main body */") - self.body.flush_to(sink) - sink.writeln() - if DEBUG_MODE: - self.post_return_code.writeln("/* end post-return code */") - self.post_return_code.flush_to(sink) - sink.writeln() - - for cleanup_action in self.cleanup_actions: - sink.writeln(cleanup_action) - if self.return_type.get_c_type() != 'void': - sink.writeln() - sink.writeln("return retval;") - sink.unindent() - sink.writeln("}") - -class TypeHandler(object): - def __init__(self, wrapper, **props): - assert isinstance(wrapper, ReverseWrapper) - self.wrapper = wrapper - self.props = props - -class ReturnType(TypeHandler): - - def get_c_type(self): - raise NotImplementedError - - def write_decl(self): - raise NotImplementedError - - def write_error_return(self): - '''Write "return <value>" code in case of error''' - raise NotImplementedError - - def write_conversion(self): - '''Writes code to convert Python return value in 'py_retval' - into C 'retval'. Returns a string with C boolean expression - that determines if anything went wrong. ''' - raise NotImplementedError - -class Parameter(TypeHandler): - - def __init__(self, wrapper, name, **props): - TypeHandler.__init__(self, wrapper, **props) - self.name = name - - def get_c_type(self): - raise NotImplementedError - - def convert_c2py(self): - '''Write some code before calling the Python method.''' - pass - - def format_for_c_proto(self): - return join_ctype_name(self.get_c_type(), self.name) - - -###--- -class StringParam(Parameter): - - def get_c_type(self): - return self.props.get('c_type', 'char *').replace('const-', 'const ') - - def convert_c2py(self): - if self.props.get('optional', False): - self.wrapper.add_declaration("PyObject *py_%s = NULL;" % self.name) - self.wrapper.write_code(code=("if (%s)\n" - " py_%s = PyString_FromString(%s);\n" - % (self.name, self.name, self.name)), - cleanup=("Py_XDECREF(py_%s);" % self.name)) - self.wrapper.add_pyargv_item("py_%s" % self.name, optional=True) - else: - self.wrapper.add_declaration("PyObject *py_%s;" % self.name) - self.wrapper.write_code(code=("py_%s = PyString_FromString(%s);" % - (self.name, self.name)), - cleanup=("Py_DECREF(py_%s);" % self.name), - failure_expression=("!py_%s" % self.name)) - self.wrapper.add_pyargv_item("py_%s" % self.name) - -for ctype in ('char*', 'gchar*', 'const-char*', 'char-const*', 'const-gchar*', - 'gchar-const*', 'string', 'static_string'): - argtypes.matcher.register_reverse(ctype, StringParam) -del ctype - -class StringReturn(ReturnType): - - def get_c_type(self): - return "char *" - - def write_decl(self): - self.wrapper.add_declaration("char *retval;") - - def write_error_return(self): - self.wrapper.write_code("return NULL;") - - def write_conversion(self): - self.wrapper.add_pyret_parse_item("s", "&retval", prepend=True) - self.wrapper.write_code("retval = g_strdup(retval);", code_sink=self.wrapper.post_return_code) - -for ctype in ('char*', 'gchar*'): - argtypes.matcher.register_reverse_ret(ctype, StringReturn) -del ctype - - -class VoidReturn(ReturnType): - - def get_c_type(self): - return "void" - - def write_decl(self): - pass - - def write_error_return(self): - self.wrapper.write_code("return;") - - def write_conversion(self): - self.wrapper.write_code( - code=None, - failure_expression="py_retval != Py_None", - failure_cleanup='PyErr_SetString(PyExc_TypeError, "retval should be None");') - -argtypes.matcher.register_reverse_ret('void', VoidReturn) -argtypes.matcher.register_reverse_ret('none', VoidReturn) - -class GObjectParam(Parameter): - - def get_c_type(self): - return self.props.get('c_type', 'GObject *') - - def convert_c2py(self): - self.wrapper.add_declaration("PyObject *py_%s = NULL;" % self.name) - self.wrapper.write_code(code=("if (%s)\n" - " py_%s = pygobject_new((GObject *) %s);\n" - "else {\n" - " Py_INCREF(Py_None);\n" - " py_%s = Py_None;\n" - "}" - % (self.name, self.name, self.name, self.name)), - cleanup=("Py_DECREF(py_%s);" % self.name)) - self.wrapper.add_pyargv_item("py_%s" % self.name) - -argtypes.matcher.register_reverse('GObject*', GObjectParam) - -class GObjectReturn(ReturnType): - - def get_c_type(self): - return self.props.get('c_type', 'GObject *') - - def write_decl(self): - self.wrapper.add_declaration("%s retval;" % self.get_c_type()) - - def write_error_return(self): - self.wrapper.write_code("return NULL;") - - def write_conversion(self): - self.wrapper.write_code( - code=None, - failure_expression="!PyObject_TypeCheck(py_retval, &PyGObject_Type)", - failure_exception='PyErr_SetString(PyExc_TypeError, "retval should be a GObject");') - self.wrapper.write_code("retval = (%s) pygobject_get(py_retval);" - % self.get_c_type()) - self.wrapper.write_code("g_object_ref((GObject *) retval);") - -argtypes.matcher.register_reverse_ret('GObject*', GObjectReturn) - - - -class IntParam(Parameter): - - def get_c_type(self): - return self.props.get('c_type', 'int') - - def convert_c2py(self): - self.wrapper.add_declaration("PyObject *py_%s;" % self.name) - self.wrapper.write_code(code=("py_%s = PyInt_FromLong(%s);" % - (self.name, self.name)), - cleanup=("Py_DECREF(py_%s);" % self.name)) - self.wrapper.add_pyargv_item("py_%s" % self.name) - -class IntReturn(ReturnType): - def get_c_type(self): - return self.props.get('c_type', 'int') - def write_decl(self): - self.wrapper.add_declaration("%s retval;" % self.get_c_type()) - def write_error_return(self): - self.wrapper.write_code("return -G_MAXINT;") - def write_conversion(self): - self.wrapper.add_pyret_parse_item("i", "&retval", prepend=True) - -for argtype in ('int', 'gint', 'guint', 'short', 'gshort', 'gushort', 'long', - 'glong', 'gsize', 'gssize', 'guint8', 'gint8', 'guint16', - 'gint16', 'gint32', 'GTime'): - argtypes.matcher.register_reverse(argtype, IntParam) - argtypes.matcher.register_reverse_ret(argtype, IntReturn) -del argtype - -class IntPtrParam(Parameter): - def __init__(self, wrapper, name, **props): - if "direction" not in props: - raise ValueError("cannot use int* parameter without direction") - if props["direction"] not in ("out", "inout"): - raise ValueError("cannot use int* parameter with direction '%s'" % (props["direction"],)) - Parameter.__init__(self, wrapper, name, **props) - def get_c_type(self): - return self.props.get('c_type', 'int*') - def convert_c2py(self): - if self.props["direction"] == "inout": - self.wrapper.add_declaration("PyObject *py_%s;" % self.name) - self.wrapper.write_code(code=("py_%s = PyInt_FromLong(*%s);" % - (self.name, self.name)), - cleanup=("Py_DECREF(py_%s);" % self.name)) - self.wrapper.add_pyargv_item("py_%s" % self.name) - self.wrapper.add_pyret_parse_item("i", self.name) -for argtype in ('int*', 'gint*'): - argtypes.matcher.register_reverse(argtype, IntPtrParam) -del argtype - - -class GEnumReturn(IntReturn): - def write_conversion(self): - self.wrapper.write_code( - code=None, - failure_expression=("pyg_enum_get_value(%s, py_retval, (gint *)&retval)" % - self.props['typecode'])) - -argtypes.matcher.register_reverse_ret("GEnum", GEnumReturn) - -class GEnumParam(IntParam): - def convert_c2py(self): - self.wrapper.add_declaration("PyObject *py_%s;" % self.name) - self.wrapper.write_code(code=("py_%s = pyg_enum_from_gtype(%s, %s);" % - (self.name, self.props['typecode'], self.name)), - cleanup=("Py_DECREF(py_%s);" % self.name), - failure_expression=("!py_%s" % self.name)) - self.wrapper.add_pyargv_item("py_%s" % self.name) - -argtypes.matcher.register_reverse("GEnum", GEnumParam) - -class GFlagsReturn(IntReturn): - def write_conversion(self): - self.wrapper.write_code( - code=None, - failure_expression=("pyg_flags_get_value(%s, py_retval, (gint *)&retval)" % - self.props['typecode'])) - -argtypes.matcher.register_reverse_ret("GFlags", GFlagsReturn) - -class GFlagsParam(IntParam): - def convert_c2py(self): - self.wrapper.add_declaration("PyObject *py_%s;" % self.name) - self.wrapper.write_code(code=("py_%s = pyg_flags_from_gtype(%s, %s);" % - (self.name, self.props['typecode'], self.name)), - cleanup=("Py_DECREF(py_%s);" % self.name), - failure_expression=("!py_%s" % self.name)) - self.wrapper.add_pyargv_item("py_%s" % self.name) - -argtypes.matcher.register_reverse("GFlags", GFlagsParam) - - -class GtkTreePathParam(IntParam): - def convert_c2py(self): - self.wrapper.add_declaration("PyObject *py_%s;" % self.name) - self.wrapper.write_code(code=("py_%s = pygtk_tree_path_to_pyobject(%s);" % - (self.name, self.name)), - cleanup=("Py_DECREF(py_%s);" % self.name), - failure_expression=("!py_%s" % self.name)) - self.wrapper.add_pyargv_item("py_%s" % self.name) - -argtypes.matcher.register_reverse("GtkTreePath*", GtkTreePathParam) - - -class BooleanReturn(ReturnType): - def get_c_type(self): - return "gboolean" - def write_decl(self): - self.wrapper.add_declaration("gboolean retval;") - self.wrapper.add_declaration("PyObject *py_main_retval;") - def write_error_return(self): - self.wrapper.write_code("return FALSE;") - def write_conversion(self): - self.wrapper.add_pyret_parse_item("O", "&py_main_retval", prepend=True) - self.wrapper.write_code("retval = PyObject_IsTrue(py_main_retval)? TRUE : FALSE;", - code_sink=self.wrapper.post_return_code) -argtypes.matcher.register_reverse_ret("gboolean", BooleanReturn) - -class BooleanParam(Parameter): - def get_c_type(self): - return "gboolean" - def convert_c2py(self): - self.wrapper.add_declaration("PyObject *py_%s;" % self.name) - self.wrapper.write_code("py_%s = %s? Py_True : Py_False;" - % (self.name, self.name)) - self.wrapper.add_pyargv_item("py_%s" % self.name) - -argtypes.matcher.register_reverse("gboolean", BooleanParam) - - -class DoubleParam(Parameter): - def get_c_type(self): - return self.props.get('c_type', 'gdouble') - def convert_c2py(self): - self.wrapper.add_declaration("PyObject *py_%s;" % self.name) - self.wrapper.write_code(code=("py_%s = PyFloat_FromDouble(%s);" % - (self.name, self.name)), - cleanup=("Py_DECREF(py_%s);" % self.name)) - self.wrapper.add_pyargv_item("py_%s" % self.name) - -class DoublePtrParam(Parameter): - def __init__(self, wrapper, name, **props): - if "direction" not in props: - raise ValueError("cannot use double* parameter without direction") - if props["direction"] not in ("out", ): # inout not yet implemented - raise ValueError("cannot use double* parameter with direction '%s'" % (props["direction"],)) - Parameter.__init__(self, wrapper, name, **props) - def get_c_type(self): - return self.props.get('c_type', 'double*') - def convert_c2py(self): - self.wrapper.add_pyret_parse_item("d", self.name) -for argtype in ('double*', 'gdouble*'): - argtypes.matcher.register_reverse(argtype, DoublePtrParam) -del argtype - -class DoubleReturn(ReturnType): - def get_c_type(self): - return self.props.get('c_type', 'gdouble') - def write_decl(self): - self.wrapper.add_declaration("%s retval;" % self.get_c_type()) - def write_error_return(self): - self.wrapper.write_code("return -G_MAXFLOAT;") - def write_conversion(self): - self.wrapper.write_code( - code=None, - failure_expression="!PyFloat_AsDouble(py_retval)", - failure_cleanup='PyErr_SetString(PyExc_TypeError, "retval should be a float");') - self.wrapper.write_code("retval = PyFloat_AsDouble(py_retval);") - -for argtype in ('float', 'double', 'gfloat', 'gdouble'): - argtypes.matcher.register_reverse(argtype, DoubleParam) - argtypes.matcher.register_reverse_ret(argtype, DoubleReturn) - - -class GBoxedParam(Parameter): - def get_c_type(self): - return self.props.get('c_type').replace('const-', 'const ') - def convert_c2py(self): - self.wrapper.add_declaration("PyObject *py_%s;" % self.name) - ctype = self.get_c_type() - if ctype.startswith('const '): - ctype_no_const = ctype[len('const '):] - self.wrapper.write_code( - code=('py_%s = pyg_boxed_new(%s, (%s) %s, TRUE, TRUE);' % - (self.name, self.props['typecode'], - ctype_no_const, self.name)), - cleanup=("Py_DECREF(py_%s);" % self.name)) - else: - self.wrapper.write_code( - code=('py_%s = pyg_boxed_new(%s, %s, FALSE, FALSE);' % - (self.name, self.props['typecode'], self.name)), - cleanup=("Py_DECREF(py_%s);" % self.name)) - self.wrapper.add_pyargv_item("py_%s" % self.name) - -argtypes.matcher.register_reverse("GBoxed", GBoxedParam) - -class GBoxedReturn(ReturnType): - def get_c_type(self): - return self.props.get('c_type') - def write_decl(self): - self.wrapper.add_declaration("%s retval;" % self.get_c_type()) - def write_error_return(self): - self.wrapper.write_code("return retval;") - def write_conversion(self): - self.wrapper.write_code( - failure_expression=("!pyg_boxed_check(py_retval, %s)" % - (self.props['typecode'],)), - failure_cleanup=('PyErr_SetString(PyExc_TypeError, "retval should be a %s");' - % (self.props['typename'],))) - self.wrapper.write_code('retval = pyg_boxed_get(py_retval, %s);' % - self.props['typename']) - -argtypes.matcher.register_reverse_ret("GBoxed", GBoxedReturn) - - -class GdkRectanglePtrParam(Parameter): - def get_c_type(self): - return self.props.get('c_type').replace('const-', 'const ') - def convert_c2py(self): - self.wrapper.add_declaration("PyObject *py_%s;" % self.name) - self.wrapper.write_code( - code=('py_%s = pyg_boxed_new(GDK_TYPE_RECTANGLE, %s, TRUE, TRUE);' % - (self.name, self.name)), - cleanup=("Py_DECREF(py_%s);" % self.name)) - self.wrapper.add_pyargv_item("py_%s" % self.name) - -argtypes.matcher.register_reverse("GdkRectangle*", GdkRectanglePtrParam) -argtypes.matcher.register_reverse('GtkAllocation*', GdkRectanglePtrParam) - - -class PyGObjectMethodParam(Parameter): - def __init__(self, wrapper, name, method_name, **props): - Parameter.__init__(self, wrapper, name, **props) - self.method_name = method_name - - def get_c_type(self): - return self.props.get('c_type', 'GObject *') - - def convert_c2py(self): - self.wrapper.add_declaration("PyObject *py_%s;" % self.name) - self.wrapper.write_code(code=("py_%s = pygobject_new((GObject *) %s);" % - (self.name, self.name)), - cleanup=("Py_DECREF(py_%s);" % self.name), - failure_expression=("!py_%s" % self.name)) - self.wrapper.set_call_target("py_%s" % self.name, self.method_name) - -class CallbackInUserDataParam(Parameter): - def __init__(self, wrapper, name, free_it, **props): - Parameter.__init__(self, wrapper, name, **props) - self.free_it = free_it - - def get_c_type(self): - return "gpointer" - - def convert_c2py(self): - self.wrapper.add_declaration("PyObject **_user_data;") - cleanup = self.free_it and ("g_free(%s);" % self.name) or None - self.wrapper.write_code(code=("_real_user_data = (PyObject **) %s;" - % self.name), - cleanup=cleanup) - - self.wrapper.add_declaration("PyObject *py_func;") - cleanup = self.free_it and "Py_DECREF(py_func);" or None - self.wrapper.write_code(code="py_func = _user_data[0];", - cleanup=cleanup) - self.wrapper.set_call_target("py_func") - - self.wrapper.add_declaration("PyObject *py_user_data;") - cleanup = self.free_it and "Py_XDECREF(py_user_data);" or None - self.wrapper.write_code(code="py_user_data = _user_data[1];", - cleanup=cleanup) - self.wrapper.add_pyargv_item("py_user_data", optional=True) - -def _test(): - import sys - - if 1: - wrapper = ReverseWrapper("this_is_the_c_function_name", is_static=True) - wrapper.set_return_type(StringReturn(wrapper)) - wrapper.add_parameter(PyGObjectMethodParam(wrapper, "self", method_name="do_xxx")) - wrapper.add_parameter(StringParam(wrapper, "param2", optional=True)) - wrapper.add_parameter(GObjectParam(wrapper, "param3")) - #wrapper.add_parameter(InoutIntParam(wrapper, "param4")) - wrapper.generate(FileCodeSink(sys.stderr)) - - if 0: - wrapper = ReverseWrapper("this_a_callback_wrapper") - wrapper.set_return_type(VoidReturn(wrapper)) - wrapper.add_parameter(StringParam(wrapper, "param1", optional=False)) - wrapper.add_parameter(GObjectParam(wrapper, "param2")) - wrapper.add_parameter(CallbackInUserDataParam(wrapper, "data", free_it=True)) - wrapper.generate(FileCodeSink(sys.stderr)) - -if __name__ == '__main__': - _test() diff --git a/bindings/python/codegen/scmexpr.py b/bindings/python/codegen/scmexpr.py deleted file mode 100644 index d08c517..0000000 --- a/bindings/python/codegen/scmexpr.py +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: Python; py-indent-offset: 4 -*- -from __future__ import generators - -import string -import types -from cStringIO import StringIO - -class error(Exception): - def __init__(self, filename, lineno, msg): - Exception.__init__(self, msg) - self.filename = filename - self.lineno = lineno - self.msg = msg - def __str__(self): - return '%s:%d: error: %s' % (self.filename, self.lineno, self.msg) - -trans = [' '] * 256 -for i in range(256): - if chr(i) in string.letters + string.digits + '_': - trans[i] = chr(i) - else: - trans[i] = '_' -trans = string.join(trans, '') - -def parse(filename): - if isinstance(filename, str): - fp = open(filename, 'r') - else: # if not string, assume it is some kind of iterator - fp = filename - filename = getattr(fp, 'name', '<unknown>') - whitespace = ' \t\n\r\x0b\x0c' - nonsymbol = whitespace + '();\'"' - stack = [] - openlines = [] - lineno = 0 - for line in fp: - pos = 0 - lineno += 1 - while pos < len(line): - if line[pos] in whitespace: # ignore whitespace - pass - elif line[pos] == ';': # comment - break - elif line[pos:pos+2] == "'(": - pass # the open parenthesis will be handled next iteration - elif line[pos] == '(': - stack.append(()) - openlines.append(lineno) - elif line[pos] == ')': - if len(stack) == 0: - raise error(filename, lineno, 'close parenthesis found when none open') - closed = stack[-1] - del stack[-1] - del openlines[-1] - if stack: - stack[-1] += (closed,) - else: - yield closed - elif line[pos] == '"': # quoted string - if not stack: - raise error(filename, lineno, - 'string found outside of s-expression') - endpos = pos + 1 - chars = [] - while endpos < len(line): - if endpos+1 < len(line) and line[endpos] == '\\': - endpos += 1 - if line[endpos] == 'n': - chars.append('\n') - elif line[endpos] == 'r': - chars.append('\r') - elif line[endpos] == 't': - chars.append('\t') - else: - chars.append('\\') - chars.append(line[endpos]) - elif line[endpos] == '"': - break - else: - chars.append(line[endpos]) - endpos += 1 - if endpos >= len(line): - raise error(filename, lineno, "unclosed quoted string") - pos = endpos - stack[-1] += (''.join(chars),) - else: # symbol/number - if not stack: - raise error(filename, lineno, - 'identifier found outside of s-expression') - endpos = pos - while endpos < len(line) and line[endpos] not in nonsymbol: - endpos += 1 - symbol = line[pos:endpos] - pos = max(pos, endpos-1) - try: symbol = int(symbol) - except ValueError: - try: symbol = float(symbol) - except ValueError: pass - stack[-1] += (symbol,) - pos += 1 - if len(stack) != 0: - msg = '%d unclosed parentheses found at end of ' \ - 'file (opened on line(s) %s)' % (len(stack), - ', '.join(map(str, openlines))) - raise error(filename, lineno, msg) - -class Parser: - def __init__(self, filename): - """Argument is either a string, a parse tree, or file object""" - self.filename = filename - def startParsing(self, filename=None): - statements = parse(filename or self.filename) - for statement in statements: - self.handle(statement) - def handle(self, tup): - cmd = string.translate(tup[0], trans) - if hasattr(self, cmd): - getattr(self, cmd)(*tup[1:]) - else: - self.unknown(tup) - def unknown(self, tup): - pass - -_testString = """; a scheme file -(define-func gdk_font_load ; a comment at end of line - GdkFont - ((string name))) - -(define-boxed GdkEvent - gdk_event_copy - gdk_event_free - "sizeof(GdkEvent)") -""" - -if __name__ == '__main__': - import sys - if sys.argv[1:]: - fp = open(sys.argv[1]) - else: - fp = StringIO(_testString) - statements = parse(fp) - for s in statements: - print `s` diff --git a/bindings/python/rtspserver-types.defs b/bindings/python/rtspserver-types.defs deleted file mode 100644 index 04949af..0000000 --- a/bindings/python/rtspserver-types.defs +++ /dev/null @@ -1,63 +0,0 @@ -;; From gst/rtsp-server/rtsp-server.h - -(define-object Server - (in-module "Gst.RTSPServer") - (parent "GObject") - (c-name "GstRTSPServer") - (gtype-id "GST_TYPE_RTSP_SERVER") -) - -;; From gst/rtsp-server/rtsp-media-mapping.h - -(define-object MediaMapping - (in-module "Gst.RTSPServer") - (parent "GObject") - (c-name "GstRTSPMediaMapping") - (gtype-id "GST_TYPE_RTSP_MEDIA_MAPPING") -) - -;; From gst/rtsp-server/rtsp-media-factory.h - -(define-object MediaFactory - (in-module "Gst.RTSPServer") - (parent "GObject") - (c-name "GstRTSPMediaFactory") - (gtype-id "GST_TYPE_RTSP_MEDIA_FACTORY") -) - -;; From gst/rtsp-server/rtsp-media.h - -(define-object Media - (in-module "Gst.RTSPServer") - (parent "GObject") - (c-name "GstRTSPMedia") - (gtype-id "GST_TYPE_RTSP_MEDIA") -) - -;; From gst/rtsp-server/rtsp-session-pool.h - -(define-object SessionPool - (in-module "Gst") - (parent "GObject") - (c-name "GstRTSPSessionPool") - (gtype-id "GST_TYPE_RTSP_SESSION_POOL") -) - -;; From gst/rtsp-server/rtsp-session.h - -(define-object Session - (in-module "Gst") - (parent "GObject") - (c-name "GstRTSPSession") - (gtype-id "GST_TYPE_RTSP_SESSION") -) - -;; From gst/rtsp-server/rtsp-client.h - -(define-object Client - (in-module "Gst") - (parent "GObject") - (c-name "GstRTSPClient") - (gtype-id "GST_TYPE_RTSP_CLIENT") -) - diff --git a/bindings/python/rtspserver.defs b/bindings/python/rtspserver.defs deleted file mode 100644 index f000434..0000000 --- a/bindings/python/rtspserver.defs +++ /dev/null @@ -1,399 +0,0 @@ -(include "rtspserver-types.defs") - -;; From gst/rtsp-server/rtsp-server.h - -(define-function rtsp_server_new - (c-name "gst_rtsp_server_new") - (is-constructor-of "GstRTSPServer") - (return-type "GstRTSPServer*") -) - -(define-method set_address - (of-object "GstRTSPServer") - (c-name "gst_rtsp_server_set_address") - (parameters - '("const-gchar*" "address") - ) -) - -(define-method get_address - (of-object "GstRTSPServer") - (c-name "gst_rtsp_server_get_address") - (return-type "const-gchar*") -) - -(define-method set_service - (of-object "GstRTSPServer") - (c-name "gst_rtsp_server_set_service") - (parameters - '("const-gchar*" "service") - ) -) - -(define-method get_service - (of-object "GstRTSPServer") - (c-name "gst_rtsp_server_get_service") - (return-type "const-gchar*") -) - -(define-method set_backlog - (of-object "GstRTSPServer") - (c-name "gst_rtsp_server_set_backlog") - (parameters - '("gint" "backlog") - ) -) - -(define-method get_backlog - (of-object "GstRTSPServer") - (c-name "gst_rtsp_server_get_backlog") - (return-type "gint") -) - -(define-method set_session_pool - (of-object "GstRTSPServer") - (c-name "gst_rtsp_server_set_session_pool") - (parameters - '("GstRTSPSessionPool*" "pool") - ) -) - -(define-method get_session_pool - (of-object "GstRTSPServer") - (c-name "gst_rtsp_server_get_session_pool") - (return-type "GstRTSPSessionPool*") -) - -(define-method set_media_mapping - (of-object "GstRTSPServer") - (c-name "gst_rtsp_server_set_media_mapping") - (parameters - '("GstRTSPMediaMapping*" "mapping") - ) -) - -(define-method get_media_mapping - (of-object "GstRTSPServer") - (c-name "gst_rtsp_server_get_media_mapping") - (return-type "GstRTSPMediaMapping*") -) - -(define-function io_func - (c-name "gst_rtsp_server_io_func") - (return-type "gboolean") - (parameters - '("GIOChannel*" "channel") - '("GIOCondition" "condition") - '("GstRTSPServer*" "server") - ) -) - -(define-method get_io_channel - (of-object "GstRTSPServer") - (c-name "gst_rtsp_server_get_io_channel") - (return-type "GIOChannel*") -) - -(define-method attach - (of-object "GstRTSPServer") - (c-name "gst_rtsp_server_attach") - (return-type "guint") - (parameters - '("GMainContext*" "context") - ) -) - -(define-method create_watch - (of-object "GstRTSPServer") - (c-name "gst_rtsp_server_create_watch") - (return-type "GSource*") -) - -;; From gst/rtsp-server/rtsp-media-mapping.h - -(define-function rtsp_media_mapping_new - (c-name "gst_rtsp_media_mapping_new") - (is-constructor-of "GstRTSPMediaMapping") - (return-type "GstRTSPMediaMapping*") -) - - -;; TODO define const-GstRTSPUrl* on arg-types.py -(define-method find_factory - (of-object "GstRTSPMediaMapping") - (c-name "gst_rtsp_media_mapping_find_factory") - (return-type "GstRTSPMediaFactory*") - (parameters - '("const-GstRTSPUrl*" "url") - ) -) - -(define-method add_factory - (of-object "GstRTSPMediaMapping") - (c-name "gst_rtsp_media_mapping_add_factory") - (parameters - '("const-gchar*" "path") - '("GstRTSPMediaFactory*" "factory") - ) -) - -(define-method remove_factory - (of-object "GstRTSPMediaMapping") - (c-name "gst_rtsp_media_mapping_remove_factory") - (parameters - '("const-gchar*" "path") - ) -) - -;; From gst/rtsp-server/rtsp-media-factory.h - -(define-function rtsp_media_factory_new - (c-name "gst_rtsp_media_factory_new") - (is-constructor-of "GstRTSMediaFactory") - (return-type "GstRTSPMediaFactory*") -) - -(define-method set_launch - (of-object "GstRTSPMediaFactory") - (c-name "gst_rtsp_media_factory_set_launch") - (parameters - '("gchar*" "launch") - ) -) - -(define-method get_launch - (of-object "GstRTSPMediaFactory") - (c-name "gst_rtsp_media_factory_get_launch") - (return-type "gchar*") -) - -(define-method set_shared - (of-object "GstRTSPMediaFactory") - (c-name "gst_rtsp_media_factory_set_shared") - (parameters - '("gboolean" "shared") - ) -) - -(define-method is_shared - (of-object "GstRTSPMediaFactory") - (c-name "gst_rtsp_media_factory_is_shared") - (return-type "gboolean") -) - -(define-method set_eos_shutdown - (of-object "GstRTSPMediaFactory") - (c-name "gst_rtsp_media_factory_set_eos_shutdown") - (parameters - '("gboolean" "eos_shutdown") - ) -) - -(define-method is_eos_shutdown - (of-object "GstRTSPMediaFactory") - (c-name "gst_rtsp_media_factory_is_eos_shutdown") - (return-type "gboolean") -) - -;; TODO define const-GstRTSPUrl* on arg-types.py -(define-method construct - (of-object "GstRTSPMediaFactory") - (c-name "gst_rtsp_media_factory_construct") - (return-type "GstRTSPMedia*") - (parameters - '("const-GstRTSPUrl*" "url") - ) -) - -(define-method collect_streams - (of-object "GstRTSPMediaFactory") - (c-name "gst_rtsp_media_factory_collect_streams") - (parameters - '("const-GstRTSPUrl*" "url") - '("GstRTSPMedia*" "media") - ) -) - -(define-virtual get_element - (of-object "GstRTSPMediaFactory") - (parameters - '("const-GstRTSPUrl*" "url") - ) - (return-type "GstElement*") -) - - -(define-virtual construct - (of-object "GstRTSPMediaFactory") - (parameters - '("const-GstRTSPUrl*" "url") - ) - (return-type "GstRTSPMedia*") -) - - -(define-virtual configure - (of-object "GstRTSPMediaFactory") - (parameters - '("GstRTSPMedia*" "media") - ) - (return-type "none") -) - - -(define-virtual create_pipeline - (of-object "GstRTSPMediaFactory") - (parameters - '("GstRTSPMedia*" "media") - ) - (return-type "GstElement*") -) - - -;; From gst/rtsp-server/rtsp-session-pool.h - -(define-function gst_rtsp_session_pool_new - (c-name "gst_rtsp_session_pool_new") - (is-constructor-of "GstRTSPSessionPool") - (return-type "GstRTSPSessionPool*") -) - -(define-method set_max_sessions - (of-object "GstRTSPSessionPool") - (c-name "gst_rtsp_session_pool_set_max_sessions") - (return-type "none") - (parameters - '("guint" "max") - ) -) - -(define-method get_max_sessions - (of-object "GstRTSPSessionPool") - (c-name "gst_rtsp_session_pool_get_max_sessions") - (return-type "guint") -) - -(define-method get_n_sessions - (of-object "GstRTSPSessionPool") - (c-name "gst_rtsp_session_pool_get_n_sessions") - (return-type "guint") -) - -(define-method create - (of-object "GstRTSPSessionPool") - (c-name "gst_rtsp_session_pool_create") - (return-type "GstRTSPSession*") -) - -(define-method find - (of-object "GstRTSPSessionPool") - (c-name "gst_rtsp_session_pool_find") - (return-type "GstRTSPSession*") - (parameters - '("const-gchar*" "sessionid") - ) -) - -(define-method remove - (of-object "GstRTSPSessionPool") - (c-name "gst_rtsp_session_pool_remove") - (return-type "gboolean") - (parameters - '("GstRTSPSession*" "sess") - ) -) - -(define-method filter - (of-object "GstRTSPSessionPool") - (c-name "gst_rtsp_session_pool_filter") - (return-type "GList*") - (parameters - '("GstRTSPSessionFilterFunc" "func") - '("gpointer" "user_data") - ) -) - -(define-method cleanup - (of-object "GstRTSPSessionPool") - (c-name "gst_rtsp_session_pool_cleanup") - (return-type "guint") -) - -(define-method create_watch - (of-object "GstRTSPSessionPool") - (c-name "gst_rtsp_session_pool_create_watch") - (return-type "GSource*") -) - -;; From gst/rtsp-server/rtsp-client.h - -(define-function gst_rtsp_client_new - (c-name "gst_rtsp_client_new") - (is-constructor-of "GstRTSPClient") - (return-type "GstRTSPClient*") -) - -(define-method set_session_pool - (of-object "GstRTSPClient") - (c-name "gst_rtsp_client_set_session_pool") - (return-type "none") - (parameters - '("GstRTSPSessionPool*" "pool") - ) -) - -(define-method get_session_pool - (of-object "GstRTSPClient") - (c-name "gst_rtsp_client_get_session_pool") - (return-type "GstRTSPSessionPool*") -) - -(define-method set_media_mapping - (of-object "GstRTSPClient") - (c-name "gst_rtsp_client_set_media_mapping") - (return-type "none") - (parameters - '("GstRTSPMediaMapping*" "mapping") - ) -) - -(define-method get_media_mapping - (of-object "GstRTSPClient") - (c-name "gst_rtsp_client_get_media_mapping") - (return-type "GstRTSPMediaMapping*") -) - -(define-method accept - (of-object "GstRTSPClient") - (c-name "gst_rtsp_client_accept") - (return-type "gboolean") - (parameters - '("GIOChannel*" "channel") - ) -) - -;; From bindings/python/rtsp-params.h - -(define-function gst_rtsp_params_set - (c-name "gst_rtsp_params_set") - (return-type "GstRTSPResult") - (parameters - '("GstRTSPClient*" "client") - '("GstRTSPUrl*" "uri") - '("GstRTSPSession*" "session") - '("GstRTSPMessage*" "request") - '("GstRTSPMessage*" "response") - ) -) - -(define-function gst_rtsp_params_get - (c-name "gst_rtsp_params_get") - (return-type "GstRTSPResult") - (parameters - '("GstRTSPClient*" "client") - '("GstRTSPUrl*" "uri") - '("GstRTSPSession*" "session") - '("GstRTSPMessage*" "request") - '("GstRTSPMessage*" "response") - ) -) diff --git a/bindings/python/rtspserver.override b/bindings/python/rtspserver.override deleted file mode 100644 index 2fd69a7..0000000 --- a/bindings/python/rtspserver.override +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4 -*- */ -%% -headers -/* include any required headers here */ -#define NO_IMPORT_PYGOBJECT -#include <pygobject.h> - -#include <gst/gst.h> -#include <gst/rtsp-server/rtsp-server.h> - -#include <glib.h> - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -/* Boonky define that allows for backwards compatibility with Python 2.4 */ -#if PY_VERSION_HEX < 0x02050000 -#define Py_ssize_t int -#endif - -#include <gst/rtsp-server/rtsp-server.h> - -typedef struct { - PyObject_HEAD - GMainContext *context; -} PyGMainContext; - -%% -import gobject.GObject as PyGObject_Type -import gobject.MainContext as PyGMainContext_Type -%% -override gst_rtsp_server_attach kwargs -static PyObject * -_wrap_gst_rtsp_server_attach (PyGObject *self, - PyObject *args, PyObject *keywords) -{ - static char *kwlist[] = {"context", NULL}; - PyGMainContext *py_context = NULL; - GMainContext *context = NULL; - guint res; - - if (!PyArg_ParseTupleAndKeywords (args, keywords, - "|O!:GstRTSPServer.__init__", kwlist, - &PyGMainContext_Type, &py_context)) - return NULL; - - if (py_context) - context = py_context->context; - - pyg_begin_allow_threads; - res = gst_rtsp_server_attach (GST_RTSP_SERVER (self->obj), context); - pyg_end_allow_threads; - - return PyLong_FromLong (res); -} -%% -override gst_rtsp_server_create_watch kwargs -static PyObject * -_wrap_gst_rtsp_server_create_watch(PyGObject *self, PyObject *args, PyObject *keywords) -{ - GSource *ret; - pyg_begin_allow_threads; - ret = gst_rtsp_server_create_watch(GST_RTSP_SERVER(self->obj)); - pyg_end_allow_threads; - return pygobject_new((GObject *)ret); -} - -%% -override gst_rtsp_media_mapping_add_factory kwargs -static PyObject * -_wrap_gst_rtsp_media_mapping_add_factory(PyGObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "path", "factory", NULL }; - char *path; - PyGObject *factory; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs,"sO!:GstRTSPMediaMapping.add_factory", kwlist, &path, &PyGstRTSPMediaFactory_Type, &factory)) - return NULL; - pyg_begin_allow_threads; - gst_rtsp_media_mapping_add_factory(GST_RTSP_MEDIA_MAPPING(self->obj), path, - g_object_ref (GST_RTSP_MEDIA_FACTORY(factory->obj))); - pyg_end_allow_threads; - Py_INCREF(Py_None); - return Py_None; -} - diff --git a/bindings/python/rtspservermodule.c b/bindings/python/rtspservermodule.c deleted file mode 100644 index e5e7d56..0000000 --- a/bindings/python/rtspservermodule.c +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4 -*- */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include <Python.h> -#include <pygobject.h> - -/* include any extra headers needed here */ - -void pygst_rtsp_server_register_classes(PyObject *d); -extern PyMethodDef pygst_rtsp_server_functions[]; - -DL_EXPORT(void) -initrtspserver(void) -{ - PyObject *m, *d; - - /* perform any initialisation required by the library here */ - - m = Py_InitModule("rtspserver", pygst_rtsp_server_functions); - d = PyModule_GetDict(m); - - init_pygobject(); - - pygst_rtsp_server_register_classes(d); - - /* add anything else to the module dictionary (such as constants) */ - - if (PyErr_Occurred()) - Py_FatalError("could not initialise module rtspserver"); -} diff --git a/bindings/python/test.py b/bindings/python/test.py deleted file mode 100644 index 3278faa..0000000 --- a/bindings/python/test.py +++ /dev/null @@ -1,130 +0,0 @@ -import unittest -import rtspserver - - -def pubdir(obj): - return [d for d in dir(obj) if not d.startswith('_')] - -#print 'Module listing:', pubdir(rtspserver) - -from rtspserver import Server, SessionPool, Session, MediaMapping, MediaFactory - -#print 'Server listing: ', pubdir(Server) -#print 'MediaMapping listing: ', pubdir(MediaMapping) -#print 'MediaFactory listing: ', pubdir(MediaFactory) -#print 'SessionPool listing: ', pubdir(SessionPool) -#print 'Session listing: ', pubdir(Session) - - -class ServerTestCase(unittest.TestCase): - - def setUp(self): - self.server = Server() - - def tearDown(self): - del self.server - - def test_address(self): - """ Server address set/get """ - addr = '1.2.3.4' - self.server.set_address(addr) - self.assertEquals(addr, self.server.get_address()) - - def test_service(self): - """ Server service set/get """ - service = '12345' - self.server.set_service(service) - self.assertEquals(service, self.server.get_service()) - - def test_backlog(self): - """ Server backlog set/get """ - backlog = 1234 - self.server.set_backlog(backlog) - self.assertEquals(backlog, self.server.get_backlog()) - - def test_session_pool(self): - """ Server session pool set/get """ - pool = SessionPool() - self.server.set_session_pool(pool) - self.assertEquals(pool, self.server.get_session_pool()) - - def test_media_mapping(self): - """ Server media mapping set/get """ - mmap = MediaMapping() - self.server.set_media_mapping(mmap) - self.assertEquals(mmap, self.server.get_media_mapping()) - - -class MediaMappingTestCase(unittest.TestCase): - - def setUp(self): - self.mmap = MediaMapping() - - def tearDown(self): - del self.mmap - - def test_factory(self): - """ MediaMapping factory add/remove """ - self.factory = MediaFactory() - self.mmap.add_factory("/test", self.factory) - self.mmap.remove_factory("/test") - - -class MediaFactoryTestCase(unittest.TestCase): - - def setUp(self): - self.factory = MediaFactory() - - def tearDown(self): - del self.factory - - def test_launch(self): - """ MediaFactory launch set/get """ - launch = "videotestsrc ! xvimagesink" - self.factory.set_launch(launch) - self.assertEquals(launch, self.factory.get_launch()) - - def test_shared(self): - """ MediaFactory shared set/is """ - self.factory.set_shared(True) - self.assert_(self.factory.is_shared()) - self.factory.set_shared(False) - self.assert_(not self.factory.is_shared()) - - def test_eos_shutdown(self): - """ MediaFactory eos_shutdown set/is """ - self.factory.set_eos_shutdown(True) - self.assert_(self.factory.is_eos_shutdown()) - self.factory.set_eos_shutdown(False) - self.assert_(not self.factory.is_eos_shutdown()) - - - -def alltests(): - tests = [] - - for p in dir(ServerTestCase): - try: - if 'test_' in p: - tests.append(ServerTestCase(p)) - except: - pass - - for p in dir(MediaMappingTestCase): - try: - if 'test_' in p: - tests.append(MediaMappingTestCase(p)) - except: - pass - - for p in dir(MediaFactoryTestCase): - try: - if 'test_' in p: - tests.append(MediaFactoryTestCase(p)) - except: - pass - - return unittest.TestSuite(tests) - - -unittest.TextTestRunner(verbosity=2).run(alltests()) diff --git a/common b/common -Subproject 11f0cd5a3fba36f85cf3e434150bfe66b1bf08d +Subproject 7fda5249ab56f0de09277df330780a3b90a2b30 diff --git a/configure.ac b/configure.ac index 70ed5e1..85c013a 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ(2.60) dnl initialize autoconf dnl when going to/from release please set the nano (fourth number) right ! dnl releases only do Wall, cvs and prerelease does Werror too -AC_INIT(Gst-RTSP, 0.10.8.1, +AC_INIT(Gst-RTSP, 0.11.0.1, http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer, gst-rtsp) AG_GST_INIT @@ -36,14 +36,14 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])], dnl our libraries and install dirs use major.minor as a version GST_MAJORMINOR=$PACKAGE_VERSION_MAJOR.$PACKAGE_VERSION_MINOR dnl we override it here if we need to for the release candidate of new series -GST_MAJORMINOR=0.10 +GST_MAJORMINOR=0.11 AC_SUBST(GST_MAJORMINOR) AM_PROG_LIBTOOL dnl *** required versions of GStreamer stuff *** -GST_REQ=0.10.31 -GSTPB_REQ=0.10.31 +GST_REQ=0.11.0 +GSTPB_REQ=0.11.0 dnl *** autotools stuff **** @@ -90,54 +90,6 @@ dnl check for documentation tools AG_GST_DOCBOOK_CHECK GTK_DOC_CHECK([1.3]) -dnl check for python -AM_PATH_PYTHON -AC_MSG_CHECKING(for python >= 2.3) -prog=" -import sys, string -minver = (2,3,0,'final',0) -if sys.version_info < minver: - sys.exit(1) -sys.exit(0)" - -if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC -then - HAVE_PYTHON=yes - AC_MSG_RESULT(okay) -else - HAVE_PYTHON=no - AC_MSG_RESULT(no python) -fi - -AM_CHECK_PYTHON_HEADERS([HAVE_PYTHON_HEADERS=yes],[HAVE_PYTHON_HEADERS=no]) - -dnl check for pygobject (optional, used in the bindings) -PYGOBJECT_REQ=2.11.2 -PKG_CHECK_MODULES(PYGOBJECT, pygobject-2.0 >= $PYGOBJECT_REQ, - [HAVE_PYGOBJECT="yes"], [HAVE_PYGOBJECT="no"]) -AC_SUBST(PYGOBJECT_CFLAGS) - -dnl check for gst-python -PKG_CHECK_MODULES(PYGST, gst-python-0.10, - [HAVE_PYGST="yes"], [HAVE_PYGST="no"]) - -if test "x$HAVE_PYGST" = "xyes"; then - PYGST_DEFSDIR=`pkg-config gst-python-0.10 --variable=defsdir` -fi -AC_SUBST(PYGST_DEFSDIR, $PYGST_DEFSDIR) - -if test \ - "x$HAVE_PYTHON" = "xyes" -a \ - "x$HAVE_PYTHON_HEADERS" = "xyes" -a \ - "x$HAVE_PYGOBJECT" = "xyes" -a \ - "x$HAVE_PYGST" = "xyes"; then - HAVE_PYTHON_BINDINGS="yes" -else - HAVE_PYTHON_BINDINGS="no" -fi - -AM_CONDITIONAL(WITH_PYTHON, [test "x$HAVE_PYTHON_BINDINGS" = "xyes"]) - dnl Check for Vala AC_ARG_ENABLE([vala], AC_HELP_STRING([--enable-vala],[enable Vala bindings (default=yes)]), @@ -242,7 +194,7 @@ AC_SUBST(GST_OPTION_CFLAGS) dnl FIXME: do we want to rename to GST_ALL_* ? dnl prefer internal headers to already installed ones dnl add GST_OPTION_CFLAGS, but overridable -GST_CFLAGS="$GST_CFLAGS \$(GST_OPTION_CFLAGS)" +GST_CFLAGS="$GST_CFLAGS -DGST_USE_UNSTABLE_API \$(GST_OPTION_CFLAGS)" AC_SUBST(GST_CFLAGS) AC_SUBST(GST_LIBS) @@ -251,7 +203,7 @@ dnl vars common to for all internal objects (core libs, elements, applications) dnl CFLAGS: dnl - src and build dirs need to be added because every piece that gets built dnl will need the GStreamer source and generated headers -GST_ALL_CFLAGS="-I\$(top_srcdir) -I\$(top_builddir) $GST_CFLAGS \$(GST_OPTION_CFLAGS)" +GST_ALL_CFLAGS="-I\$(top_srcdir) -I\$(top_builddir) $GST_PLUGINS_BASE_CFLAGS $GST_CFLAGS \$(GST_OPTION_CFLAGS)" AC_SUBST([GST_ALL_CFLAGS]) dnl FIXME: check if LTLIBINTL is needed everywhere @@ -265,11 +217,11 @@ GST_ALL_LDFLAGS="-no-undefined" AC_SUBST(GST_ALL_LDFLAGS) dnl GST_OBJ_* -dnl default vars for all internal objects built on libgstphonon +dnl default vars for all internal objects built on libgstrtspserver dnl includes GST_ALL_* GST_OBJ_CFLAGS="\$(GST_ALL_CFLAGS)" AC_SUBST([GST_OBJ_CFLAGS]) -GST_OBJ_LIBS="\$(top_builddir)/gst-phonon/libgstphonon.la \$(GST_ALL_LIBS)" +GST_OBJ_LIBS="\$(top_builddir)/gst/rtsp-server/libgstrtspserver-$GST_MAJORMINOR.la \$(GST_ALL_LIBS)" AC_SUBST([GST_OBJ_LIBS]) dnl this really should only contain flags, not libs - they get added before @@ -288,12 +240,10 @@ gst/rtsp-server/Makefile examples/Makefile tests/Makefile bindings/Makefile -bindings/python/Makefile -bindings/python/codegen/Makefile bindings/vala/Makefile pkgconfig/Makefile -pkgconfig/gst-rtsp-server.pc -pkgconfig/gst-rtsp-server-uninstalled.pc +pkgconfig/gstreamer-rtsp-server.pc +pkgconfig/gstreamer-rtsp-server-uninstalled.pc docs/Makefile docs/version.entities docs/libs/Makefile @@ -308,7 +258,6 @@ Configuration Prefix : ${prefix} Compiler : ${CC} Vala bindings : ${enable_vala} - Python bindings: : ${HAVE_PYTHON_BINDINGS} -Gst-rtsp-server configured. Type 'make' to build. +gst-rtsp-server configured. Type 'make' to build. " diff --git a/examples/Makefile.am b/examples/Makefile.am index 92f6cf4..9c64305 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1,9 +1,6 @@ noinst_PROGRAMS = test-video test-ogg test-mp4 test-readme test-launch test-sdp test-uri test-auth -INCLUDES = -I$(top_srcdir) -I$(srcdir) - -AM_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) -AM_LDFLAGS = \ - $(GST_LIBS) \ - $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_MAJORMINOR@.la +#INCLUDES = -I$(top_srcdir) -I$(srcdir) +AM_CFLAGS = $(GST_OBJ_CFLAGS) +AM_LDFLAGS = $(GST_OBJ_LIBS) diff --git a/examples/test-auth.c b/examples/test-auth.c index 915173a..5cba45b 100644 --- a/examples/test-auth.c +++ b/examples/test-auth.c @@ -62,9 +62,9 @@ main (int argc, char *argv[]) * element with pay%d names will be a stream */ factory = gst_rtsp_media_factory_new (); gst_rtsp_media_factory_set_launch (factory, "( " - "videotestsrc ! video/x-raw-yuv,width=352,height=288,framerate=15/1 ! " + "videotestsrc ! video/x-raw,width=352,height=288,framerate=15/1 ! " "x264enc ! rtph264pay name=pay0 pt=96 " - "audiotestsrc ! audio/x-raw-int,rate=8000 ! " + "audiotestsrc ! audio/x-raw,rate=8000 ! " "alawenc ! rtppcmapay name=pay1 pt=97 " ")"); /* make a new authentication manager */ @@ -80,7 +80,7 @@ main (int argc, char *argv[]) /* make another factory */ factory = gst_rtsp_media_factory_new (); gst_rtsp_media_factory_set_launch (factory, "( " - "videotestsrc ! video/x-raw-yuv,width=352,height=288,framerate=30/1 ! " + "videotestsrc ! video/x-raw,width=352,height=288,framerate=30/1 ! " "x264enc ! rtph264pay name=pay0 pt=96 )"); /* make a new authentication manager */ auth = gst_rtsp_auth_new (); diff --git a/examples/test-video.c b/examples/test-video.c index c39c8b0..b2536cb 100644 --- a/examples/test-video.c +++ b/examples/test-video.c @@ -80,9 +80,9 @@ main (int argc, char *argv[]) * element with pay%d names will be a stream */ factory = gst_rtsp_media_factory_new (); gst_rtsp_media_factory_set_launch (factory, "( " - "videotestsrc ! video/x-raw-yuv,width=352,height=288,framerate=15/1 ! " + "videotestsrc ! video/x-raw,width=352,height=288,framerate=15/1 ! " "x264enc ! rtph264pay name=pay0 pt=96 " - "audiotestsrc ! audio/x-raw-int,rate=8000 ! " + "audiotestsrc ! audio/x-raw,rate=8000 ! " "alawenc ! rtppcmapay name=pay1 pt=97 " ")"); /* attach the test factory to the /test url */ diff --git a/gst/rtsp-server/.gitignore b/gst/rtsp-server/.gitignore index f94bcca..6091a86 100644 --- a/gst/rtsp-server/.gitignore +++ b/gst/rtsp-server/.gitignore @@ -1,2 +1,2 @@ -GstRtspServer-0.10.gir -GstRtspServer-0.10.typelib +GstRtspServer-0.11.gir +GstRtspServer-0.11.typelib diff --git a/gst/rtsp-server/Makefile.am b/gst/rtsp-server/Makefile.am index 5f640d9..eeac445 100644 --- a/gst/rtsp-server/Makefile.am +++ b/gst/rtsp-server/Makefile.am @@ -12,7 +12,6 @@ public_headers = \ rtsp-server.h c_sources = \ - rtsp-funnel.c \ rtsp-auth.c \ rtsp-params.c \ rtsp-sdp.c \ @@ -25,7 +24,7 @@ c_sources = \ rtsp-client.c \ rtsp-server.c -noinst_HEADERS = rtsp-funnel.h +noinst_HEADERS = lib_LTLIBRARIES = \ libgstrtspserver-@GST_MAJORMINOR@.la diff --git a/gst/rtsp-server/rtsp-client.c b/gst/rtsp-server/rtsp-client.c index 7e05ff9..f814c51 100644 --- a/gst/rtsp-server/rtsp-client.c +++ b/gst/rtsp-server/rtsp-client.c @@ -400,20 +400,24 @@ static gboolean do_send_data (GstBuffer * buffer, guint8 channel, GstRTSPClient * client) { GstRTSPMessage message = { 0 }; + GstMapInfo map_info; guint8 *data; - guint size; + guint usize; gst_rtsp_message_init_data (&message, channel); - data = GST_BUFFER_DATA (buffer); - size = GST_BUFFER_SIZE (buffer); - gst_rtsp_message_take_body (&message, data, size); + if (!gst_buffer_map (buffer, &map_info, GST_MAP_READ)) + return FALSE; + + gst_rtsp_message_take_body (&message, map_info.data, map_info.size); /* FIXME, client->watch could have been finalized here, we need to keep an * extra refcount to the watch. */ gst_rtsp_watch_send_message (client->watch, &message, NULL); - gst_rtsp_message_steal_body (&message, &data, &size); + gst_rtsp_message_steal_body (&message, &data, &usize); + gst_buffer_unmap (buffer, &map_info); + gst_rtsp_message_unset (&message); return TRUE; @@ -423,18 +427,15 @@ static gboolean do_send_data_list (GstBufferList * blist, guint8 channel, GstRTSPClient * client) { - GstBufferListIterator *it; + guint len, i; - it = gst_buffer_list_iterate (blist); - while (gst_buffer_list_iterator_next_group (it)) { - GstBuffer *group = gst_buffer_list_iterator_merge_group (it); + len = gst_buffer_list_len (blist); - if (group == NULL) - continue; + for (i = 0; i < len; i++) { + GstBuffer *group = gst_buffer_list_get (blist, i); do_send_data (group, channel, client); } - gst_buffer_list_iterator_free (it); return TRUE; } @@ -445,8 +446,7 @@ link_stream (GstRTSPClient * client, GstRTSPSession * session, { GST_DEBUG ("client %p: linking stream %p", client, stream); gst_rtsp_session_stream_set_callbacks (stream, (GstRTSPSendFunc) do_send_data, - (GstRTSPSendFunc) do_send_data, (GstRTSPSendListFunc) do_send_data_list, - (GstRTSPSendListFunc) do_send_data_list, client, NULL); + (GstRTSPSendFunc) do_send_data, client, NULL); client->streams = g_list_prepend (client->streams, stream); /* make sure our session can't expire */ gst_rtsp_session_prevent_expire (session); @@ -457,8 +457,7 @@ unlink_stream (GstRTSPClient * client, GstRTSPSession * session, GstRTSPSessionStream * stream) { GST_DEBUG ("client %p: unlinking stream %p", client, stream); - gst_rtsp_session_stream_set_callbacks (stream, NULL, NULL, NULL, NULL, NULL, - NULL); + gst_rtsp_session_stream_set_callbacks (stream, NULL, NULL, NULL, NULL); client->streams = g_list_remove (client->streams, stream); /* our session can now expire */ gst_rtsp_session_allow_expire (session); @@ -1435,9 +1434,8 @@ handle_data (GstRTSPClient * client, GstRTSPMessage * message) gst_rtsp_message_steal_body (message, &data, &size); buffer = gst_buffer_new (); - GST_BUFFER_DATA (buffer) = data; - GST_BUFFER_MALLOCDATA (buffer) = data; - GST_BUFFER_SIZE (buffer) = size; + gst_buffer_take_memory (buffer, -1, + gst_memory_new_wrapped (0, data, size, 0, size, data, g_free)); handled = FALSE; for (walk = client->streams; walk; walk = g_list_next (walk)) { @@ -1892,9 +1890,11 @@ client_watch_notify (GstRTSPClient * client) /** * gst_rtsp_client_attach: * @client: a #GstRTSPClient - * @channel: a #GIOChannel + * @socket: a #GSocket + * @cancellable: a #GCancellable + * @error: a #GError * - * Accept a new connection for @client on the socket in @channel. + * Accept a new connection for @client on @socket. * * This function should be called when the client properties and urls are fully * configured and the client is ready to start. @@ -1902,11 +1902,13 @@ client_watch_notify (GstRTSPClient * client) * Returns: %TRUE if the client could be accepted. */ gboolean -gst_rtsp_client_accept (GstRTSPClient * client, GIOChannel * channel) +gst_rtsp_client_accept (GstRTSPClient * client, GSocket * socket, + GCancellable * cancellable, GError ** error) { - int sock, fd; GstRTSPConnection *conn; GstRTSPResult res; + GSocket *read_socket; + GSocketAddress *addres; GSource *source; GMainContext *context; GstRTSPUrl *url; @@ -1915,17 +1917,18 @@ gst_rtsp_client_accept (GstRTSPClient * client, GIOChannel * channel) gchar ip[INET6_ADDRSTRLEN]; /* a new client connected. */ - sock = g_io_channel_unix_get_fd (channel); + GST_RTSP_CHECK (gst_rtsp_connection_accept (socket, &conn, cancellable), + accept_failed); - GST_RTSP_CHECK (gst_rtsp_connection_accept (sock, &conn), accept_failed); + read_socket = gst_rtsp_connection_get_read_socket (conn); + client->is_ipv6 = g_socket_get_family (socket) == G_SOCKET_FAMILY_IPV6; - fd = gst_rtsp_connection_get_readfd (conn); + if (!(addres = g_socket_get_remote_address (read_socket, error))) + goto no_address; addrlen = sizeof (addr); - if (getsockname (fd, (struct sockaddr *) &addr, &addrlen) < 0) - goto getpeername_failed; - - client->is_ipv6 = addr.ss_family == AF_INET6; + if (!g_socket_address_to_native (addres, &addr, addrlen, error)) + goto native_failed; if (getnameinfo ((struct sockaddr *) &addr, addrlen, ip, sizeof (ip), NULL, 0, NI_NUMERICHOST) != 0) @@ -1965,13 +1968,18 @@ accept_failed: { gchar *str = gst_rtsp_strresult (res); - GST_ERROR ("Could not accept client on server socket %d: %s", sock, str); + GST_ERROR ("Could not accept client on server socket %p: %s", socket, str); g_free (str); return FALSE; } -getpeername_failed: +no_address: + { + GST_ERROR ("could not get remote address %s", (*error)->message); + return FALSE; + } +native_failed: { - GST_ERROR ("getpeername failed: %s", g_strerror (errno)); + GST_ERROR ("could not get native address %s", (*error)->message); return FALSE; } getnameinfo_failed: diff --git a/gst/rtsp-server/rtsp-client.h b/gst/rtsp-server/rtsp-client.h index dc2c79c..bc56cc7 100644 --- a/gst/rtsp-server/rtsp-client.h +++ b/gst/rtsp-server/rtsp-client.h @@ -132,7 +132,9 @@ GstRTSPAuth * gst_rtsp_client_get_auth (GstRTSPClient *client); gboolean gst_rtsp_client_accept (GstRTSPClient *client, - GIOChannel *channel); + GSocket *socket, + GCancellable *cancellable, + GError **error); G_END_DECLS diff --git a/gst/rtsp-server/rtsp-funnel.c b/gst/rtsp-server/rtsp-funnel.c deleted file mode 100644 index 6f073c1..0000000 --- a/gst/rtsp-server/rtsp-funnel.c +++ /dev/null @@ -1,407 +0,0 @@ -/* - * Farsight2 - Farsight Funnel element - * - * Copyright 2007 Collabora Ltd. - * @author: Olivier Crete <olivier.crete@collabora.co.uk> - * Copyright 2007 Nokia Corp. - * - * rtsp-funnel.c: Simple Funnel element - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * SECTION:element-rtspfunnel - * @short_description: N-to-1 simple funnel - * - * Takes packets from various input sinks into one output source - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "rtsp-funnel.h" - -GST_DEBUG_CATEGORY_STATIC (rtsp_funnel_debug); -#define GST_CAT_DEFAULT rtsp_funnel_debug - -static const GstElementDetails rtsp_funnel_details = -GST_ELEMENT_DETAILS ("Farsight Funnel pipe fitting", - "Generic", - "N-to-1 pipe fitting", - "Olivier Crete <olivier.crete@collabora.co.uk>"); - -static GstStaticPadTemplate funnel_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink%d", - GST_PAD_SINK, - GST_PAD_REQUEST, - GST_STATIC_CAPS_ANY); - -static GstStaticPadTemplate funnel_src_template = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - - -static void -_do_init (GType type) -{ - GST_DEBUG_CATEGORY_INIT (rtsp_funnel_debug, "rtspfunnel", 0, - "rtsp funnel element"); -} - -GST_BOILERPLATE_FULL (RTSPFunnel, rtsp_funnel, GstElement, GST_TYPE_ELEMENT, - _do_init); - - - -static GstStateChangeReturn rtsp_funnel_change_state (GstElement * element, - GstStateChange transition); - -static GstPad *rtsp_funnel_request_new_pad (GstElement * element, - GstPadTemplate * templ, const gchar * name); -static void rtsp_funnel_release_pad (GstElement * element, GstPad * pad); - -static GstFlowReturn rtsp_funnel_chain (GstPad * pad, GstBuffer * buffer); -static gboolean rtsp_funnel_event (GstPad * pad, GstEvent * event); -static gboolean rtsp_funnel_src_event (GstPad * pad, GstEvent * event); -static GstCaps *rtsp_funnel_getcaps (GstPad * pad); - - -typedef struct -{ - GstSegment segment; -} RTSPFunnelPadPrivate; - -static void -rtsp_funnel_base_init (gpointer g_class) -{ - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_set_details (gstelement_class, &rtsp_funnel_details); - - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&funnel_sink_template)); - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&funnel_src_template)); -} - - -static void -rtsp_funnel_dispose (GObject * object) -{ - GList *item; - -restart: - for (item = GST_ELEMENT_PADS (object); item; item = g_list_next (item)) { - GstPad *pad = GST_PAD (item->data); - - if (GST_PAD_IS_SINK (pad)) { - gst_element_release_request_pad (GST_ELEMENT (object), pad); - goto restart; - } - } - - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -rtsp_funnel_class_init (RTSPFunnelClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); - - gobject_class->dispose = GST_DEBUG_FUNCPTR (rtsp_funnel_dispose); - - gstelement_class->request_new_pad = - GST_DEBUG_FUNCPTR (rtsp_funnel_request_new_pad); - gstelement_class->release_pad = GST_DEBUG_FUNCPTR (rtsp_funnel_release_pad); - gstelement_class->change_state = GST_DEBUG_FUNCPTR (rtsp_funnel_change_state); -} - -static void -rtsp_funnel_init (RTSPFunnel * funnel, RTSPFunnelClass * g_class) -{ - funnel->srcpad = gst_pad_new_from_static_template (&funnel_src_template, - "src"); - gst_pad_set_event_function (funnel->srcpad, rtsp_funnel_src_event); - gst_pad_use_fixed_caps (funnel->srcpad); - gst_element_add_pad (GST_ELEMENT (funnel), funnel->srcpad); -} - - -static GstPad * -rtsp_funnel_request_new_pad (GstElement * element, GstPadTemplate * templ, - const gchar * name) -{ - GstPad *sinkpad; - RTSPFunnelPadPrivate *priv = g_slice_alloc0 (sizeof (RTSPFunnelPadPrivate)); - - GST_DEBUG_OBJECT (element, "requesting pad"); - - sinkpad = gst_pad_new_from_template (templ, name); - - gst_pad_set_chain_function (sinkpad, GST_DEBUG_FUNCPTR (rtsp_funnel_chain)); - gst_pad_set_event_function (sinkpad, GST_DEBUG_FUNCPTR (rtsp_funnel_event)); - gst_pad_set_getcaps_function (sinkpad, - GST_DEBUG_FUNCPTR (rtsp_funnel_getcaps)); - - gst_segment_init (&priv->segment, GST_FORMAT_UNDEFINED); - gst_pad_set_element_private (sinkpad, priv); - - gst_pad_set_active (sinkpad, TRUE); - - gst_element_add_pad (element, sinkpad); - - return sinkpad; -} - -static void -rtsp_funnel_release_pad (GstElement * element, GstPad * pad) -{ - RTSPFunnel *funnel = RTSP_FUNNEL (element); - RTSPFunnelPadPrivate *priv = gst_pad_get_element_private (pad); - - GST_DEBUG_OBJECT (funnel, "releasing pad"); - - gst_pad_set_active (pad, FALSE); - - if (priv) - g_slice_free1 (sizeof (RTSPFunnelPadPrivate), priv); - - gst_element_remove_pad (GST_ELEMENT_CAST (funnel), pad); -} - -static GstCaps * -rtsp_funnel_getcaps (GstPad * pad) -{ - RTSPFunnel *funnel = RTSP_FUNNEL (gst_pad_get_parent (pad)); - GstCaps *caps; - - caps = gst_pad_peer_get_caps (funnel->srcpad); - if (caps == NULL) - caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); - - gst_object_unref (funnel); - - return caps; -} - -static GstFlowReturn -rtsp_funnel_chain (GstPad * pad, GstBuffer * buffer) -{ - GstFlowReturn res; - RTSPFunnel *funnel = RTSP_FUNNEL (gst_pad_get_parent (pad)); - RTSPFunnelPadPrivate *priv = gst_pad_get_element_private (pad); - GstEvent *event = NULL; - GstClockTime newts; - GstCaps *padcaps; - - GST_DEBUG_OBJECT (funnel, "received buffer %p", buffer); - - GST_OBJECT_LOCK (funnel); - if (priv->segment.format == GST_FORMAT_UNDEFINED) { - GST_WARNING_OBJECT (funnel, "Got buffer without segment," - " setting segment [0,inf["); - gst_segment_set_newsegment_full (&priv->segment, FALSE, 1.0, 1.0, - GST_FORMAT_TIME, 0, -1, 0); - } - - if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) - gst_segment_set_last_stop (&priv->segment, priv->segment.format, - GST_BUFFER_TIMESTAMP (buffer)); - - newts = gst_segment_to_running_time (&priv->segment, - priv->segment.format, GST_BUFFER_TIMESTAMP (buffer)); - if (newts != GST_BUFFER_TIMESTAMP (buffer)) { - buffer = gst_buffer_make_metadata_writable (buffer); - GST_BUFFER_TIMESTAMP (buffer) = newts; - } - - if (!funnel->has_segment) { - event = gst_event_new_new_segment_full (FALSE, 1.0, 1.0, GST_FORMAT_TIME, - 0, -1, 0); - funnel->has_segment = TRUE; - } - GST_OBJECT_UNLOCK (funnel); - - if (event) { - if (!gst_pad_push_event (funnel->srcpad, event)) { - GST_WARNING_OBJECT (funnel, "Could not push out newsegment event"); - res = GST_FLOW_ERROR; - goto out; - } - } - - - GST_OBJECT_LOCK (pad); - padcaps = GST_PAD_CAPS (funnel->srcpad); - GST_OBJECT_UNLOCK (pad); - - if (GST_BUFFER_CAPS (buffer) && GST_BUFFER_CAPS (buffer) != padcaps) { - if (!gst_pad_set_caps (funnel->srcpad, GST_BUFFER_CAPS (buffer))) { - res = GST_FLOW_NOT_NEGOTIATED; - goto out; - } - } - - res = gst_pad_push (funnel->srcpad, buffer); - - GST_LOG_OBJECT (funnel, "handled buffer %s", gst_flow_get_name (res)); - -out: - gst_object_unref (funnel); - - return res; -} - -static gboolean -rtsp_funnel_event (GstPad * pad, GstEvent * event) -{ - RTSPFunnel *funnel = RTSP_FUNNEL (gst_pad_get_parent (pad)); - RTSPFunnelPadPrivate *priv = gst_pad_get_element_private (pad); - gboolean forward = TRUE; - gboolean res = TRUE; - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NEWSEGMENT: - { - gboolean update; - gdouble rate, arate; - GstFormat format; - gint64 start; - gint64 stop; - gint64 time; - - gst_event_parse_new_segment_full (event, &update, &rate, &arate, - &format, &start, &stop, &time); - - - GST_OBJECT_LOCK (funnel); - gst_segment_set_newsegment_full (&priv->segment, update, rate, arate, - format, start, stop, time); - GST_OBJECT_UNLOCK (funnel); - - forward = FALSE; - gst_event_unref (event); - } - break; - case GST_EVENT_FLUSH_STOP: - { - GST_OBJECT_LOCK (funnel); - gst_segment_init (&priv->segment, GST_FORMAT_UNDEFINED); - GST_OBJECT_UNLOCK (funnel); - } - break; - default: - break; - } - - - if (forward) - res = gst_pad_push_event (funnel->srcpad, event); - - gst_object_unref (funnel); - - return res; -} - -static gboolean -rtsp_funnel_src_event (GstPad * pad, GstEvent * event) -{ - GstElement *funnel; - GstIterator *iter; - GstPad *sinkpad; - gboolean result = FALSE; - gboolean done = FALSE; - - funnel = gst_pad_get_parent_element (pad); - g_return_val_if_fail (funnel != NULL, FALSE); - - iter = gst_element_iterate_sink_pads (funnel); - - while (!done) { - switch (gst_iterator_next (iter, (gpointer) & sinkpad)) { - case GST_ITERATOR_OK: - gst_event_ref (event); - result |= gst_pad_push_event (sinkpad, event); - gst_object_unref (sinkpad); - break; - case GST_ITERATOR_RESYNC: - gst_iterator_resync (iter); - result = FALSE; - break; - case GST_ITERATOR_ERROR: - GST_WARNING_OBJECT (funnel, "Error iterating sinkpads"); - case GST_ITERATOR_DONE: - done = TRUE; - break; - } - } - gst_iterator_free (iter); - gst_object_unref (funnel); - gst_event_unref (event); - - return result; -} - -static void -reset_pad (gpointer data, gpointer user_data) -{ - GstPad *pad = data; - RTSPFunnelPadPrivate *priv = gst_pad_get_element_private (pad); - - GST_OBJECT_LOCK (pad); - gst_segment_init (&priv->segment, GST_FORMAT_UNDEFINED); - GST_OBJECT_UNLOCK (pad); - gst_object_unref (pad); -} - -static GstStateChangeReturn -rtsp_funnel_change_state (GstElement * element, GstStateChange transition) -{ - RTSPFunnel *funnel = RTSP_FUNNEL (element); - GstStateChangeReturn ret; - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - { - GstIterator *iter = gst_element_iterate_sink_pads (element); - GstIteratorResult res; - - do { - res = gst_iterator_foreach (iter, reset_pad, NULL); - } while (res == GST_ITERATOR_RESYNC); - - gst_iterator_free (iter); - - if (res == GST_ITERATOR_ERROR) - return GST_STATE_CHANGE_FAILURE; - - GST_OBJECT_LOCK (funnel); - funnel->has_segment = FALSE; - GST_OBJECT_UNLOCK (funnel); - } - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - return ret; -} diff --git a/gst/rtsp-server/rtsp-funnel.h b/gst/rtsp-server/rtsp-funnel.h deleted file mode 100644 index f762d81..0000000 --- a/gst/rtsp-server/rtsp-funnel.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Farsight2 - Farsight Funnel element - * - * Copyright 2007 Collabora Ltd. - * @author: Olivier Crete <olivier.crete@collabora.co.uk> - * Copyright 2007 Nokia Corp. - * - * rtsp-funnel.h: Simple Funnel element - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#ifndef __RTSP_FUNNEL_H__ -#define __RTSP_FUNNEL_H__ - -#include <gst/gst.h> - -G_BEGIN_DECLS - -#define RTSP_TYPE_FUNNEL \ - (rtsp_funnel_get_type ()) -#define RTSP_FUNNEL(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),RTSP_TYPE_FUNNEL,RTSPFunnel)) -#define RTSP_FUNNEL_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),RTSP_TYPE_FUNNEL,RTSPFunnelClass)) -#define RTSP_IS_FUNNEL(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),RTSP_TYPE_FUNNEL)) -#define RTSP_IS_FUNNEL_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),RTSP_TYPE_FUNNEL)) - -typedef struct _RTSPFunnel RTSPFunnel; -typedef struct _RTSPFunnelClass RTSPFunnelClass; - -/** - * RTSPFunnel: - * - * Opaque #RTSPFunnel data structure. - */ -struct _RTSPFunnel { - GstElement element; - - /*< private >*/ - GstPad *srcpad; - - gboolean has_segment; -}; - -struct _RTSPFunnelClass { - GstElementClass parent_class; -}; - -GType rtsp_funnel_get_type (void); - -G_END_DECLS - -#endif /* __RTSP_FUNNEL_H__ */ diff --git a/gst/rtsp-server/rtsp-media-factory-uri.c b/gst/rtsp-server/rtsp-media-factory-uri.c index bb0d661..eee112a 100644 --- a/gst/rtsp-server/rtsp-media-factory-uri.c +++ b/gst/rtsp-server/rtsp-media-factory-uri.c @@ -34,13 +34,10 @@ enum #define RAW_VIDEO_CAPS \ - "video/x-raw-yuv; " \ - "video/x-raw-rgb; " \ - "video/x-raw-gray" + "video/x-raw" #define RAW_AUDIO_CAPS \ - "audio/x-raw-int; " \ - "audio/x-raw-float" + "audio/x-raw" static GstStaticCaps raw_video_caps = GST_STATIC_CAPS (RAW_VIDEO_CAPS); static GstStaticCaps raw_audio_caps = GST_STATIC_CAPS (RAW_AUDIO_CAPS); @@ -150,7 +147,7 @@ payloader_filter (GstPluginFeature * feature, FilterData * data) list = &data->payload; if (list) { - GST_DEBUG ("adding %s", GST_PLUGIN_FEATURE_NAME (fact)); + GST_DEBUG ("adding %s", GST_OBJECT_NAME (fact)); *list = g_list_prepend (*list, fact); } @@ -166,7 +163,7 @@ gst_rtsp_media_factory_uri_init (GstRTSPMediaFactoryURI * factory) factory->use_gstpay = DEFAULT_USE_GSTPAY; /* get the feature list using the filter */ - gst_default_registry_feature_filter ((GstPluginFeatureFilter) + gst_registry_feature_filter (gst_registry_get (), (GstPluginFeatureFilter) payloader_filter, FALSE, &data); /* sort */ factory->demuxers = @@ -393,15 +390,14 @@ pad_added_cb (GstElement * uribin, GstPad * pad, GstElement * element) padname = gst_pad_get_name (pad); /* get pad caps first, then call get_caps, then fail */ - if ((caps = GST_PAD_CAPS (pad))) - gst_caps_ref (caps); - else if ((caps = gst_pad_get_caps (pad)) == NULL) - goto no_caps; + if ((caps = gst_pad_get_current_caps (pad)) == NULL) + if ((caps = gst_pad_query_caps (pad, NULL)) == NULL) + goto no_caps; /* check for raw caps */ if (gst_caps_can_intersect (caps, urifact->raw_vcaps)) { /* we have raw video caps, insert converter */ - convert = gst_element_factory_make ("ffmpegcolorspace", NULL); + convert = gst_element_factory_make ("videoconvert", NULL); } else if (gst_caps_can_intersect (caps, urifact->raw_acaps)) { /* we have raw audio caps, insert converter */ convert = gst_element_factory_make ("audioconvert", NULL); @@ -422,10 +418,9 @@ pad_added_cb (GstElement * uribin, GstPad * pad, GstElement * element) /* continue with new pad and caps */ pad = gst_element_get_static_pad (convert, "src"); - if ((caps = GST_PAD_CAPS (pad))) - gst_caps_ref (caps); - else if ((caps = gst_pad_get_caps (pad)) == NULL) - goto no_caps; + if ((caps = gst_pad_get_current_caps (pad)) == NULL) + if ((caps = gst_pad_query_caps (pad, NULL)) == NULL) + goto no_caps; } if (!(factory = find_payloader (urifact, caps))) diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index 96d039e..fef99ca 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -23,7 +23,6 @@ #include <gst/app/gstappsrc.h> #include <gst/app/gstappsink.h> -#include "rtsp-funnel.h" #include "rtsp-media.h" #define DEFAULT_SHARED FALSE @@ -148,9 +147,6 @@ gst_rtsp_media_class_init (GstRTSPMediaClass * klass) klass->unprepare = default_unprepare; ssrc_stream_map_key = g_quark_from_static_string ("GstRTSPServer.stream"); - - gst_element_register (NULL, "rtspfunnel", GST_RANK_NONE, RTSP_TYPE_FUNNEL); - } static void @@ -318,7 +314,6 @@ do_loop (GstRTSPMediaClass * klass) static void collect_media_stats (GstRTSPMedia * media) { - GstFormat format; gint64 position, duration; media->range.unit = GST_RTSP_RANGE_NPT; @@ -330,15 +325,15 @@ collect_media_stats (GstRTSPMedia * media) media->range.max.seconds = -1; } else { /* get the position */ - format = GST_FORMAT_TIME; - if (!gst_element_query_position (media->pipeline, &format, &position)) { + if (!gst_element_query_position (media->pipeline, GST_FORMAT_TIME, + &position)) { GST_INFO ("position query failed"); position = 0; } /* get the duration */ - format = GST_FORMAT_TIME; - if (!gst_element_query_duration (media->pipeline, &format, &duration)) { + if (!gst_element_query_duration (media->pipeline, GST_FORMAT_TIME, + &duration)) { GST_INFO ("duration query failed"); duration = -1; } @@ -856,7 +851,8 @@ alloc_udp_ports (GstRTSPMedia * media, GstRTSPMediaStream * stream) GstElement *udpsink0, *udpsink1; gint tmp_rtp, tmp_rtcp; guint count; - gint rtpport, rtcpport, sockfd; + gint rtpport, rtcpport; + GSocket *socket; const gchar *host; udpsrc0 = NULL; @@ -949,9 +945,9 @@ again: if (!udpsink0) goto no_udp_protocol; - g_object_get (G_OBJECT (udpsrc0), "sock", &sockfd, NULL); - g_object_set (G_OBJECT (udpsink0), "sockfd", sockfd, NULL); - g_object_set (G_OBJECT (udpsink0), "closefd", FALSE, NULL); + g_object_get (G_OBJECT (udpsrc0), "socket", &socket, NULL); + g_object_set (G_OBJECT (udpsink0), "socket", socket, NULL); + g_object_set (G_OBJECT (udpsink0), "close-socket", FALSE, NULL); udpsink1 = gst_element_factory_make ("multiudpsink", NULL); if (!udpsink1) @@ -973,9 +969,9 @@ again: GST_WARNING ("multiudpsink version found without buffer-size property"); } - g_object_get (G_OBJECT (udpsrc1), "sock", &sockfd, NULL); - g_object_set (G_OBJECT (udpsink1), "sockfd", sockfd, NULL); - g_object_set (G_OBJECT (udpsink1), "closefd", FALSE, NULL); + g_object_get (G_OBJECT (udpsrc1), "socket", &socket, NULL); + g_object_set (G_OBJECT (udpsink1), "socket", socket, NULL); + g_object_set (G_OBJECT (udpsink1), "close-socket", FALSE, NULL); g_object_set (G_OBJECT (udpsink1), "sync", FALSE, NULL); g_object_set (G_OBJECT (udpsink1), "async", FALSE, NULL); @@ -1041,8 +1037,7 @@ caps_notify (GstPad * pad, GParamSpec * unused, GstRTSPMediaStream * stream) gchar *capsstr; GstCaps *newcaps, *oldcaps; - if ((newcaps = GST_PAD_CAPS (pad))) - gst_caps_ref (newcaps); + newcaps = gst_pad_get_current_caps (pad); oldcaps = stream->caps; stream->caps = newcaps; @@ -1203,17 +1198,19 @@ on_timeout (GObject * session, GObject * source, GstRTSPMediaStream * stream) } static GstFlowReturn -handle_new_buffer (GstAppSink * sink, gpointer user_data) +handle_new_sample (GstAppSink * sink, gpointer user_data) { GList *walk; + GstSample *sample; GstBuffer *buffer; GstRTSPMediaStream *stream; - buffer = gst_app_sink_pull_buffer (sink); - if (!buffer) + sample = gst_app_sink_pull_sample (sink); + if (!sample) return GST_FLOW_OK; stream = (GstRTSPMediaStream *) user_data; + buffer = gst_sample_get_buffer (sample); for (walk = stream->transports; walk; walk = g_list_next (walk)) { GstRTSPMediaTrans *tr = (GstRTSPMediaTrans *) walk->data; @@ -1226,47 +1223,15 @@ handle_new_buffer (GstAppSink * sink, gpointer user_data) tr->send_rtcp (buffer, tr->transport->interleaved.max, tr->user_data); } } - gst_buffer_unref (buffer); - - return GST_FLOW_OK; -} - -static GstFlowReturn -handle_new_buffer_list (GstAppSink * sink, gpointer user_data) -{ - GList *walk; - GstBufferList *blist; - GstRTSPMediaStream *stream; - - blist = gst_app_sink_pull_buffer_list (sink); - if (!blist) - return GST_FLOW_OK; - - stream = (GstRTSPMediaStream *) user_data; - - for (walk = stream->transports; walk; walk = g_list_next (walk)) { - GstRTSPMediaTrans *tr = (GstRTSPMediaTrans *) walk->data; - - if (GST_ELEMENT_CAST (sink) == stream->appsink[0]) { - if (tr->send_rtp_list) - tr->send_rtp_list (blist, tr->transport->interleaved.min, - tr->user_data); - } else { - if (tr->send_rtcp_list) - tr->send_rtcp_list (blist, tr->transport->interleaved.max, - tr->user_data); - } - } - gst_buffer_list_unref (blist); + gst_sample_unref (sample); return GST_FLOW_OK; } static GstAppSinkCallbacks sink_cb = { NULL, /* not interested in EOS */ - NULL, /* not interested in preroll buffers */ - handle_new_buffer, - handle_new_buffer_list + NULL, /* not interested in preroll samples */ + handle_new_sample, }; /* prepare the pipeline objects to handle @stream in @media */ @@ -1274,7 +1239,7 @@ static gboolean setup_stream (GstRTSPMediaStream * stream, guint idx, GstRTSPMedia * media) { gchar *name; - GstPad *pad, *teepad, *selpad; + GstPad *pad, *teepad, *queuepad, *selpad; GstPadLinkReturn ret; gint i; @@ -1293,10 +1258,11 @@ setup_stream (GstRTSPMediaStream * stream, guint idx, GstRTSPMedia * media) /* create elements for the TCP transfer */ for (i = 0; i < 2; i++) { stream->appsrc[i] = gst_element_factory_make ("appsrc", NULL); + stream->appqueue[i] = gst_element_factory_make ("queue", NULL); stream->appsink[i] = gst_element_factory_make ("appsink", NULL); g_object_set (stream->appsink[i], "async", FALSE, "sync", FALSE, NULL); g_object_set (stream->appsink[i], "emit-signals", FALSE, NULL); - g_object_set (stream->appsink[i], "preroll-queue-len", 1, NULL); + gst_bin_add (GST_BIN_CAST (media->pipeline), stream->appqueue[i]); gst_bin_add (GST_BIN_CAST (media->pipeline), stream->appsink[i]); gst_bin_add (GST_BIN_CAST (media->pipeline), stream->appsrc[i]); gst_app_sink_set_callbacks (GST_APP_SINK_CAST (stream->appsink[i]), @@ -1304,19 +1270,19 @@ setup_stream (GstRTSPMediaStream * stream, guint idx, GstRTSPMedia * media) } /* hook up the stream to the RTP session elements. */ - name = g_strdup_printf ("send_rtp_sink_%d", idx); + name = g_strdup_printf ("send_rtp_sink_%u", idx); stream->send_rtp_sink = gst_element_get_request_pad (media->rtpbin, name); g_free (name); - name = g_strdup_printf ("send_rtp_src_%d", idx); + name = g_strdup_printf ("send_rtp_src_%u", idx); stream->send_rtp_src = gst_element_get_static_pad (media->rtpbin, name); g_free (name); - name = g_strdup_printf ("send_rtcp_src_%d", idx); + name = g_strdup_printf ("send_rtcp_src_%u", idx); stream->send_rtcp_src = gst_element_get_request_pad (media->rtpbin, name); g_free (name); - name = g_strdup_printf ("recv_rtcp_sink_%d", idx); + name = g_strdup_printf ("recv_rtcp_sink_%u", idx); stream->recv_rtcp_sink = gst_element_get_request_pad (media->rtpbin, name); g_free (name); - name = g_strdup_printf ("recv_rtp_sink_%d", idx); + name = g_strdup_printf ("recv_rtp_sink_%u", idx); stream->recv_rtp_sink = gst_element_get_request_pad (media->rtpbin, name); g_free (name); @@ -1351,18 +1317,24 @@ setup_stream (GstRTSPMediaStream * stream, guint idx, GstRTSPMedia * media) gst_object_unref (pad); /* link RTP sink, we're pretty sure this will work. */ - teepad = gst_element_get_request_pad (stream->tee[0], "src%d"); + teepad = gst_element_get_request_pad (stream->tee[0], "src_%u"); pad = gst_element_get_static_pad (stream->udpsink[0], "sink"); gst_pad_link (teepad, pad); gst_object_unref (pad); gst_object_unref (teepad); - teepad = gst_element_get_request_pad (stream->tee[0], "src%d"); - pad = gst_element_get_static_pad (stream->appsink[0], "sink"); + teepad = gst_element_get_request_pad (stream->tee[0], "src_%u"); + pad = gst_element_get_static_pad (stream->appqueue[0], "sink"); gst_pad_link (teepad, pad); gst_object_unref (pad); gst_object_unref (teepad); + queuepad = gst_element_get_static_pad (stream->appqueue[0], "src"); + pad = gst_element_get_static_pad (stream->appsink[0], "sink"); + gst_pad_link (queuepad, pad); + gst_object_unref (pad); + gst_object_unref (queuepad); + /* make tee for RTCP */ stream->tee[1] = gst_element_factory_make ("tee", NULL); gst_bin_add (GST_BIN_CAST (media->pipeline), stream->tee[1]); @@ -1372,53 +1344,59 @@ setup_stream (GstRTSPMediaStream * stream, guint idx, GstRTSPMedia * media) gst_object_unref (pad); /* link RTCP elements */ - teepad = gst_element_get_request_pad (stream->tee[1], "src%d"); + teepad = gst_element_get_request_pad (stream->tee[1], "src_%u"); pad = gst_element_get_static_pad (stream->udpsink[1], "sink"); gst_pad_link (teepad, pad); gst_object_unref (pad); gst_object_unref (teepad); - teepad = gst_element_get_request_pad (stream->tee[1], "src%d"); - pad = gst_element_get_static_pad (stream->appsink[1], "sink"); + teepad = gst_element_get_request_pad (stream->tee[1], "src_%u"); + pad = gst_element_get_static_pad (stream->appqueue[1], "sink"); gst_pad_link (teepad, pad); gst_object_unref (pad); gst_object_unref (teepad); + queuepad = gst_element_get_static_pad (stream->appqueue[1], "src"); + pad = gst_element_get_static_pad (stream->appsink[1], "sink"); + gst_pad_link (queuepad, pad); + gst_object_unref (pad); + gst_object_unref (queuepad); + /* make selector for the RTP receivers */ - stream->selector[0] = gst_element_factory_make ("rtspfunnel", NULL); + stream->selector[0] = gst_element_factory_make ("funnel", NULL); gst_bin_add (GST_BIN_CAST (media->pipeline), stream->selector[0]); pad = gst_element_get_static_pad (stream->selector[0], "src"); gst_pad_link (pad, stream->recv_rtp_sink); gst_object_unref (pad); - selpad = gst_element_get_request_pad (stream->selector[0], "sink%d"); + selpad = gst_element_get_request_pad (stream->selector[0], "sink_%u"); pad = gst_element_get_static_pad (stream->udpsrc[0], "src"); gst_pad_link (pad, selpad); gst_object_unref (pad); gst_object_unref (selpad); - selpad = gst_element_get_request_pad (stream->selector[0], "sink%d"); + selpad = gst_element_get_request_pad (stream->selector[0], "sink_%u"); pad = gst_element_get_static_pad (stream->appsrc[0], "src"); gst_pad_link (pad, selpad); gst_object_unref (pad); gst_object_unref (selpad); /* make selector for the RTCP receivers */ - stream->selector[1] = gst_element_factory_make ("rtspfunnel", NULL); + stream->selector[1] = gst_element_factory_make ("funnel", NULL); gst_bin_add (GST_BIN_CAST (media->pipeline), stream->selector[1]); pad = gst_element_get_static_pad (stream->selector[1], "src"); gst_pad_link (pad, stream->recv_rtcp_sink); gst_object_unref (pad); - selpad = gst_element_get_request_pad (stream->selector[1], "sink%d"); + selpad = gst_element_get_request_pad (stream->selector[1], "sink_%u"); pad = gst_element_get_static_pad (stream->udpsrc[1], "src"); gst_pad_link (pad, selpad); gst_object_unref (pad); gst_object_unref (selpad); - selpad = gst_element_get_request_pad (stream->selector[1], "sink%d"); + selpad = gst_element_get_request_pad (stream->selector[1], "sink_%u"); pad = gst_element_get_static_pad (stream->appsrc[1], "src"); gst_pad_link (pad, selpad); gst_object_unref (pad); @@ -1658,6 +1636,7 @@ pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media) for (i = 0; i < 2; i++) { gst_element_set_state (stream->udpsink[i], GST_STATE_PAUSED); gst_element_set_state (stream->appsink[i], GST_STATE_PAUSED); + gst_element_set_state (stream->appqueue[i], GST_STATE_PAUSED); gst_element_set_state (stream->tee[i], GST_STATE_PAUSED); gst_element_set_state (stream->selector[i], GST_STATE_PAUSED); gst_element_set_state (stream->appsrc[i], GST_STATE_PAUSED); @@ -1707,6 +1686,10 @@ gst_rtsp_media_prepare (GstRTSPMedia * media) if (!media->reusable && media->reused) goto is_reused; + media->rtpbin = gst_element_factory_make ("rtpbin", NULL); + if (media->rtpbin == NULL) + goto no_rtpbin; + GST_INFO ("preparing media %p", media); /* reset some variables */ @@ -1727,8 +1710,6 @@ gst_rtsp_media_prepare (GstRTSPMedia * media) klass = GST_RTSP_MEDIA_GET_CLASS (media); media->id = g_source_attach (media->source, klass->context); - media->rtpbin = gst_element_factory_make ("gstrtpbin", NULL); - /* add stuff to the bin */ gst_bin_add (GST_BIN (media->pipeline), media->rtpbin); @@ -1808,6 +1789,12 @@ is_reused: GST_WARNING ("can not reuse media %p", media); return FALSE; } +no_rtpbin: + { + GST_WARNING ("no rtpbin element"); + g_warning ("failed to create element 'rtpbin', check your installation"); + return FALSE; + } state_failed: { GST_WARNING ("failed to preroll pipeline"); @@ -2069,6 +2056,7 @@ gst_rtsp_media_remove_elements (GstRTSPMedia * media) gst_element_set_state (stream->udpsink[j], GST_STATE_NULL); gst_element_set_state (stream->appsrc[j], GST_STATE_NULL); gst_element_set_state (stream->appsink[j], GST_STATE_NULL); + gst_element_set_state (stream->appqueue[j], GST_STATE_NULL); gst_element_set_state (stream->tee[j], GST_STATE_NULL); gst_element_set_state (stream->selector[j], GST_STATE_NULL); @@ -2076,6 +2064,7 @@ gst_rtsp_media_remove_elements (GstRTSPMedia * media) gst_bin_remove (GST_BIN (media->pipeline), stream->udpsink[j]); gst_bin_remove (GST_BIN (media->pipeline), stream->appsrc[j]); gst_bin_remove (GST_BIN (media->pipeline), stream->appsink[j]); + gst_bin_remove (GST_BIN (media->pipeline), stream->appqueue[j]); gst_bin_remove (GST_BIN (media->pipeline), stream->tee[j]); gst_bin_remove (GST_BIN (media->pipeline), stream->selector[j]); } diff --git a/gst/rtsp-server/rtsp-media.h b/gst/rtsp-server/rtsp-media.h index a7334ed..38f7c35 100644 --- a/gst/rtsp-server/rtsp-media.h +++ b/gst/rtsp-server/rtsp-media.h @@ -42,7 +42,6 @@ typedef struct _GstRTSPMediaClass GstRTSPMediaClass; typedef struct _GstRTSPMediaTrans GstRTSPMediaTrans; typedef gboolean (*GstRTSPSendFunc) (GstBuffer *buffer, guint8 channel, gpointer user_data); -typedef gboolean (*GstRTSPSendListFunc) (GstBufferList *blist, guint8 channel, gpointer user_data); typedef void (*GstRTSPKeepAliveFunc) (gpointer user_data); /** @@ -69,8 +68,6 @@ struct _GstRTSPMediaTrans { GstRTSPSendFunc send_rtp; GstRTSPSendFunc send_rtcp; - GstRTSPSendListFunc send_rtp_list; - GstRTSPSendListFunc send_rtcp_list; gpointer user_data; GDestroyNotify notify; @@ -128,6 +125,7 @@ struct _GstRTSPMediaStream { GstElement *udpsink[2]; /* for TCP transport */ GstElement *appsrc[2]; + GstElement *appqueue[2]; GstElement *appsink[2]; GstElement *tee[2]; diff --git a/gst/rtsp-server/rtsp-server.c b/gst/rtsp-server/rtsp-server.c index f1f431f..6cef196 100644 --- a/gst/rtsp-server/rtsp-server.c +++ b/gst/rtsp-server/rtsp-server.c @@ -78,7 +78,7 @@ static void gst_rtsp_server_finalize (GObject * object); static GstRTSPClient *default_create_client (GstRTSPServer * server); static gboolean default_accept_client (GstRTSPServer * server, - GstRTSPClient * client, GIOChannel * channel); + GstRTSPClient * client, GSocket * socket, GError ** error); static void gst_rtsp_server_class_init (GstRTSPServerClass * klass) @@ -546,87 +546,94 @@ gst_rtsp_server_set_property (GObject * object, guint propid, } /** - * gst_rtsp_server_get_io_channel: + * gst_rtsp_server_create_socket: * @server: a #GstRTSPServer + * @cancellable: a #GCancellable + * @error: a #GError * - * Create a #GIOChannel for @server. The io channel will listen on the + * Create a #GSocket for @server. The socket will listen on the * configured service. * - * Returns: the GIOChannel for @server or NULL when an error occured. + * Returns: the #GSocket for @server or NULL when an error occured. */ -GIOChannel * -gst_rtsp_server_get_io_channel (GstRTSPServer * server) +GSocket * +gst_rtsp_server_create_socket (GstRTSPServer * server, + GCancellable * cancellable, GError ** error) { - GIOChannel *channel; - int ret, sockfd = -1; - struct addrinfo hints; - struct addrinfo *result, *rp; + GSocketConnectable *conn; + GSocketAddressEnumerator *enumerator; + GSocket *socket; #ifdef USE_SOLINGER struct linger linger; #endif + GError *sock_error = NULL; + GError *bind_error = NULL; + guint16 port; g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL); - memset (&hints, 0, sizeof (struct addrinfo)); - hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ - hints.ai_socktype = SOCK_STREAM; /* stream socket */ - hints.ai_flags = AI_PASSIVE | AI_CANONNAME; /* For wildcard IP address */ - hints.ai_protocol = 0; /* Any protocol */ - hints.ai_canonname = NULL; - hints.ai_addr = NULL; - hints.ai_next = NULL; - + GST_RTSP_SERVER_LOCK (server); GST_DEBUG_OBJECT (server, "getting address info of %s/%s", server->address, server->service); - GST_RTSP_SERVER_LOCK (server); /* resolve the server IP address */ - if ((ret = - getaddrinfo (server->address, server->service, &hints, &result)) != 0) - goto no_address; + port = atoi (server->service); + if (port != 0) + conn = g_network_address_new (server->address, port); + else + conn = g_network_service_new (server->service, "tcp", server->address); + + enumerator = g_socket_connectable_enumerate (conn); + g_object_unref (conn); /* create server socket, we loop through all the addresses until we manage to * create a socket and bind. */ - for (rp = result; rp; rp = rp->ai_next) { - sockfd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if (sockfd == -1) { - GST_DEBUG_OBJECT (server, "failed to make socket (%s), try next", - g_strerror (errno)); - continue; + while (TRUE) { + GSocketAddress *sockaddr; + + sockaddr = + g_socket_address_enumerator_next (enumerator, cancellable, error); + if (!sockaddr) { + GST_DEBUG_OBJECT (server, "no more addresses %s", (*error)->message); + break; } - /* make address reusable */ - ret = 1; - if (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, - (void *) &ret, sizeof (ret)) < 0) { - /* warn but try to bind anyway */ - GST_WARNING_OBJECT (server, "failed to reuse socker (%s)", - g_strerror (errno)); + /* only keep the first error */ + socket = g_socket_new (g_socket_address_get_family (sockaddr), + G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, + sock_error ? NULL : &sock_error); + + if (socket == NULL) { + GST_DEBUG_OBJECT (server, "failed to make socket (%s), try next", + sock_error->message); + continue; } - if (bind (sockfd, rp->ai_addr, rp->ai_addrlen) == 0) { - GST_DEBUG_OBJECT (server, "bind on %s", rp->ai_canonname); + if (g_socket_bind (socket, sockaddr, TRUE, bind_error ? NULL : &bind_error)) { + g_object_unref (sockaddr); break; } GST_DEBUG_OBJECT (server, "failed to bind socket (%s), try next", - g_strerror (errno)); - close (sockfd); - sockfd = -1; + bind_error->message); + g_object_unref (sockaddr); + g_object_unref (socket); + socket = NULL; } - freeaddrinfo (result); + g_object_unref (enumerator); - if (sockfd == -1) + if (socket == NULL) goto no_socket; - GST_DEBUG_OBJECT (server, "opened sending server socket with fd %d", sockfd); + g_clear_error (&sock_error); + g_clear_error (&bind_error); + + GST_DEBUG_OBJECT (server, "opened sending server socket"); /* keep connection alive; avoids SIGPIPE during write */ - ret = 1; - if (setsockopt (sockfd, SOL_SOCKET, SO_KEEPALIVE, - (void *) &ret, sizeof (ret)) < 0) - goto keepalive_failed; + g_socket_set_keepalive (socket, TRUE); +#if 0 #ifdef USE_SOLINGER /* make sure socket is reset 5 seconds after close. This ensure that we can * reuse the socket quickly while still having a chance to send data to the @@ -637,50 +644,31 @@ gst_rtsp_server_get_io_channel (GstRTSPServer * server) (void *) &linger, sizeof (linger)) < 0) goto linger_failed; #endif +#endif /* set the server socket to nonblocking */ - fcntl (sockfd, F_SETFL, O_NONBLOCK); + g_socket_set_blocking (socket, FALSE); - GST_DEBUG_OBJECT (server, "listening on server socket %d with queue of %d", - sockfd, server->backlog); - if (listen (sockfd, server->backlog) == -1) + /* set listen backlog */ + g_socket_set_listen_backlog (socket, server->backlog); + + if (!g_socket_listen (socket, error)) goto listen_failed; - GST_DEBUG_OBJECT (server, - "listened on server socket %d, returning from connection setup", sockfd); + GST_DEBUG_OBJECT (server, "listening on server socket %p with queue of %d", + socket, server->backlog); - /* create IO channel for the socket */ -#ifdef G_OS_WIN32 - channel = g_io_channel_win32_new_socket (sockfd); -#else - channel = g_io_channel_unix_new (sockfd); -#endif - g_io_channel_set_close_on_unref (channel, TRUE); - - GST_INFO_OBJECT (server, "listening on service %s", server->service); GST_RTSP_SERVER_UNLOCK (server); - return channel; + return socket; /* ERRORS */ -no_address: - { - GST_ERROR_OBJECT (server, "failed to resolve address: %s", - gai_strerror (ret)); - goto close_error; - } no_socket: { - GST_ERROR_OBJECT (server, "failed to create socket: %s", - g_strerror (errno)); - goto close_error; - } -keepalive_failed: - { - GST_ERROR_OBJECT (server, "failed to configure keepalive socket: %s", - g_strerror (errno)); + GST_ERROR_OBJECT (server, "failed to create socket"); goto close_error; } +#if 0 #ifdef USE_SOLINGER linger_failed: { @@ -689,16 +677,29 @@ linger_failed: goto close_error; } #endif +#endif listen_failed: { GST_ERROR_OBJECT (server, "failed to listen on socket: %s", - g_strerror (errno)); + (*error)->message); goto close_error; } close_error: { - if (sockfd >= 0) { - close (sockfd); + if (socket) + g_object_unref (socket); + + if (sock_error) { + if (error == NULL) + g_propagate_error (error, sock_error); + else + g_error_free (sock_error); + } + if (bind_error) { + if (error == NULL) + g_propagate_error (error, bind_error); + else + g_error_free (bind_error); } GST_RTSP_SERVER_UNLOCK (server); return NULL; @@ -759,12 +760,12 @@ default_create_client (GstRTSPServer * server) * handle a client connection on this server */ static gboolean default_accept_client (GstRTSPServer * server, GstRTSPClient * client, - GIOChannel * channel) + GSocket * socket, GError ** error) { /* accept connections for that client, this function returns after accepting * the connection and will run the remainder of the communication with the * client asyncronously. */ - if (!gst_rtsp_client_accept (client, channel)) + if (!gst_rtsp_client_accept (client, socket, NULL, error)) goto accept_failed; return TRUE; @@ -773,29 +774,29 @@ default_accept_client (GstRTSPServer * server, GstRTSPClient * client, accept_failed: { GST_ERROR_OBJECT (server, - "Could not accept client on server : %s (%d)", g_strerror (errno), - errno); + "Could not accept client on server : %s", (*error)->message); return FALSE; } } /** * gst_rtsp_server_io_func: - * @channel: a #GIOChannel + * @socket: a #GSocket * @condition: the condition on @source * - * A default #GIOFunc that creates a new #GstRTSPClient to accept and handle a - * new connection on @channel or @server. + * A default #GSocketSourceFunc that creates a new #GstRTSPClient to accept and handle a + * new connection on @socket or @server. * * Returns: TRUE if the source could be connected, FALSE if an error occured. */ gboolean -gst_rtsp_server_io_func (GIOChannel * channel, GIOCondition condition, +gst_rtsp_server_io_func (GSocket * socket, GIOCondition condition, GstRTSPServer * server) { gboolean result; GstRTSPClient *client = NULL; GstRTSPServerClass *klass; + GError *error = NULL; if (condition & G_IO_IN) { klass = GST_RTSP_SERVER_GET_CLASS (server); @@ -807,7 +808,7 @@ gst_rtsp_server_io_func (GIOChannel * channel, GIOCondition condition, /* a new client connected, create a client object to handle the client. */ if (klass->accept_client) - result = klass->accept_client (server, client, channel); + result = klass->accept_client (server, client, socket, &error); if (!result) goto accept_failed; @@ -829,7 +830,8 @@ client_failed: } accept_failed: { - GST_ERROR_OBJECT (server, "failed to accept client"); + GST_ERROR_OBJECT (server, "failed to accept client: %s", error->message); + g_error_free (error); gst_object_unref (client); return FALSE; } @@ -843,30 +845,39 @@ watch_destroyed (GstRTSPServer * server) } /** - * gst_rtsp_server_create_watch: + * gst_rtsp_server_create_source: * @server: a #GstRTSPServer + * @cancellable: a #GCancellable or %NULL. + * @error: a #GError * * Create a #GSource for @server. The new source will have a default - * #GIOFunc of gst_rtsp_server_io_func(). + * #GSocketSourceFunc of gst_rtsp_server_io_func(). * - * Returns: the #GSource for @server or NULL when an error occured. + * @cancellable if not NULL can be used to cancel the source, which will cause + * the source to trigger, reporting the current condition (which is likely 0 + * unless cancellation happened at the same time as a condition change). You can + * check for this in the callback using g_cancellable_is_cancelled(). + * + * Returns: the #GSource for @server or NULL when an error occured. Free with + * g_source_unref () */ GSource * -gst_rtsp_server_create_watch (GstRTSPServer * server) +gst_rtsp_server_create_source (GstRTSPServer * server, + GCancellable * cancellable, GError ** error) { - GIOChannel *channel; + GSocket *socket; GSource *source; g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL); - channel = gst_rtsp_server_get_io_channel (server); - if (channel == NULL) - goto no_channel; + socket = gst_rtsp_server_create_socket (server, NULL, error); + if (socket == NULL) + goto no_socket; /* create a watch for reads (new connections) and possible errors */ - source = g_io_create_watch (channel, G_IO_IN | - G_IO_ERR | G_IO_HUP | G_IO_NVAL); - g_io_channel_unref (channel); + source = g_socket_create_source (socket, G_IO_IN | + G_IO_ERR | G_IO_HUP | G_IO_NVAL, cancellable); + g_object_unref (socket); /* configure the callback */ g_source_set_callback (source, @@ -875,9 +886,9 @@ gst_rtsp_server_create_watch (GstRTSPServer * server) return source; -no_channel: +no_socket: { - GST_ERROR_OBJECT (server, "failed to create IO channel"); + GST_ERROR_OBJECT (server, "failed to create socket"); return NULL; } } @@ -886,6 +897,7 @@ no_channel: * gst_rtsp_server_attach: * @server: a #GstRTSPServer * @context: a #GMainContext + * @error: a #GError * * Attaches @server to @context. When the mainloop for @context is run, the * server will be dispatched. When @context is NULL, the default context will be @@ -901,10 +913,11 @@ gst_rtsp_server_attach (GstRTSPServer * server, GMainContext * context) { guint res; GSource *source; + GError *error = NULL; g_return_val_if_fail (GST_IS_RTSP_SERVER (server), 0); - source = gst_rtsp_server_create_watch (server); + source = gst_rtsp_server_create_source (server, NULL, &error); if (source == NULL) goto no_source; @@ -916,7 +929,8 @@ gst_rtsp_server_attach (GstRTSPServer * server, GMainContext * context) /* ERRORS */ no_source: { - GST_ERROR_OBJECT (server, "failed to create watch"); + GST_ERROR_OBJECT (server, "failed to create watch: %s", error->message); + g_error_free (error); return 0; } } diff --git a/gst/rtsp-server/rtsp-server.h b/gst/rtsp-server/rtsp-server.h index 98a3391..dd6e386 100644 --- a/gst/rtsp-server/rtsp-server.h +++ b/gst/rtsp-server/rtsp-server.h @@ -79,7 +79,7 @@ struct _GstRTSPServer { * GstRTSPServerClass: * * @create_client: Create, configure a new GstRTSPClient - * object that handles the new connection on @channel. + * object that handles the new connection on @socket. * @accept_client: accept a new GstRTSPClient * * The RTSP server class structure @@ -88,8 +88,8 @@ struct _GstRTSPServerClass { GObjectClass parent_class; GstRTSPClient * (*create_client) (GstRTSPServer *server); - gboolean (*accept_client) (GstRTSPServer *server, GstRTSPClient *client, GIOChannel *channel); - + gboolean (*accept_client) (GstRTSPServer *server, GstRTSPClient *client, + GSocket *socket, GError **error); /* signals */ void (*client_connected) (GstRTSPServer *server, GstRTSPClient *client); }; @@ -116,11 +116,15 @@ GstRTSPMediaMapping * gst_rtsp_server_get_media_mapping (GstRTSPServer *serve void gst_rtsp_server_set_auth (GstRTSPServer *server, GstRTSPAuth *auth); GstRTSPAuth * gst_rtsp_server_get_auth (GstRTSPServer *server); -gboolean gst_rtsp_server_io_func (GIOChannel *channel, GIOCondition condition, +gboolean gst_rtsp_server_io_func (GSocket *socket, GIOCondition condition, GstRTSPServer *server); -GIOChannel * gst_rtsp_server_get_io_channel (GstRTSPServer *server); -GSource * gst_rtsp_server_create_watch (GstRTSPServer *server); +GSocket * gst_rtsp_server_create_socket (GstRTSPServer *server, + GCancellable *cancellable, + GError **error); +GSource * gst_rtsp_server_create_source (GstRTSPServer *server, + GCancellable * cancellable, + GError **error); guint gst_rtsp_server_attach (GstRTSPServer *server, GMainContext *context); diff --git a/gst/rtsp-server/rtsp-session-pool.c b/gst/rtsp-server/rtsp-session-pool.c index de9234e..1d00dc4 100644 --- a/gst/rtsp-server/rtsp-session-pool.c +++ b/gst/rtsp-server/rtsp-session-pool.c @@ -477,7 +477,7 @@ collect_timeout (gchar * sessionid, GstRTSPSession * sess, GstPoolSource * psrc) gint timeout; GTimeVal now; - g_source_get_current_time ((GSource *) psrc, &now); + g_get_current_time (&now); timeout = gst_rtsp_session_next_timeout (sess, &now); GST_INFO ("%p: next timeout: %d", sess, timeout); diff --git a/gst/rtsp-server/rtsp-session.c b/gst/rtsp-server/rtsp-session.c index ce86d43..de16415 100644 --- a/gst/rtsp-server/rtsp-session.c +++ b/gst/rtsp-server/rtsp-session.c @@ -82,8 +82,7 @@ gst_rtsp_session_free_stream (GstRTSPSessionStream * stream) GST_INFO ("free session stream %p", stream); /* remove callbacks now */ - gst_rtsp_session_stream_set_callbacks (stream, NULL, NULL, NULL, NULL, NULL, - NULL); + gst_rtsp_session_stream_set_callbacks (stream, NULL, NULL, NULL, NULL); gst_rtsp_session_stream_set_keepalive (stream, NULL, NULL, NULL); gst_rtsp_media_trans_cleanup (&stream->trans); @@ -564,13 +563,10 @@ gst_rtsp_session_stream_set_transport (GstRTSPSessionStream * stream, void gst_rtsp_session_stream_set_callbacks (GstRTSPSessionStream * stream, GstRTSPSendFunc send_rtp, GstRTSPSendFunc send_rtcp, - GstRTSPSendListFunc send_rtp_list, GstRTSPSendListFunc send_rtcp_list, gpointer user_data, GDestroyNotify notify) { stream->trans.send_rtp = send_rtp; stream->trans.send_rtcp = send_rtcp; - stream->trans.send_rtp_list = send_rtp_list; - stream->trans.send_rtcp_list = send_rtcp_list; if (stream->trans.notify) stream->trans.notify (stream->trans.user_data); stream->trans.user_data = user_data; diff --git a/gst/rtsp-server/rtsp-session.h b/gst/rtsp-server/rtsp-session.h index 4289ecb..973f196 100644 --- a/gst/rtsp-server/rtsp-session.h +++ b/gst/rtsp-server/rtsp-session.h @@ -154,8 +154,6 @@ GstRTSPTransport * gst_rtsp_session_stream_set_transport (GstRTSPSessionStre void gst_rtsp_session_stream_set_callbacks (GstRTSPSessionStream *stream, GstRTSPSendFunc send_rtp, GstRTSPSendFunc send_rtcp, - GstRTSPSendListFunc send_rtp_list, - GstRTSPSendListFunc send_rtcp_list, gpointer user_data, GDestroyNotify notify); void gst_rtsp_session_stream_set_keepalive (GstRTSPSessionStream *stream, diff --git a/pkgconfig/Makefile.am b/pkgconfig/Makefile.am index 8d38e35..54f82ac 100644 --- a/pkgconfig/Makefile.am +++ b/pkgconfig/Makefile.am @@ -1,8 +1,8 @@ pcfiles = \ - gst-rtsp-server-@GST_MAJORMINOR@.pc + gstreamer-rtsp-server-@GST_MAJORMINOR@.pc pcfiles_uninstalled = \ - gst-rtsp-server-@GST_MAJORMINOR@-uninstalled.pc + gstreamer-rtsp-server-@GST_MAJORMINOR@-uninstalled.pc all-local: $(pcfiles) $(pcfiles_uninstalled) @@ -16,6 +16,6 @@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = $(pcfiles) EXTRA_DIST = \ - gst-rtsp-server.pc.in \ - gst-rtsp-server-uninstalled.pc.in + gstreamer-rtsp-server.pc.in \ + gstreamer-rtsp-server-uninstalled.pc.in CLEANFILES = $(pcfiles) $(pcfiles_uninstalled) diff --git a/pkgconfig/gst-rtsp-server-uninstalled.pc.in b/pkgconfig/gstreamer-rtsp-server-uninstalled.pc.in index cd591be..cd591be 100644 --- a/pkgconfig/gst-rtsp-server-uninstalled.pc.in +++ b/pkgconfig/gstreamer-rtsp-server-uninstalled.pc.in diff --git a/pkgconfig/gst-rtsp-server.pc.in b/pkgconfig/gstreamer-rtsp-server.pc.in index 52e33c5..52e33c5 100644 --- a/pkgconfig/gst-rtsp-server.pc.in +++ b/pkgconfig/gstreamer-rtsp-server.pc.in |