Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Position and signed enums #244

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 61 additions & 15 deletions generator/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@
processor, see U{http://code.activestate.com/recipes/546532}.

This module and the generated Python bindings have been tested with
32- and 64-bit Python 2.6, 2.7 and 3.6 on Linux, Windows XP SP3, MacOS
X 10.4.11 (Intel) and MacOS X 10.11.3 using the public API include
files from VLC 1.1.4.1, 1.1.5, 2.1.0, 2.2.2, 3.0.3.
32- and 64-bit Python 2.6, 2.7, 3.6 and 3.11 on Linux, Windows XP SP3,
MacOS X 10.4.11 (Intel), 10.11.3 (Intel) and macOS 13.0.1 (Apple Silicon)
using the public API include files from VLC 1.1.4.1, 1.1.5, 2.1.0, 2.2.2,
3.0.3 and 3.0.18.

B{**)} Java/JNA bindings for the VLC public API can be created in a
similar manner and depend on 3 Java files: C{boilerplate.java},
Expand All @@ -56,7 +57,7 @@

# Version number MUST have a major < 10 and a minor < 99 so that the
# generated dist version can be correctly generated.
__version__ = '1.20'
__version__ = '1.21'

_debug = False

Expand Down Expand Up @@ -614,12 +615,18 @@ def parse_callbacks(self):
yield Func(name, type_.replace(' ', ''), pars, docs,
file_=self.h_file, line=line)

FIXME_enums = {'libvlc_position_t': '''libvlc_position_disable=-1,
libvlc_position_center=0, libvlc_position_left, libvlc_position_right,
libvlc_position_top=4, libvlc_position_top_left, libvlc_position_top_right,
libvlc_position_bottom=8, libvlc_position_bottom_left, libvlc_position_bottom_right'''}

def parse_enums(self):
"""Parse header file for enum type definitions.

@return: yield an Enum instance for each enum.
"""
for typ, name, enum, docs, line in self.parse_groups(enum_type_re.match, enum_re.match):
enum = self.FIXME_enums.get(name, enum)
vals, locs, e = [], {}, -1 # enum value(s)
for t in paramlist_re.split(enum):
n = t.split('/*')[0].strip()
Expand Down Expand Up @@ -685,7 +692,6 @@ def match_t(t):
return _VLC_PUBLIC_API_ in t

for name, pars, docs, line in self.parse_groups(match_t, api_re.match, ');'):

f = Par.parse_param(name)
if f.name in _blacklist:
_blacklist[f.name] = f.type
Expand Down Expand Up @@ -851,12 +857,11 @@ def check_types(self):
def class4(self, type, flag=None):
"""Return the class name for a type or enum.
"""
cl = None
cl, out = None, ''
if flag == Flag.Out:
cl = self.type2class_out.get(type)
cl, out = self.type2class_out.get(type, None), 'OUT_'
if cl is None:
cl = self.type2class.get(type, 'FIXME_%s%s' % ('OUT_' if flag == Flag.Out else '',
type))
cl = self.type2class.get(type, '') or ('FIXME_%s%s' % (out, type))
return cl

def convert_classnames(self, element_list):
Expand All @@ -880,7 +885,7 @@ def convert_classnames(self, element_list):
elif c[0].islower():
c = c.capitalize()
self.type2class[e.name] = c
self.type2class[e.name+'*'] = f"ctypes.POINTER({c})"
self.type2class[e.name+'*'] = f"ctypes.POINTER({c})"
self.type2class[e.name+'**'] = f"ctypes.POINTER(ctypes.POINTER({c}))"

def dump_dicts(self): # for debug
Expand Down Expand Up @@ -1105,6 +1110,36 @@ class PythonGenerator(_Generator):
'RendererDiscoverer'
)

# C enums become an unsigned _Enum or a signed
# _Enim class in Python to avoid TypeError in
# libvlc_... function arguments of type c_int
enum2Enim = ( # signed C enum classes only
'libvlc_audio_output_channel_t',
'libvlc_audio_output_device_types_t',
# 'libvlc_dialog_question_type',
# 'libvlc_enum_t',
# 'libvlc_event_e',
'libvlc_log_level',
# 'libvlc_media_discoverer_category_t',
# 'libvlc_media_parse_flag_t',
# 'libvlc_media_parsed_status_t',
# 'libvlc_media_player_role',
# 'libvlc_media_slave_type_t',
# 'libvlc_media_type_t',
# 'libvlc_meta_t',
# 'libvlc_navigate_mode_t',
# 'libvlc_playback_mode_t',
'libvlc_position_t',
# 'libvlc_state_t',
# 'libvlc_teletext_key_t',
'libvlc_track_type_t',
# 'libvlc_video_adjust_option_t',
# 'libvlc_video_logo_option_t',
# 'libvlc_video_marquee_option_t',
# 'libvlc_video_orient_t',
# 'libvlc_video_projection_t'
)

def __init__(self, parser=None):
"""New instance.

Expand Down Expand Up @@ -1204,7 +1239,7 @@ def generate_enums(self):
"""Generate classes for all enum types.
"""
self.output("""
class _Enum(ctypes.c_uint):
class _EnumBase():
'''(INTERNAL) Base class
'''
_enum_names_ = {}
Expand All @@ -1220,19 +1255,30 @@ def __repr__(self):
return '.'.join((self.__class__.__module__, self.__str__()))

def __eq__(self, other):
return ( (isinstance(other, _Enum) and self.value == other.value)
or (isinstance(other, _Ints) and self.value == other) )
return ( (isinstance(other, (_Enum, _Enim)) and self.value == other.value)
or (isinstance(other, _Ints) and self.value == other) )

def __ne__(self, other):
return not self.__eq__(other)

class _Enum(_EnumBase, ctypes.c_uint):
'''(INTERNAL) Unsigned C enum.
'''
pass

class _Enim(_EnumBase, ctypes.c_int):
'''(INTERNAL) Signed C enum.
'''
pass
""")
for e in self.parser.enums:

cls = self.class4(e.name)
self.output("""class %s(_Enum):
u_i = 'i' if e.name in self.enum2Enim else 'u'
self.output("""class %s(_En%sm):
'''%s
'''
_enum_names_ = {""" % (cls, e.epydocs() or _NA_))
_enum_names_ = {""" % (cls, u_i, e.epydocs() or _NA_))

for v in e.vals:
self.output(" %s: '%s'," % (v.value, v.name))
Expand Down