]> git.sesse.net Git - vlc/blobdiff - bindings/python-ctypes/header.py
python-ctypes: improve enum conversion
[vlc] / bindings / python-ctypes / header.py
index 840bb331e4cd9a6d86a6bf4e1a6ba05c3aa0f2c2..cc951192fa3eb2e55c6c27ce9c77b1f13e32612c 100755 (executable)
@@ -33,6 +33,7 @@ create a libvlc Instance. From this instance, you can then create
 L{MediaPlayer} and L{MediaListPlayer} instances.
 """
 
+import logging
 import ctypes
 import sys
 
@@ -41,11 +42,50 @@ build_date="This will be replaced by the build date"
 if sys.platform == 'linux2':
     dll=ctypes.CDLL('libvlc.so')
 elif sys.platform == 'win32':
-    dll=ctypes.CDLL('libvlc.dll')
+    import ctypes.util
+    import os
+    plugin_path=None
+    path=ctypes.util.find_library('libvlc.dll')
+    if path is None:
+        # Try to use registry settings
+        import _winreg
+        plugin_path_found = None
+        subkey, name = 'Software\\VideoLAN\\VLC','InstallDir'
+        for hkey in _winreg.HKEY_LOCAL_MACHINE, _winreg.HKEY_CURRENT_USER:
+            try:
+                reg = _winreg.OpenKey(hkey, subkey)
+                plugin_path_found, type_id = _winreg.QueryValueEx(reg, name)
+                _winreg.CloseKey(reg)
+                break
+            except _winreg.error:
+                pass
+        if plugin_path_found:
+            plugin_path = plugin_path_found
+        else:
+            # Try a standard location.
+            p='c:\\Program Files\\VideoLAN\\VLC\\libvlc.dll'
+            if os.path.exists(p):
+                plugin_path=os.path.dirname(p)
+        os.chdir(plugin_path)
+        # If chdir failed, this will not work and raise an exception
+        path='libvlc.dll'
+    else:
+        plugin_path=os.path.dirname(path)
+    dll=ctypes.CDLL(path)
 elif sys.platform == 'darwin':
     # FIXME: should find a means to configure path
     dll=ctypes.CDLL('/Applications/VLC.app/Contents/MacOS/lib/libvlc.2.dylib')
 
+#
+# Generated enum types.
+#
+
+# GENERATED_ENUMS
+
+#
+# End of generated enum types.
+#
+
 class ListPOINTER(object):
     '''Just like a POINTER but accept a list of ctype as an argument.
     '''
@@ -56,18 +96,48 @@ class ListPOINTER(object):
         if isinstance(param, (list,tuple)):
             return (self.etype * len(param))(*param)
 
+class LibVLCException(Exception):
+    """Python exception raised by libvlc methods.
+    """
+    pass
+
 # From libvlc_structures.h
-class VLCException(ctypes.Structure):
-    _fields_= [
-                ('raised', ctypes.c_int),
-                ('code', ctypes.c_int),
-                ('message', ctypes.c_char_p),
-                ]
-    def init(self):
-        libvlc_exception_init(self)
 
-    def clear(self):
-        libvlc_exception_clear(self)
+# This is version-dependent, depending on the presence of libvlc_errmsg
+
+if hasattr(dll, 'libvlc_errmsg'):
+    # New-style message passing
+    class VLCException(ctypes.Structure):
+        """libvlc exception.
+        """
+        _fields_= [
+                    ('raised', ctypes.c_int),
+                    ]
+
+        @property
+        def message(self):
+            return dll.libvlc_errmsg()
+
+        def init(self):
+            libvlc_exception_init(self)
+
+        def clear(self):
+            libvlc_exception_clear(self)
+else:
+    # Old-style exceptions
+    class VLCException(ctypes.Structure):
+        """libvlc exception.
+        """
+        _fields_= [
+                    ('raised', ctypes.c_int),
+                    ('code', ctypes.c_int),
+                    ('message', ctypes.c_char_p),
+                    ]
+        def init(self):
+            libvlc_exception_init(self)
+
+        def clear(self):
+            libvlc_exception_clear(self)
 
 class PlaylistItem(ctypes.Structure):
     _fields_= [
@@ -76,6 +146,9 @@ class PlaylistItem(ctypes.Structure):
                 ('name', ctypes.c_char_p),
                 ]
 
+    def __str__(self):
+        return "PlaylistItem #%d %s (%uri)" % (self.id, self.name, self.uri)
+
 class LogMessage(ctypes.Structure):
     _fields_= [
                 ('size', ctypes.c_uint),
@@ -86,35 +159,47 @@ class LogMessage(ctypes.Structure):
                 ('message', ctypes.c_char_p),
                 ]
 
+    def __init__(self):
+        self.size=ctypes.sizeof(self)
+
     def __str__(self):
-        print "vlc.LogMessage(%d:%s): %s" % (self.severity, self.type, self.message)
+        return "vlc.LogMessage(%d:%s): %s" % (self.severity, self.type, self.message)
 
 class MediaControlPosition(ctypes.Structure):
     _fields_= [
-                ('origin', ctypes.c_ushort),
-                ('key', ctypes.c_ushort),
+                ('origin', PositionOrigin),
+                ('key', PositionKey),
                 ('value', ctypes.c_longlong),
                 ]
 
+    def __init__(self, value=0, origin=None, key=None):
+        # We override the __init__ method so that instanciating the
+        # class with an int as parameter will create the appropriate
+        # default position (absolute position, media time, with the
+        # int as value).
+        self.value=value
+        if origin is None:
+            origin=PositionOrigin.AbsolutePosition
+        if key is None:
+            key=PositionKey.MediaTime
+        self.origin=origin
+        self.key=key
+
+    def __str__(self):
+        return "MediaControlPosition %ld (%s, %s)" % (
+            self.value,
+            str(self.origin),
+            str(self.key)
+            )
+
     @staticmethod
     def from_param(arg):
         if isinstance(arg, (int, long)):
-            p=MediaControlPosition()
-            p.value=arg
-            p.key=2
+            p=MediaControlPosition(arg)
             return p
         else:
             return arg
 
-class MediaControlPositionOrigin(ctypes.c_uint):
-    enum=(
-        'AbsolutePosition',
-        'RelativePosition',
-        'ModuloPosition',
-        )
-    def __repr__(self):
-        return self.enum[self.value]
-
 class MediaControlException(ctypes.Structure):
     _fields_= [
                 ('code', ctypes.c_int),
@@ -128,20 +213,35 @@ class MediaControlException(ctypes.Structure):
 
 class MediaControlStreamInformation(ctypes.Structure):
     _fields_= [
-                ('code', ctypes.c_int),
-                ('message', ctypes.c_char_p),
+                ('status', PlayerStatus),
+                ('url', ctypes.c_char_p),
+                ('position', ctypes.c_longlong),
+                ('length', ctypes.c_longlong),
                 ]
 
+    def __str__(self):
+        return "%s (%s) : %ld / %ld" % (self.url or "<No defined URL>",
+                                        str(self.status),
+                                        self.position,
+                                        self.length)
+
 class RGBPicture(ctypes.Structure):
     _fields_= [
                 ('width', ctypes.c_int),
                 ('height', ctypes.c_int),
                 ('type', ctypes.c_uint32),
-                ('date', ctypes.c_longlong),
+                ('date', ctypes.c_ulonglong),
                 ('size', ctypes.c_int),
-                ('data', ctypes.c_char_p),
+                ('data_pointer', ctypes.c_void_p),
                 ]
 
+    @property
+    def data(self):
+        return ctypes.string_at(self.data_pointer, self.size)
+
+    def __str__(self):
+        return "RGBPicture (%d, %d) - %ld ms - %d bytes" % (self.width, self.height, self.date, self.size)
+
     def free(self):
         mediacontrol_RGBPicture__free(self)
 
@@ -149,8 +249,13 @@ def check_vlc_exception(result, func, args):
     """Error checking method for functions using an exception in/out parameter.
     """
     ex=args[-1]
-    # Take into account both VLCException and MediacontrolException
+    if not isinstance(ex, (VLCException, MediaControlException)):
+        logging.warn("python-vlc: error when processing function %s. Please report this as a bug to vlc-devel@videolan.org" % str(func))
+        return result
+    # Take into account both VLCException and MediacontrolException:
     c=getattr(ex, 'raised', getattr(ex, 'code', 0))
     if c:
-        raise Exception(args[-1].message)
+        raise LibVLCException(ex.message)
     return result
+
+### End of header.py ###