"libvlc_exception_get_message",
"libvlc_get_vlc_instance",
- "libvlc_media_add_option_flag",
"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_option_as_int',
'libvlc_video_get_marquee_option_as_string',
'libvlc_vlm_get_event_manager',
'mediacontrol_PlaylistSeq__free',
-
- # TODO
- "libvlc_event_detach",
- "libvlc_event_attach",
]
# Precompiled regexps
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*\};')
# Definition of parameter passing mode for types. This should not be
# hardcoded this way, but works alright ATM.
'libvlc_log_t*': 'Log',
'libvlc_log_iterator_t*': 'LogIterator',
'libvlc_log_message_t*': 'LogMessage',
- 'libvlc_event_type_t': 'EventType',
+ 'libvlc_event_type_t': 'ctypes.c_uint',
'libvlc_event_manager_t*': 'EventManager',
'libvlc_media_discoverer_t*': 'MediaDiscoverer',
'libvlc_media_library_t*': 'MediaLibrary',
'unsigned': 'ctypes.c_uint',
'int': 'ctypes.c_int',
'...': 'FIXMEva_list',
- 'libvlc_callback_t': 'FIXMEcallback',
+ 'libvlc_callback_t': 'ctypes.c_void_p',
'libvlc_time_t': 'ctypes.c_longlong',
}
'Log',
'LogIterator',
#'LogMessage',
- 'EventType',
'EventManager',
'MediaDiscoverer',
'MediaLibrary',
'TrackDescription',
'AudioOutput',
'MediaControl',
- #'RGBPicture',
- #'MediaControlPosition',
- #'MediaControlStreamInformation',
)
# Definition of prefixes that we can strip from method names when
# K&R definition: only type
return s.replace(' ', ''), ''
-def generate_header(classes=None):
- """Generate header code.
+def insert_code(filename):
+ """Generate header/footer code.
"""
- f=open('header.py', 'r')
+ f=open(filename, 'r')
for l in f:
if 'build_date' in l:
print 'build_date="%s"' % time.ctime()
def convert_enum_names(enums):
res={}
- for (typ, name, values) in enums:
+ 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('_', '')
- else:
+ elif not pyname[0].isupper():
pyname=pyname.capitalize()
res[name]=pyname
return res
def generate_enums(enums):
- for (typ, name, values) in enums:
+ for (typ, name, values, comment) in enums:
if typ != 'enum':
raise Exception('This method only handles enums')
pyname=typ2class[name]
print "class %s(ctypes.c_uint):" % pyname
+ print ' """%s\n """' % comment
conv={}
# Convert symbol names
n=k.split('_')[-1]
if len(n) == 1:
# Single character. Some symbols use 1_1, 5_1, etc.
- n="_".join( k.split('_')[:-2] )
+ n="_".join( k.split('_')[-2:] )
if re.match('^[0-9]', n):
# Cannot start an identifier with a number
n='_'+n
"""Parse include file for typedef expressions.
This generates a tuple for each typedef:
- (type, name, value_list)
+ (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.
"""
continue
l=l.strip()
+ if l.startswith('/*') or l.endswith('*/'):
+ continue
- if accumulator:
+ 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=''
- elif l.startswith('typedef enum') and not l.endswith(';'):
- # Multiline definition. Accumulate until end of definition
- accumulator=l
- continue
m=enum_re.match(l)
if m:
else:
if l:
values.append( (l, str(i)) )
- yield (typ, name, values)
+ comment=comment.replace('@{', '').replace('@see', 'See').replace('\ingroup', '')
+ yield (typ, name.strip(), values, comment)
+ comment=''
+ continue
+
+ # Special case, used only for libvlc_events.h
+ m=special_enum_re.match(l)
+ if m:
+ values=[]
+ (typ, name, data)=m.groups()
+ 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(name):
"""Parse include file.
method,
params,
comment)
+ comment=''
def output_ctypes(rtype, method, params, comment):
"""Output ctypes decorator for the given method.
"""Parse override definitions file.
It is possible to override methods definitions in classes.
+
+ It returns a tuple
+ (code, overriden_methods, docstring)
"""
- res={}
+ code={}
data=[]
current=None
if m:
# Dump old data
if current is not None:
- res[current]="\n".join(data)
+ code[current]="".join(data)
current=m.group(1)
data=[]
continue
data.append(l)
- res[current]="\n".join(data)
+ code[current]="".join(data)
f.close()
- return res
+
+ 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(c):
"""Fix comment by removing first and last parameters (self and exception)
"""
- data=c.splitlines()
- body=itertools.takewhile(lambda l: not '@param' in l, data)
+ 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) ]
),
key=operator.itemgetter(0))
- overrides=parse_override('override.py')
+ overrides, overriden_methods, docstring=parse_override('override.py')
for classname, el in itertools.groupby(elements, key=operator.itemgetter(0)):
+ print """class %(name)s(object):""" % {'name': classname}
+ if classname in docstring:
+ print ' """%s\n """' % docstring[classname]
+
print """
-class %(name)s(object):
def __new__(cls, pointer=None):
'''Internal method used for instanciating wrappers from ctypes.
'''
# 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 )
print " def %s(%s):" % (name, args)
- print ' """%s\n"""' % fix_python_comment(comment)
+ print ' """%s\n """' % fix_python_comment(comment)
if params and params[-1][0] == 'libvlc_exception_t*':
# Exception handling
print " e=VLCException()"
else:
print " return %s(%s)" % (method, args)
print
+
+ # Check for standard methods
+ if name == 'count':
+ # There is a count method. Generate a __len__ one.
+ print " def __len__(self):"
+ print " e=VLCException()"
+ print " return %s(self, e)" % method
+ print
+ elif name.endswith('item_at_index'):
+ # Indexable (and thus iterable)"
+ print " def __getitem__(self, i):"
+ print " e=VLCException()"
+ print " return %s(self, i, e)" % method
+ print
+ print " def __iter__(self):"
+ print " e=VLCException()"
+ print " for i in xrange(len(self)):"
+ print " yield self[i]"
+ print
+
return ret
if __name__ == '__main__':
if debug:
sys.exit(0)
- generate_header()
+ insert_code('header.py')
generate_enums(enums)
wrapped=generate_wrappers(methods)
for l in methods:
output_ctypes(*l)
+ insert_code('footer.py')
all=set( t[1] for t in methods )
not_wrapped=all.difference(wrapped)