Initial Project Commit
[retroconv] / pygobject.py
diff --git a/pygobject.py b/pygobject.py
new file mode 100644 (file)
index 0000000..150deae
--- /dev/null
@@ -0,0 +1,156 @@
+from ctypes import *
+import sys
+import ctypes
+
+import gobject
+
+# -------------------------------------------------------------------------
+class _PyGObject_Functions(ctypes.Structure):
+    """GObject <-> Python mapping from http://faq.pygtk.org/index.py?req=show&file=faq23.041.htp"""
+    _fields_ = [
+        ('register_class',
+         ctypes.PYFUNCTYPE(ctypes.c_void_p, ctypes.c_char_p,
+                           ctypes.c_int, ctypes.py_object,
+                           ctypes.py_object)),
+        ('register_wrapper',
+         ctypes.PYFUNCTYPE(ctypes.c_void_p, ctypes.py_object)),
+        ('register_sinkfunc',
+         ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
+        ('lookupclass',
+         ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_int)),
+        ('newgobj',
+         ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
+        ]
+
+
+# -------------------------------------------------------------------------
+class PyGObjectCAPI(object):
+    """GObject <-> Python mapping from http://faq.pygtk.org/index.py?req=show&file=faq23.041.htp"""
+    
+    def __init__(self):
+        addr = ctypes.pythonapi.PyCObject_AsVoidPtr(
+            ctypes.py_object(gobject._PyGObject_API))
+        self._api = _PyGObject_Functions.from_address(addr)
+
+    def pygobject_new(self, addr):
+        return self._api.newgobj(addr)
+
+
+# -------------------------------------------------------------------------
+class GList(Structure):
+    """GList representation and convenience functions, based on Java's Iterable.
+    
+       Copyright (c) Andrew Flegg <andrew@bleb.org> 2009.
+       Released under the Artistic Licence."""
+    
+    
+    # -----------------------------------------------------------------------
+    @classmethod
+    def new(clazz, ptr = None):
+        """Return a reference to an empty, or valid, GList at the
+           given pointer address."""
+           
+        if ptr:
+            return cast(c_void_p(ptr), POINTER(GList)).contents
+        else:
+            return GList()
+    
+    
+    # -----------------------------------------------------------------------
+    _fields_ = [('_data', c_void_p),
+                ('_next', c_void_p),
+                ('_prev', c_void_p)]
+                
+    _ptr = None # Initialises to before the list for `while(has_next)...'
+    
+    
+    # -----------------------------------------------------------------------
+    def reset(self):
+        """Rewind the iterable to the start of the list."""
+      
+        self._ptr = None
+      
+    # -----------------------------------------------------------------------
+    def has_next(self):
+        """Return True if the list has an item on which next can be called."""
+      
+        return (not self._ptr and self._data) or (self._ptr and self._ptr._next)
+    
+    
+    # -----------------------------------------------------------------------
+    def next(self, as_a = None):
+        """Move the pointer on to the next item in the list and return its value, or
+           raise an exception if already on the last."""
+           
+        if self._ptr and not self._ptr._next:
+            raise Exception("IndexOutOfBounds")
+        
+        self._ptr = self._ptr and cast(self._ptr._next, POINTER(GList)).contents or self
+        if not self._ptr._data:
+            return None
+        elif as_a:
+            return cast(self._ptr._data, POINTER(as_a)).contents
+        else:
+            return self._ptr._data
+        
+        
+    # -----------------------------------------------------------------------
+    def set(self, value):
+        """Set the data in the current position in the list."""
+      
+        if not self._ptr:
+            self._ptr = self
+        
+        self._ptr._data = cast(value, c_void_p);
+      
+      
+      
+    # -----------------------------------------------------------------------
+    def add(self):
+        """Add a new entry on to the end of the list, ready to be "set"."""
+        
+        self.reset()
+        while self.has_next():
+            self.next()
+          
+        if not self._ptr:
+            self._ptr = self
+        else:      
+            new = GList()
+            new._prev = addressof(self._ptr)
+            self._ptr._next = addressof(new)
+            self._ptr = new
+
+
+# -------------------------------------------------------------------------
+class EContactPhoto_inlined(Structure):
+    _fields_ = [('mime_type', c_char_p),
+                ('length', c_uint),
+                ('data', c_void_p)]
+
+class EContactPhoto_data(Union):
+    _fields_ = [('inlined', EContactPhoto_inlined),
+                ('uri', c_char_p)]
+
+class EContactPhoto(Structure):
+    _fields_ = [('type', c_int),
+                ('data', EContactPhoto_data)]
+
+class EContactDate(Structure):
+    _fields_ = [('year', c_uint),
+                ('month', c_uint),
+                ('day', c_uint)]
+
+# -------------------------------------------------------------------------
+class EVCardAttribute(Structure):
+    _fields_ = [('group', c_char_p),
+               ('name', c_char_p),
+               ('params', POINTER(GList)),
+               ('values', POINTER(GList)),]
+            
+    def value(self):
+        if not self.values:
+            return None
+     
+        return self.values.contents
+