]> git.sesse.net Git - vlc/blobdiff - bindings/python-ctypes/generate.py
bindings: remove java, phonon and python-ctypes. They moved to a dedicated git.
[vlc] / bindings / python-ctypes / generate.py
diff --git a/bindings/python-ctypes/generate.py b/bindings/python-ctypes/generate.py
deleted file mode 100755 (executable)
index 1564323..0000000
+++ /dev/null
@@ -1,935 +0,0 @@
-#! /usr/bin/python
-debug=False
-
-#
-# Code generator for python ctypes bindings for VLC
-# Copyright (C) 2009 the VideoLAN team
-# $Id: $
-#
-# Authors: Olivier Aubert <olivier.aubert at liris.cnrs.fr>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program 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 General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
-#
-
-"""This module parses VLC public API include files and generates
-corresponding python/ctypes code. Moreover, it generates class
-wrappers for most methods.
-"""
-
-import sys
-import os
-import re
-import time
-import operator
-import itertools
-from optparse import OptionParser
-
-# DefaultDict from ASPN python cookbook
-import copy
-class DefaultDict(dict):
-    """Dictionary with a default value for unknown keys."""
-    def __init__(self, default=None, **items):
-        dict.__init__(self, **items)
-        self.default = default
-
-    def __getitem__(self, key):
-        if key in self:
-            return self.get(key)
-        else:
-            ## Need copy in case self.default is something like []
-            return self.setdefault(key, copy.deepcopy(self.default))
-
-    def __copy__(self):
-        return DefaultDict(self.default, **self)
-
-# Methods not decorated/not referenced
-blacklist=[
-    "libvlc_exception_raise",
-    "libvlc_exception_raised",
-    "libvlc_exception_get_message",
-    "libvlc_get_vlc_instance",
-
-    "libvlc_media_list_view_index_of_item",
-    "libvlc_media_list_view_insert_at_index",
-    "libvlc_media_list_view_remove_at_index",
-    "libvlc_media_list_view_add_item",
-
-    # In svn but not in current 1.0.0.
-    #"libvlc_media_add_option_flag",
-    #'libvlc_video_set_deinterlace',
-    #'libvlc_video_get_marquee_int',
-    #'libvlc_video_get_marquee_string',
-    #'libvlc_video_set_marquee_int',
-    #'libvlc_video_set_marquee_string',
-    #'libvlc_vlm_get_event_manager',
-    #"libvlc_media_list_player_event_manager",
-    #'libvlc_media_player_next_frame',
-
-    'mediacontrol_PlaylistSeq__free',
-    ]
-
-# Precompiled regexps
-api_re=re.compile('VLC_PUBLIC_API\s+(\S+\s+.+?)\s*\(\s*(.+?)\s*\)')
-param_re=re.compile('\s*(const\s*|unsigned\s*|struct\s*)?(\S+\s*\**)\s+(.+)')
-paramlist_re=re.compile('\s*,\s*')
-comment_re=re.compile('\\param\s+(\S+)')
-python_param_re=re.compile('(@param\s+\S+)(.+)')
-forward_re=re.compile('.+\(\s*(.+?)\s*\)(\s*\S+)')
-enum_re=re.compile('typedef\s+(enum)\s*(\S+\s*)?\{\s*(.+)\s*\}\s*(\S+);')
-special_enum_re=re.compile('^(enum)\s*(\S+\s*)?\{\s*(.+)\s*\};')
-event_def_re=re.compile('^DEF\(\s*(\w+)\s*\)')
-
-# Definition of parameter passing mode for types.  This should not be
-# hardcoded this way, but works alright ATM.
-parameter_passing=DefaultDict(default=1)
-parameter_passing['libvlc_exception_t*']=3
-
-class Parser(object):
-    def __init__(self, list_of_files):
-        self.methods=[]
-        self.enums=[]
-
-        for name in list_of_files:
-            self.enums.extend(self.parse_typedef(name))
-            self.methods.extend(self.parse_include(name))
-
-    def parse_param(self, s):
-        """Parse a C parameter expression.
-
-        It is used to parse both the type/name for methods, and type/name
-        for their parameters.
-
-        It returns a tuple (type, name).
-        """
-        s=s.strip()
-        s=s.replace('const', '')
-        if 'VLC_FORWARD' in s:
-            m=forward_re.match(s)
-            s=m.group(1)+m.group(2)
-        m=param_re.search(s)
-        if m:
-            const, typ, name=m.groups()
-            while name.startswith('*'):
-                typ += '*'
-                name=name[1:]
-            if name == 'const*':
-                # K&R definition: const char * const*
-                name=''
-            typ=typ.replace(' ', '')
-            return typ, name
-        else:
-            # K&R definition: only type
-            return s.replace(' ', ''), ''
-
-    def parse_typedef(self, name):
-        """Parse include file for typedef expressions.
-
-        This generates a tuple for each typedef:
-        (type, name, value_list, comment)
-        with type == 'enum' (for the moment) and value_list being a list of (name, value)
-        Note that values are string, since this is intended for code generation.
-        """
-        event_names=[]
-
-        f=open(name, 'r')
-        accumulator=''
-        for l in f:
-            # Note: lstrip() should not be necessary, but there is 1 badly
-            # formatted comment in vlc1.0.0 includes
-            if l.lstrip().startswith('/**'):
-                comment=''
-                continue
-            elif l.startswith(' * '):
-                comment = comment + l[3:]
-                continue
-
-            l=l.strip()
-            if l.startswith('/*') or l.endswith('*/'):
-                continue
-
-            if (l.startswith('typedef enum') or l.startswith('enum')) and not l.endswith(';'):
-                # Multiline definition. Accumulate until end of definition
-                accumulator=l
-                continue
-            elif accumulator:
-                accumulator=" ".join( (accumulator, l) )
-                if l.endswith(';'):
-                    # End of definition
-                    l=accumulator
-                    accumulator=''
-
-            m=enum_re.match(l)
-            if m:
-                values=[]
-                (typ, dummy, data, name)=m.groups()
-                for i, l in enumerate(paramlist_re.split(data)):
-                    l=l.strip()
-                    if l.startswith('/*'):
-                        continue
-                    if '=' in l:
-                        # A value was specified. Use it.
-                        values.append(re.split('\s*=\s*', l))
-                    else:
-                        if l:
-                            values.append( (l, str(i)) )
-                comment=comment.replace('@{', '').replace('@see', 'See').replace('\ingroup', '')
-                yield (typ, name.strip(), values, comment)
-                comment=''
-                continue
-
-            # Special case, used only for libvlc_events.h
-            # (version after 96a96f60bb0d1f2506e68b356897ceca6f6b586d)
-            m=event_def_re.match(l)
-            if m:
-                # Event definition.
-                event_names.append('libvlc_'+m.group(1))
-                continue
-
-            # Special case, used only for libvlc_events.h
-            m=special_enum_re.match(l)
-            if m:
-                (typ, name, data)=m.groups()
-                if event_names:
-                    # event_names were defined through DEF macro
-                    # (see 96a96f60bb0d1f2506e68b356897ceca6f6b586d)
-                    values=list( (n, str(i)) for i, n in enumerate(event_names))
-                else:
-                    # Before 96a96f60bb0d1f2506e68b356897ceca6f6b586d
-                    values=[]
-                    for i, l in enumerate(paramlist_re.split(data)):
-                        l=l.strip()
-                        if l.startswith('/*') or l.startswith('#'):
-                            continue
-                        if '=' in l:
-                            # A value was specified. Use it.
-                            values.append(re.split('\s*=\s*', l))
-                        else:
-                            if l:
-                                values.append( (l, str(i)) )
-                comment=comment.replace('@{', '').replace('@see', 'See').replace('\ingroup', '')
-                yield (typ, name.strip(), values, comment)
-                comment=''
-                continue
-
-    def parse_include(self, name):
-        """Parse include file.
-
-        This generates a tuple for each function:
-        (return_type, method_name, parameter_list, comment)
-        with parameter_list being a list of tuples (parameter_type, parameter_name).
-        """
-        f=open(name, 'r')
-        accumulator=''
-        comment=''
-        for l in f:
-            # Note: lstrip() should not be necessary, but there is 1 badly
-            # formatted comment in vlc1.0.0 includes
-            if l.lstrip().startswith('/**'):
-                comment=''
-                continue
-            elif l.startswith(' * '):
-                comment = comment + l[3:]
-                continue
-
-            l=l.strip()
-
-            if accumulator:
-                accumulator=" ".join( (accumulator, l) )
-                if l.endswith(');'):
-                    # End of definition
-                    l=accumulator
-                    accumulator=''
-            elif l.startswith('VLC_PUBLIC_API') and not l.endswith(');'):
-                # Multiline definition. Accumulate until end of definition
-                accumulator=l
-                continue
-
-            m=api_re.match(l)
-            if m:
-                (ret, param)=m.groups()
-
-                rtype, method=self.parse_param(ret)
-
-                params=[]
-                for p in paramlist_re.split(param):
-                    params.append( self.parse_param(p) )
-
-                if len(params) == 1 and params[0][0] == 'void':
-                    # Empty parameter list
-                    params=[]
-
-                if list(p for p in params if not p[1]):
-                    # Empty parameter names. Have to poke into comment.
-                    names=comment_re.findall(comment)
-                    if len(names) < len(params):
-                        # Bad description: all parameters are not specified.
-                        # Generate default parameter names
-                        badnames=[ "param%d" % i for i in xrange(len(params)) ]
-                        # Put in the existing ones
-                        for (i, p) in enumerate(names):
-                            badnames[i]=names[i]
-                        names=badnames
-                        print "### Error ###"
-                        print "### Cannot get parameter names from comment for %s: %s" % (method, comment.replace("\n", ' '))
-                        # Note: this was previously
-                        # raise Exception("Cannot get parameter names from comment for %s: %s" % (method, comment))
-                        # but it prevented code generation for a minor detail (some bad descriptions).
-                    params=[ (p[0], names[i]) for (i, p) in enumerate(params) ]
-
-                # Transform Doxygen syntax into epydoc syntax
-                comment=comment.replace('\\param', '@param').replace('\\return', '@return')
-
-                if debug:
-                    print '********************'
-                    print l
-                    print '-------->'
-                    print "%s (%s)" % (method, rtype)
-                    for typ, name in params:
-                        print "        %s (%s)" % (name, typ)
-                    print '********************'
-                yield (rtype,
-                       method,
-                       params,
-                       comment)
-                comment=''
-
-    def dump_methods(self):
-        print "** Defined functions **"
-        for (rtype, name, params, comment) in self.methods:
-            print "%(name)s (%(rtype)s):" % locals()
-            for t, n in params:
-                print "    %(n)s (%(t)s)" % locals()
-
-    def dump_enums(self):
-        print "** Defined enums **"
-        for (typ, name, values, comment) in self.enums:
-            print "%(name)s (%(typ)s):" % locals()
-            for k, v in values:
-                print "    %(k)s=%(v)s" % locals()
-
-class PythonGenerator(object):
-    # C-type to ctypes/python type conversion.
-    # Note that enum types conversions are generated (cf convert_enum_names)
-    type2class={
-        'libvlc_exception_t*': 'ctypes.POINTER(VLCException)',
-
-        'libvlc_media_player_t*': 'MediaPlayer',
-        'libvlc_instance_t*': 'Instance',
-        'libvlc_media_t*': 'Media',
-        'libvlc_log_t*': 'Log',
-        'libvlc_log_iterator_t*': 'LogIterator',
-        'libvlc_log_message_t*': 'ctypes.POINTER(LogMessage)',
-        'libvlc_event_type_t': 'ctypes.c_uint',
-        'libvlc_event_manager_t*': 'EventManager',
-        'libvlc_media_discoverer_t*': 'MediaDiscoverer',
-        'libvlc_media_library_t*': 'MediaLibrary',
-        'libvlc_media_list_t*': 'MediaList',
-        'libvlc_media_list_player_t*': 'MediaListPlayer',
-        'libvlc_media_list_view_t*': 'MediaListView',
-        'libvlc_track_description_t*': 'TrackDescription',
-        'libvlc_audio_output_t*': 'AudioOutput',
-        'libvlc_media_stats_t*': 'ctypes.POINTER(MediaStats)',
-        'libvlc_media_es_t**': 'ctypes.POINTER(ctypes.POINTER(MediaES))',
-
-        'mediacontrol_Instance*': 'MediaControl',
-        'mediacontrol_Exception*': 'MediaControlException',
-        'mediacontrol_RGBPicture*': 'ctypes.POINTER(RGBPicture)',
-        'mediacontrol_PlaylistSeq*': 'MediaControlPlaylistSeq',
-        'mediacontrol_Position*': 'ctypes.POINTER(MediaControlPosition)',
-        'mediacontrol_StreamInformation*': 'ctypes.POINTER(MediaControlStreamInformation)',
-        'WINDOWHANDLE': 'ctypes.c_ulong',
-
-        'void': 'None',
-        'void*': 'ctypes.c_void_p',
-        'short': 'ctypes.c_short',
-        'char*': 'ctypes.c_char_p',
-        'char**': 'ListPOINTER(ctypes.c_char_p)',
-        'uint32_t': 'ctypes.c_uint',
-        'float': 'ctypes.c_float',
-        'unsigned': 'ctypes.c_uint',
-        'int': 'ctypes.c_int',
-        '...': 'FIXMEva_list',
-        'libvlc_callback_t': 'ctypes.c_void_p',
-        'libvlc_time_t': 'ctypes.c_longlong',
-        }
-
-    # Defined python classes, i.e. classes for which we want to generate
-    # class wrappers around libvlc functions
-    defined_classes=(
-        'MediaPlayer',
-        'Instance',
-        'Media',
-        'Log',
-        'LogIterator',
-        'EventManager',
-        'MediaDiscoverer',
-        'MediaLibrary',
-        'MediaList',
-        'MediaListPlayer',
-        'MediaListView',
-        'TrackDescription',
-        'AudioOutput',
-        'MediaControl',
-        )
-
-    def __init__(self, parser=None):
-        self.parser=parser
-
-        # Generate python names for enums
-        self.type2class.update(self.convert_enum_names(parser.enums))
-        self.check_types()
-
-        # Definition of prefixes that we can strip from method names when
-        # wrapping them into class methods
-        self.prefixes=dict( (v, k[:-2])
-                            for (k, v) in self.type2class.iteritems()
-                            if  v in self.defined_classes )
-        self.prefixes['MediaControl']='mediacontrol_'
-
-    def save(self, filename=None):
-        if filename is None or filename == '-':
-            self.fd=sys.stdout
-        else:
-            self.fd=open(filename, 'w')
-
-        self.insert_code('header.py')
-        wrapped_methods=self.generate_wrappers(self.parser.methods)
-        for l in self.parser.methods:
-            self.output_ctypes(*l)
-        self.insert_code('footer.py')
-
-        all_methods=set( t[1] for t in self.parser.methods )
-        not_wrapped=all_methods.difference(wrapped_methods)
-        self.output("# Not wrapped methods:")
-        for m in not_wrapped:
-            self.output("#   ", m)
-
-        if self.fd != sys.stdout:
-            self.fd.close()
-
-    def output(self, *p):
-        self.fd.write(" ".join(p))
-        self.fd.write("\n")
-
-    def check_types(self):
-        """Make sure that all types are properly translated.
-
-        This method must be called *after* convert_enum_names, since
-        the latter populates type2class with converted enum names.
-        """
-        for (rt, met, params, c) in self.parser.methods:
-            for typ, name in params:
-                if not typ in self.type2class:
-                    raise Exception("No conversion for %s (from %s:%s)" % (typ, met, name))
-
-    def insert_code(self, filename):
-        """Generate header/footer code.
-        """
-        f=open(filename, 'r')
-        for l in f:
-            if l.startswith('build_date'):
-                self.output('build_date="%s"' % time.ctime())
-            elif l.startswith('# GENERATED_ENUMS'):
-                self.generate_enums(self.parser.enums)
-            else:
-                self.output(l.rstrip())
-
-        f.close()
-
-    def convert_enum_names(self, enums):
-        res={}
-        for (typ, name, values, comment) in enums:
-            if typ != 'enum':
-                raise Exception('This method only handles enums')
-            pyname=re.findall('(libvlc|mediacontrol)_(.+?)(_t)?$', name)[0][1]
-            if '_' in pyname:
-                pyname=pyname.title().replace('_', '')
-            elif not pyname[0].isupper():
-                pyname=pyname.capitalize()
-            res[name]=pyname
-        return res
-
-    def generate_enums(self, enums):
-        for (typ, name, values, comment) in enums:
-            if typ != 'enum':
-                raise Exception('This method only handles enums')
-            pyname=self.type2class[name]
-
-            self.output("class %s(ctypes.c_ulong):" % pyname)
-            self.output('    """%s\n    """' % comment)
-
-            conv={}
-            # Convert symbol names
-            for k, v in values:
-                n=k.split('_')[-1]
-                if len(n) == 1:
-                    # Single character. Some symbols use 1_1, 5_1, etc.
-                    n="_".join( k.split('_')[-2:] )
-                if re.match('^[0-9]', n):
-                    # Cannot start an identifier with a number
-                    n='_'+n
-                conv[k]=n
-
-            self.output("    _names={")
-            for k, v in values:
-                self.output("        %s: '%s'," % (v, conv[k]))
-            self.output("    }")
-
-            self.output("""
-    def __repr__(self):
-        return ".".join((self.__class__.__module__, self.__class__.__name__, self._names[self.value]))
-
-    def __eq__(self, other):
-        return ( (isinstance(other, ctypes.c_ulong) and self.value == other.value)
-                 or (isinstance(other, (int, long)) and self.value == other ) )
-
-    def __ne__(self, other):
-        return not self.__eq__(other)
-    """)
-            for k, v in values:
-                self.output("%(class)s.%(attribute)s=%(class)s(%(value)s)" % {
-                        'class': pyname,
-                        'attribute': conv[k],
-                        'value': v
-                        })
-            self.output("")
-
-    def output_ctypes(self, rtype, method, params, comment):
-        """Output ctypes decorator for the given method.
-        """
-        if method in blacklist:
-            # FIXME
-            return
-
-        self.output("""if hasattr(dll, '%s'):""" % method)
-        if params:
-            self.output("    prototype=ctypes.CFUNCTYPE(%s, %s)" % (self.type2class.get(rtype, 'FIXME_%s' % rtype),
-                                                                ", ".join( self.type2class[p[0]] for p in params )))
-        else:
-            self.output("    prototype=ctypes.CFUNCTYPE(%s)" % self.type2class.get(rtype, 'FIXME_%s' % rtype))
-
-
-        if not params:
-            flags='    paramflags= tuple()'
-        elif len(params) == 1:
-            flags="    paramflags=( (%d, ), )" % parameter_passing[params[0][0]]
-        else:
-            flags="    paramflags=%s" % ", ".join( '(%d,)' % parameter_passing[p[0]] for p in params )
-        self.output(flags)
-        self.output('    %s = prototype( ("%s", dll), paramflags )' % (method, method))
-        if '3' in flags:
-            # A VLCException is present. Process it.
-            self.output("    %s.errcheck = check_vlc_exception" % method)
-        self.output('    %s.__doc__ = """%s"""' % (method, comment))
-        self.output()
-
-    def parse_override(self, name):
-        """Parse override definitions file.
-
-        It is possible to override methods definitions in classes.
-
-        It returns a tuple
-        (code, overriden_methods, docstring)
-        """
-        code={}
-
-        data=[]
-        current=None
-        f=open(name, 'r')
-        for l in f:
-            m=re.match('class (\S+):', l)
-            if m:
-                # Dump old data
-                if current is not None:
-                    code[current]="".join(data)
-                current=m.group(1)
-                data=[]
-                continue
-            data.append(l)
-        code[current]="".join(data)
-        f.close()
-
-        docstring={}
-        for k, v in code.iteritems():
-            if v.lstrip().startswith('"""'):
-                # Starting comment. Use it as docstring.
-                dummy, docstring[k], code[k]=v.split('"""', 2)
-
-        # Not robust wrt. internal methods, but this works for the moment.
-        overridden_methods=dict( (k, re.findall('^\s+def\s+(\w+)', v, re.MULTILINE)) for (k, v) in code.iteritems() )
-
-        return code, overridden_methods, docstring
-
-    def fix_python_comment(self, c):
-        """Fix comment by removing first and last parameters (self and exception)
-        """
-        data=c.replace('@{', '').replace('@see', 'See').splitlines()
-        body=itertools.takewhile(lambda l: not '@param' in l and not '@return' in l, data)
-        param=[ python_param_re.sub('\\1:\\2', l) for l in  itertools.ifilter(lambda l: '@param' in l, data) ]
-        ret=[ l.replace('@return', '@return:') for l in itertools.ifilter(lambda l: '@return' in l, data) ]
-
-        if len(param) >= 2:
-            param=param[1:-1]
-        elif len(param) == 1:
-            param=[]
-
-        return "\n".join(itertools.chain(body, param, ret))
-
-    def generate_wrappers(self, methods):
-        """Generate class wrappers for all appropriate methods.
-
-        @return: the set of wrapped method names
-        """
-        ret=set()
-        # Sort methods against the element they apply to.
-        elements=sorted( ( (self.type2class.get(params[0][0]), rt, met, params, c)
-                           for (rt, met, params, c) in methods
-                           if params and self.type2class.get(params[0][0], '_') in self.defined_classes
-                           ),
-                         key=operator.itemgetter(0))
-
-        overrides, overriden_methods, docstring=self.parse_override('override.py')
-
-        for classname, el in itertools.groupby(elements, key=operator.itemgetter(0)):
-            self.output("""class %(name)s(object):""" % {'name': classname})
-            if classname in docstring:
-                self.output('    """%s\n    """' % docstring[classname])
-
-            if not 'def __new__' in overrides.get(classname, ''):
-                self.output("""
-    def __new__(cls, pointer=None):
-        '''Internal method used for instanciating wrappers from ctypes.
-        '''
-        if pointer is None:
-            raise Exception("Internal method. Surely this class cannot be instanciated by itself.")
-        if pointer == 0:
-            return None
-        else:
-            o=object.__new__(cls)
-            o._as_parameter_=ctypes.c_void_p(pointer)
-            return o
-""")
-
-            self.output("""
-    @staticmethod
-    def from_param(arg):
-        '''(INTERNAL) ctypes parameter conversion method.
-        '''
-        return arg._as_parameter_
-""")
-
-            if classname in overrides:
-                self.output(overrides[classname])
-
-            prefix=self.prefixes.get(classname, '')
-
-            for cl, rtype, method, params, comment in el:
-                if method in blacklist:
-                    continue
-                # Strip prefix
-                name=method.replace(prefix, '').replace('libvlc_', '')
-                ret.add(method)
-                if name in overriden_methods.get(cl, []):
-                    # Method already defined in override.py
-                    continue
-
-                if params:
-                    params[0]=(params[0][0], 'self')
-                if params and params[-1][0] in ('libvlc_exception_t*', 'mediacontrol_Exception*'):
-                    args=", ".join( p[1] for p in params[:-1] )
-                else:
-                    args=", ".join( p[1] for p in params )
-
-                self.output("    if hasattr(dll, '%s'):" % method)
-                self.output("        def %s(%s):" % (name, args))
-                self.output('            """%s\n        """' % self.fix_python_comment(comment))
-                if params and params[-1][0] == 'libvlc_exception_t*':
-                    # Exception handling
-                    self.output("            e=VLCException()")
-                    self.output("            return %s(%s, e)" % (method, args))
-                elif params and params[-1][0] == 'mediacontrol_Exception*':
-                    # Exception handling
-                    self.output("            e=MediaControlException()")
-                    self.output("            return %s(%s, e)" % (method, args))
-                else:
-                    self.output("            return %s(%s)" % (method, args))
-                self.output()
-
-                # Check for standard methods
-                if name == 'count':
-                    # There is a count method. Generate a __len__ one.
-                    if params and params[-1][0] == 'libvlc_exception_t*':
-                        self.output("""    def __len__(self):
-        e=VLCException()
-        return %s(self, e)
-""" % method)
-                    else:
-                        # No exception
-                        self.output("""    def __len__(self):
-        return %s(self)
-""" % method)
-                elif name.endswith('item_at_index'):
-                    # Indexable (and thus iterable)"
-                    self.output("""    def __getitem__(self, i):
-        e=VLCException()
-        return %s(self, i, e)
-
-    def __iter__(self):
-        e=VLCException()
-        for i in xrange(len(self)):
-            yield self[i]
-""" % method)
-        return ret
-
-class JavaGenerator(object):
-    # C-type to java/jna type conversion.
-    # Note that enum types conversions are generated (cf convert_enum_names)
-    type2class={
-        'libvlc_exception_t*': 'libvlc_exception_t',
-        'libvlc_media_player_t*': 'LibVlcMediaPlayer',
-        'libvlc_instance_t*': 'LibVlcInstance',
-        'libvlc_media_t*': 'LibVlcMedia',
-        'libvlc_log_t*': 'LibVlcLog',
-        'libvlc_log_iterator_t*': 'LibVlcLogIterator',
-        'libvlc_log_message_t*': 'libvlc_log_message_t',
-        'libvlc_event_type_t': 'int',
-        'libvlc_event_manager_t*': 'LibVlcEventManager',
-        'libvlc_media_discoverer_t*': 'LibVlcMediaDiscoverer',
-        'libvlc_media_library_t*': 'LibVlcMediaLibrary',
-        'libvlc_media_list_t*': 'LibVlcMediaList',
-        'libvlc_media_list_player_t*': 'LibVlcMediaListPlayer',
-        'libvlc_media_list_view_t*': 'LibVlcMediaListView',
-        'libvlc_media_stats_t*': 'LibVlcMediaStats',
-
-        'libvlc_track_description_t*': 'LibVlcTrackDescription',
-        'libvlc_audio_output_t*': 'LibVlcAudioOutput',
-
-        'void': 'void',
-        'void*': 'Pointer',
-        'short': 'short',
-        'char*': 'String',
-        'char**': 'String[]',
-        'uint32_t': 'uint32',
-        'float': 'float',
-        'unsigned': 'int',
-        'int': 'int',
-        '...': 'FIXMEva_list',
-        'libvlc_callback_t': 'LibVlcCallback',
-        'libvlc_time_t': 'long',
-
-        'mediacontrol_RGBPicture*': 'Pointer',
-        'mediacontrol_PlaylistSeq*': 'Pointer',
-        'mediacontrol_StreamInformation*': 'Pointer',
-        }
-
-    def __init__(self, parser=None):
-        self.parser=parser
-
-        # Blacklist all mediacontrol methods
-        for (rt, met, params, c) in self.parser.methods:
-            if met.startswith('mediacontrol'):
-                blacklist.append(met)
-        # Generate Java names for enums
-        self.type2class.update(self.convert_enum_names(parser.enums))
-        self.check_types()
-
-    def save(self, dirname=None):
-        if dirname is None or dirname == '-':
-            dirname='internal'
-            if not os.path.isdir(dirname):
-                os.mkdir(dirname)
-
-        print "Generating java code in %s/" % dirname
-
-        # Generate enum files
-        self.generate_enums(dirname, self.parser.enums)
-
-        # Generate LibVlc.java code
-        self.generate_libvlc(dirname)
-
-    def output(self, fd, *p):
-        fd.write(" ".join(p))
-        fd.write("\n")
-
-    def check_types(self):
-        """Make sure that all types are properly translated.
-
-        This method must be called *after* convert_enum_names, since
-        the latter populates type2class with converted enum names.
-        """
-        for (rt, met, params, c) in self.parser.methods:
-            if met in blacklist:
-                continue
-            for typ, name in params:
-                if not typ in self.type2class:
-                    raise Exception("No conversion for %s (from %s:%s)" % (typ, met, name))
-
-    def convert_enum_names(self, enums):
-        """Convert enum names into Java names.
-        """
-        res={}
-        for (typ, name, values, comment) in enums:
-            if typ != 'enum':
-                raise Exception('This method only handles enums')
-            pyname=re.findall('(libvlc|mediacontrol)_(.+?)(_t)?$', name)[0][1]
-            if '_' in pyname:
-                pyname=pyname.title().replace('_', '')
-            elif not pyname[0].isupper():
-                pyname=pyname.capitalize()
-            res[name]=pyname
-        return res
-
-    def insert_code(self, fd, filename):
-        """Generate header/footer code.
-        """
-        f=open(filename, 'r')
-        for l in f:
-            if l.startswith('build_date'):
-                self.output(fd, 'build_date="%s";' % time.ctime())
-            else:
-                self.output(fd, l.rstrip())
-        f.close()
-
-    def generate_header(self, fd):
-        """Generate LibVlc header.
-        """
-        for (c_type, jna_type) in self.type2class.iteritems():
-            if c_type.endswith('*') and jna_type.startswith('LibVlc'):
-                self.output(fd, '''    public class %s extends PointerType
-    {
-    }
-''' % jna_type)
-
-    def generate_libvlc(self, dirname):
-        """Generate LibVlc.java JNA glue code.
-        """
-        filename=os.path.join(dirname, 'LibVlc.java')
-        fd=open(filename, 'w')
-
-        self.insert_code(fd, 'boilerplate.java')
-        self.insert_code(fd, 'LibVlc-header.java')
-        #wrapped_methods=self.generate_wrappers(self.parser.methods)
-        self.generate_header(fd)
-        for (rtype, method, params, comment) in self.parser.methods:
-            if method in blacklist:
-                # FIXME
-                continue
-            self.output(fd, "%s %s(%s);\n" % (self.type2class.get(rtype, 'FIXME_%s' % rtype),
-                                          method,
-                                          ", ".join( ("%s %s" % (self.type2class[p[0]],
-                                                                 p[1])) for p in params )))
-        self.insert_code(fd, 'LibVlc-footer.java')
-        fd.close()
-
-    def generate_enums(self, dirname, enums):
-        """Generate JNA glue code for enums
-        """
-        for (typ, name, values, comment) in enums:
-            if typ != 'enum':
-                raise Exception('This method only handles enums')
-            javaname=self.type2class[name]
-
-            filename=javaname+".java"
-
-            fd=open(os.path.join(dirname, filename), 'w')
-
-            self.insert_code(fd, 'boilerplate.java')
-            self.output(fd, """package org.videolan.jvlc.internal;
-
-
-public enum %s
-{
-""" % javaname)
-            # FIXME: write comment
-
-            for k, v in values:
-                self.output(fd, "        %s (%s)," % (k, v))
-            self.output(fd, "");
-            self.output(fd, "        private final int _value;");
-            self.output(fd, "        %s(int value) { this._value = value; }" % javaname);
-            self.output(fd, "        public int value() { return this._value; }");
-            self.output(fd, "}")
-            fd.close()
-
-    def fix_python_comment(self, c):
-        """Fix comment by removing first and last parameters (self and exception)
-        """
-        data=c.replace('@{', '').replace('@see', 'See').splitlines()
-        body=itertools.takewhile(lambda l: not '@param' in l and not '@return' in l, data)
-        param=[ python_param_re.sub('\\1:\\2', l) for l in  itertools.ifilter(lambda l: '@param' in l, data) ]
-        ret=[ l.replace('@return', '@return:') for l in itertools.ifilter(lambda l: '@return' in l, data) ]
-
-        if len(param) >= 2:
-            param=param[1:-1]
-        elif len(param) == 1:
-            param=[]
-
-        return "\n".join(itertools.chain(body, param, ret))
-
-def process(output, list_of_includes):
-    p=Parser(list_of_includes)
-    g=PythonGenerator(p)
-    g.save(output)
-
-if __name__ == '__main__':
-    opt=OptionParser(usage="""Parse VLC include files and generate bindings code.
-%prog [options] include_file.h [...]""")
-
-    opt.add_option("-d", "--debug", dest="debug", action="store_true",
-                      default=False,
-                      help="Debug mode")
-
-    opt.add_option("-c", "--check", dest="check", action="store_true",
-                      default=False,
-                      help="Check mode")
-
-    opt.add_option("-j", "--java", dest="java", action="store_true",
-                      default=False,
-                      help="Generate java bindings (default is python)")
-
-    opt.add_option("-o", "--output", dest="output", action="store",
-                      type="str", default="-",
-                      help="Output filename(python)/dirname(java)")
-
-    (options, args) = opt.parse_args()
-
-    if not args:
-        opt.print_help()
-        sys.exit(1)
-
-    p=Parser(args)
-    if options.check:
-        # Various consistency checks.
-        for (rt, name, params, comment) in p.methods:
-            if not comment.strip():
-                print "No comment for %s" % name
-                continue
-            names=comment_re.findall(comment)
-            if len(names) != len(params):
-                print "Docstring comment parameters mismatch for %s" % name
-
-    if options.debug:
-        p.dump_methods()
-        p.dump_enums()
-
-    if options.check or options.debug:
-        sys.exit(0)
-
-    if options.java:
-        g=JavaGenerator(p)
-    else:
-        g=PythonGenerator(p)
-
-    g.save(options.output)