diff options
Diffstat (limited to 'python/dbus_bindings.pyx')
| -rw-r--r-- | python/dbus_bindings.pyx | 1488 | 
1 files changed, 1488 insertions, 0 deletions
diff --git a/python/dbus_bindings.pyx b/python/dbus_bindings.pyx new file mode 100644 index 00000000..608ef544 --- /dev/null +++ b/python/dbus_bindings.pyx @@ -0,0 +1,1488 @@ +# -*- Mode: Python -*- + +# jdahlin is the most coolest and awesomest person in the world +# and wrote all the good parts of this code. all the bad parts +# where python conditionals have a ( ) around them, thus violating +# PEP-8 were written by the lame wannabe python programmer seth + +#FIXME: find memory leaks that I am sure exist + +cdef extern from "sys/types.h": +    ctypedef size_t +    ctypedef __int64_t +    ctypedef __uint64_t + +cdef extern from "sys/cdefs.h": +    ctypedef __signed + +cdef extern from "stdlib.h": +    cdef void *malloc(size_t size) +    cdef void free(void *ptr) +    cdef void *calloc(size_t nmemb, size_t size) + +cdef extern from "Python.h": +    void Py_XINCREF (object) +    void Py_XDECREF (object) +    object PyString_FromStringAndSize(char *, int) +    ctypedef void *PyGILState_STATE +    void PyErr_Clear() +    PyGILState_STATE PyGILState_Ensure() +    void PyGILState_Release(PyGILState_STATE) + +ctypedef struct DBusError: +    char *name +    char *message +    unsigned int dummy1  +    unsigned int dummy2 +    unsigned int dummy3 +    unsigned int dummy4 +    unsigned int dummy5 +    void *padding1 +     +ctypedef struct DBusMessageIter: +    void *dummy1 +    void *dummy2 +    dbus_uint32_t dummy3 +    int dummy4 +    int dummy5 +    int dummy6 +    int dummy7 +    int dummy8 +    int dummy9 +    int dummy10 +    int dummy11 +    int pad1 +    int pad2 +    void *pad3 + +ctypedef struct DBusObjectPathVTable: +  DBusObjectPathUnregisterFunction   unregister_function +  DBusObjectPathMessageFunction      message_function +  void (* dbus_internal_pad1) (void *) +  void (* dbus_internal_pad2) (void *) +  void (* dbus_internal_pad3) (void *) +  void (* dbus_internal_pad4) (void *) + + +_user_data_references = [ ] + +class DBusException(Exception): +    pass + +class ConnectionError(Exception): +    pass + +class ObjectPath(str): +    def __init__(self, value): +        str.__init__(value) + +class ByteArray(str): +    def __init__(self, value): +        str.__init__(value) + +class Signature(str): +    def __init__(self, value): +        str.__init__(value) + +class Byte(int): +    def __init__(self, value): +        int.__init__(value) + +class Boolean(int): +    def __init__(self, value): +        int.__init__(value) + +class Int16(int): +    def __init__(self, value): +        int.__init__(value) + +class UInt16(int): +    def __init__(self, value): +        if value < 0: +            raise TypeError('Unsigned integers must not have a negitive value')  +        int.__init__(value) + +class Int32(int): +    def __init__(self, value): +        int.__init__(value) + +class UInt32(long): +    def __init__(self, value): +        if value < 0: +            raise TypeError('Unsigned integers must not have a negitive value')  +        long.__init__(value) + +class Int64(long): +    def __init__(self, value): +        long.__init__(value) + +class UInt64(long): +    def __init__(self, value): +        if value < 0: +            raise TypeError('Unsigned integers must not have a negitive value')  +        long.__init__(value) + +class Double(float): +    def __init__(self, value): +        float.__init__(self, value) + +class String(str): +    def __init__(self, value): +        str.__init__(value) + +class Array(list): +    def __init__(self, value): +        list.__init__(value) + +class Struct(tuple): +    def __init__(self, value): +        tuple.__init__(value) + +class Dictionary(dict): +    def __init__(self, value): +        dict.__init__(value) + +#forward delcerations +cdef class Message +cdef class PendingCall +cdef class Watch +cdef class MessageIter + +cdef void cunregister_function_handler (DBusConnection *connection, +                                        void *user_data): +    cdef Connection conn +    cdef PyGILState_STATE gil + +    gil = PyGILState_Ensure() +    try: +        itup = <object>user_data +        assert (type(tup) == list)     +        function = tup[1] +        conn = Connection() +        conn.__cinit__(None, connection) + +        args = [conn] +        function(*args) +    finally: +        PyGILState_Release(gil) + +cdef DBusHandlerResult cmessage_function_handler (DBusConnection *connection, +                                                  DBusMessage *msg, +                                                  void *user_data): +    cdef Connection conn +    cdef Message message +    cdef PyGILState_STATE gil + +    gil = PyGILState_Ensure() +    try: +        tup = <object>user_data +        assert (type(tup) == list) +        function = tup[0] +        message = Message(_create=0) +        message._set_msg(msg) +        conn = Connection() +        conn.__cinit__(None, connection)   +        args = [conn, +                message] +        retval = function(*args) +        if (retval == None): +            retval = DBUS_HANDLER_RESULT_HANDLED +        return retval +    finally: +        PyGILState_Release(gil) +	 +cdef class Connection: +    def __init__(self, address=None, Connection _conn=None): +        cdef DBusConnection *c_conn +        cdef char *c_address +        c_conn=NULL +        self.conn = NULL +        if (_conn != None): +            c_conn = _conn.conn + +        if (address != None or _conn != None): +            self.__cinit__(c_address, c_conn) + +    # hack to be able to pass in a c pointer to the constructor +    # while still alowing python programs to create a Connection object +    cdef __cinit__(self, address, DBusConnection *_conn): +        cdef DBusError error +        dbus_error_init(&error) +        if _conn != NULL: +            self.conn = _conn +            dbus_connection_ref(self.conn) +        else: +            self.conn = dbus_connection_open(address, +                                         &error) +            if dbus_error_is_set(&error): +                raise DBusException, error.message + +    def __del__(self): +        if self.conn != NULL: +            dbus_connection_unref(self.conn) + +    cdef _set_conn(self, DBusConnection *conn): +        self.conn = conn +     +    cdef DBusConnection *_get_conn(self): +        return self.conn +     +    def get_unique_name(self): +        return bus_get_unique_name(self) + +    def disconnect(self): +        dbus_connection_disconnect(self.conn) + +    def get_is_connected(self): +        return dbus_connection_get_is_connected(self.conn) +     +    def get_is_authenticated(self): +        return dbus_connection_get_is_authenticated(self.conn) + +    def flush(self): +        dbus_connection_flush(self.conn) + +    def borrow_message(self): +        cdef Message m +        m = Message(_create=0) +        m._set_msg(dbus_connection_borrow_message(self.conn)) +        return m +     +    def return_message(self, Message message): +        cdef DBusMessage *msg +        msg = message._get_msg() +        dbus_connection_return_message(self.conn, msg) + +    def steal_borrowed_message(self, Message message): +        cdef DBusMessage *msg +        msg = message._get_msg() +        dbus_connection_steal_borrowed_message(self.conn, +                                               msg) +     +    def pop_message(self): +        cdef DBusMessage *msg +        cdef Message m +  +        msg = dbus_connection_pop_message(self.conn) +        if msg != NULL: +            m = Message(_create=0) +            m._set_msg(msg) +        else: +            m = None +        return m         + +    def get_dispatch_status(self): +        return dbus_connection_get_dispatch_status(self.conn) +     +    def dispatch(self): +        return dbus_connection_dispatch(self.conn) + +    def send(self, Message message): +        #cdef dbus_uint32_t client_serial +        #if type(message) != Message: +        #    raise TypeError +        cdef DBusMessage *msg +        msg = message._get_msg() +        retval = dbus_connection_send(self.conn, +                                      msg, +                                      NULL) +        return retval + +    def send_with_reply_handlers(self, Message message, timeout_milliseconds, reply_handler, error_handler): +        retval = False +        try: +            (retval, pending_call) = self.send_with_reply(message, timeout_milliseconds) +            if pending_call: +                pending_call.set_notify(reply_handler, error_handler) +        except Exception, e: +            error_handler(e) +             +        return retval + +    def send_with_reply(self, Message message, timeout_milliseconds): +        cdef dbus_bool_t retval +        cdef DBusPendingCall *cpending_call +        cdef DBusError error +        cdef DBusMessage *msg +        cdef PendingCall pending_call + +        dbus_error_init(&error) + +        cpending_call = NULL +         +        msg = message._get_msg() + +        retval = dbus_connection_send_with_reply(self.conn, +                                                 msg, +                                                 &cpending_call, +                                                 timeout_milliseconds) + +        if dbus_error_is_set(&error): +            raise DBusException, error.message + +        if (cpending_call != NULL): +            pending_call = PendingCall() +            pending_call.__cinit__(cpending_call) +        else: +            pending_call = None + +        return (retval, pending_call) +                                 +    def send_with_reply_and_block(self, Message message, +                                  timeout_milliseconds=0): +        cdef DBusMessage * retval +        cdef DBusError error +        cdef DBusMessage *msg +        cdef Message m + +        dbus_error_init(&error) + +        msg = message._get_msg() + +        retval = dbus_connection_send_with_reply_and_block( +            self.conn, +            msg, +            timeout_milliseconds, +            &error) + +        if dbus_error_is_set(&error): +            raise DBusException, error.message + +        if retval == NULL: +            raise AssertionError +         +        m = Message(_create=0) +        m._set_msg(retval) +        return m + +    def set_watch_functions(self, add_function, remove_function, data): +        pass + +    def set_timeout_functions(self, add_function, remove_function, data): +        pass + +    def set_wakeup_main_function(self, wakeup_main_function, data): +        pass + +    # FIXME: set_dispatch_status_function, get_unix_user, set_unix_user_function + +    def add_filter(self, filter_function): +        user_data = [ filter_function ] +        global _user_data_references +        _user_data_references.append(user_data) +         +        return dbus_connection_add_filter(self.conn, +                                          cmessage_function_handler, +                                          <void*>user_data, +                                          NULL) + + +    #FIXME: remove_filter +    #       this is pretty tricky, we want to only remove the filter +    #       if we truly have no more calls to our message_function_handler...ugh + +    def set_data(self, slot, data): +        pass + +    def get_data(self, slot): +        pass + +    def set_max_message_size(self, size): +        dbus_connection_set_max_message_size(self.conn, size) + +    def get_max_message_size(self): +        return dbus_connection_get_max_message_size(self.conn) + +    def set_max_received_size(self, size): +        dbus_connection_set_max_received_size(self.conn, size) + +    def get_max_received_size(self): +        return dbus_connection_get_max_received_size(self.conn) + +    def get_outgoing_size(self): +        return dbus_connection_get_outgoing_size(self.conn)     + +    # preallocate_send, free_preallocated_send, send_preallocated + +    def register_object_path(self, path, unregister_cb, message_cb): +        cdef DBusObjectPathVTable cvtable +         +        cvtable.unregister_function = cunregister_function_handler  +        cvtable.message_function    = cmessage_function_handler + +        user_data = [message_cb, unregister_cb] +        global _user_data_references +        _user_data_references.append(user_data) +         +        return dbus_connection_register_object_path(self.conn, path, &cvtable, +                                                    <void*>user_data)  + +    def register_fallback(self, path, unregister_cb, message_cb): +        cdef DBusObjectPathVTable cvtable + +        cvtable.unregister_function = cunregister_function_handler  +        cvtable.message_function    = cmessage_function_handler + +        user_data = [message_cb, unregister_cb] +        global _user_data_references +        _user_data_references.append(user_data)         +         +        return dbus_connection_register_fallback(self.conn, path, &cvtable, +                                                 <void*>user_data)  + +    #FIXME: unregister_object_path , see problems with remove_filter + +    def list_registered (self, parent_path): +        cdef char **cchild_entries +        cdef dbus_bool_t retval +         +        retval = dbus_connection_list_registered(self.conn, parent_path, &cchild_entries) + +        if (not retval): +            #FIXME: raise out of memory exception? +            return None + +        i = 0 +        child_entries = [] + +        while (cchild_entries[i] != NULL): +            child_entries.append(cchild_entries[i]) +            i = i + 1 + +        dbus_free_string_array(cchild_entries) + +        return child_entries + +cdef void _pending_call_notification(DBusPendingCall *pending_call, void *user_data): +    cdef DBusMessage *dbus_message +    cdef Message message +    +    (reply_handler, error_handler) = <object>user_data +    +    dbus_message = dbus_pending_call_steal_reply(pending_call) +    message = Message(_create=0) +    message._set_msg(dbus_message) + +    type = message.get_type() + +    if type == MESSAGE_TYPE_METHOD_RETURN: +        args = message.get_args_list() +        reply_handler(*args) +    elif type == MESSAGE_TYPE_ERROR: +        args = message.get_args_list() +        error_handler(DBusException(args[0])) +    else: +        error_handler(DBusException('Unexpected Message Type: ' + message.type_to_name(type))) + +    dbus_message_unref(dbus_message) +    dbus_pending_call_unref(pending_call) + +cdef void _pending_call_free_user_data(void *data): +    call_tuple = <object>data +    Py_XDECREF(call_tuple) + +cdef class PendingCall: +    cdef DBusPendingCall *pending_call + +    def __init__(self, PendingCall _pending_call=None): +        self.pending_call = NULL +        if (_pending_call != None): +            self.__cinit__(_pending_call.pending_call) + +    cdef void __cinit__(self, DBusPendingCall *_pending_call): +        self.pending_call = _pending_call +        dbus_pending_call_ref(self.pending_call) + +    def __del__(self): +        if self.pending_call != NULL: +            dbus_pending_call_unref(self.pending_call) + +    cdef DBusPendingCall *_get_pending_call(self): +        return self.pending_call + +    def cancel(self): +        dbus_pending_call_cancel(self.pending_call) + +    def get_completed(self): +        return dbus_pending_call_get_completed(self.pending_call) + +    def get_reply(self): +        cdef Message message +        message = Message(_create=0) +        message._set_msg(dbus_pending_call_steal_reply(self.pending_call)) +        return message + +    def block(self): +        dbus_pending_call_block(self.pending_call) + +    def set_notify(self, reply_handler, error_handler): +        user_data = (reply_handler, error_handler) +        Py_XINCREF(user_data) +        dbus_pending_call_set_notify(self.pending_call, _pending_call_notification,  +                                     <void *>user_data, _pending_call_free_user_data) +         + +cdef class Watch: +    cdef DBusWatch* watch + +    def __init__(self): +        pass + +    cdef __cinit__(self, DBusWatch *cwatch): +        self.watch = cwatch + +    def get_fd(self): +        return dbus_watch_get_fd(self.watch) + +    # FIXME: not picked up correctly by extract.py +    #def get_flags(self): +    #    return dbus_watch_get_flags(self.watch) + +    def handle(self, flags): +        return dbus_watch_handle(self.watch, flags) + +    def get_enabled(self): +        return dbus_watch_get_enabled(self.watch) +     +cdef class MessageIter: +    cdef DBusMessageIter *iter +    cdef DBusMessageIter real_iter +    cdef dbus_uint32_t level + +    def __init__(self, level=0): +        self.iter = &self.real_iter +        self.level = level +        if(self.level > 32): +            raise TypeError, 'Type recurion is too deep'  + +    cdef __cinit__(self, DBusMessageIter *iter): +        self.real_iter = iter[0] + +    cdef DBusMessageIter *_get_iter(self): +        return self.iter + +    def has_next(self): +        return dbus_message_iter_has_next(self.iter) +     +    def next(self): +        return dbus_message_iter_next(self.iter) + +    def get(self, arg_type=None): +        if(arg_type == None): +            arg_type = self.get_arg_type() + +        if arg_type == TYPE_INVALID: +            raise TypeError, 'Invalid arg type in MessageIter' +        elif arg_type == TYPE_STRING: +            retval = self.get_string() +        elif arg_type == TYPE_INT16: +            retval = self.get_int16() +        elif arg_type == TYPE_UINT16: +            retval = self.get_uint16() +        elif arg_type == TYPE_INT32: +            retval = self.get_int32() +        elif arg_type == TYPE_UINT32: +            retval = self.get_uint32() +        elif arg_type == TYPE_INT64: +            retval = self.get_int64() +        elif arg_type == TYPE_UINT64: +            retval = self.get_uint64() +        elif arg_type == TYPE_DOUBLE: +            retval = self.get_double() +        elif arg_type == TYPE_BYTE: +            retval = self.get_byte() +        elif arg_type == TYPE_BOOLEAN: +            retval = self.get_boolean() +        elif arg_type == TYPE_SIGNATURE: +            retval = self.get_signature() +        elif arg_type == TYPE_ARRAY: +            array_type = self.get_element_type() +            if array_type == TYPE_DICT_ENTRY: +                retval = self.get_dict() +            else: +                retval = self.get_array(array_type) +        elif arg_type == TYPE_OBJECT_PATH: +            retval = self.get_object_path() +        elif arg_type == TYPE_STRUCT: +            retval = self.get_struct() +        elif arg_type == TYPE_VARIANT: +            retval = self.get_variant() +        elif arg_type == TYPE_DICT_ENTRY: +            raise TypeError, 'Dictionary Entries can only appear as part of an array container' +        else: +            raise TypeError, 'Unknown arg type %d in MessageIter' % (arg_type) + +        return retval + +    def get_arg_type(self): +        return dbus_message_iter_get_arg_type(self.iter) + +    def get_element_type(self): +        return dbus_message_iter_get_element_type(self.iter) + +    def get_byte(self): +        cdef char c_val +        dbus_message_iter_get_basic(self.iter, <char *>&c_val) +        return c_val +         +    def get_boolean(self): +        cdef dbus_bool_t c_val +        dbus_message_iter_get_basic(self.iter, <dbus_bool_t *>&c_val) +        return c_val + +    def get_signature(self): +        signature_string = self.get_string() +        return Signature(signature_string) + +    def get_int16(self): +        cdef dbus_int16_t c_val +        dbus_message_iter_get_basic(self.iter, <dbus_int16_t *>&c_val) +        return c_val + +    def get_uint16(self): +        cdef dbus_uint16_t c_val +        dbus_message_iter_get_basic(self.iter, <dbus_uint16_t *>&c_val) +        return c_val + +    def get_int32(self): +        cdef dbus_int32_t c_val +        dbus_message_iter_get_basic(self.iter, <dbus_int32_t *>&c_val) +        return c_val +         +    def get_uint32(self): +        cdef dbus_uint32_t c_val +        dbus_message_iter_get_basic(self.iter, <dbus_uint32_t *>&c_val) +        return c_val +         +    def get_int64(self): +        cdef dbus_int64_t c_val +        dbus_message_iter_get_basic(self.iter, <dbus_int64_t *>&c_val) +        return c_val + +    def get_uint64(self): +        cdef dbus_uint64_t c_val +        dbus_message_iter_get_basic(self.iter, <dbus_uint64_t *>&c_val) +        return c_val + +    def get_double(self): +        cdef double c_val +        dbus_message_iter_get_basic(self.iter, <double *>&c_val) +        return c_val + +    def get_string(self): +        cdef char *c_str +        dbus_message_iter_get_basic(self.iter, <char **>&c_str) +        return c_str + +    def get_object_path(self): +        object_path_string = self.get_string() +        return ObjectPath(object_path_string) + +    def get_dict(self): +        cdef DBusMessageIter c_dict_iter +        cdef MessageIter dict_iter +        level = self.level + 1 + +        dbus_message_iter_recurse(self.iter, <DBusMessageIter *>&c_dict_iter) +        dict_iter = MessageIter(level) +        dict_iter.__cinit__(&c_dict_iter) +         +        python_dict = {} +        cur_arg_type = dict_iter.get_arg_type() +        while cur_arg_type == TYPE_DICT_ENTRY: +            if cur_arg_type != TYPE_DICT_ENTRY: +                raise TypeError, "Dictionary elements must be of type TYPE_DICT_ENTRY '%s != %s'" % (TYPE_DICT_ENTRY, cur_arg_type) +                 +            dict_entry = dict_iter.get_struct() +            if len(dict_entry) != 2: +                raise TypeError, "Dictionary entries must be structs of two elements.  This entry had %i elements.'" % (len(dict_entry)) + +            python_dict[dict_entry[0]] = dict_entry[1] +             +            dict_iter.next() +            cur_arg_type = dict_iter.get_arg_type() + +        return python_dict +    +    def get_array(self, type): +        cdef DBusMessageIter c_array_iter +        cdef MessageIter array_iter +        level = self.level + 1 + +        dbus_message_iter_recurse(self.iter, <DBusMessageIter *>&c_array_iter) +        array_iter = MessageIter(level) +        array_iter.__cinit__(&c_array_iter) +         +        python_list = [] +        cur_arg_type = array_iter.get_arg_type() +        while cur_arg_type != TYPE_INVALID: +            if cur_arg_type != type: +                raise TypeError, "Array elements must be of the same type '%s != %s'" % (type, cur_arg_type) +                 +            value = array_iter.get(type) +            python_list.append(value) +             +            array_iter.next() +            cur_arg_type = array_iter.get_arg_type() + +        return python_list + +    def get_variant(self): +        cdef DBusMessageIter c_var_iter +        cdef MessageIter var_iter +        level = self.level + 1 + +        dbus_message_iter_recurse(self.iter, <DBusMessageIter *>&c_var_iter) +        var_iter = MessageIter(level) +        var_iter.__cinit__(&c_var_iter) +         +        return var_iter.get()  + +    def get_struct(self): +        cdef DBusMessageIter c_struct_iter +        cdef MessageIter struct_iter +        level = self.level + 1 + +        dbus_message_iter_recurse(self.iter, <DBusMessageIter *>&c_struct_iter) +        struct_iter = MessageIter(level) +        struct_iter.__cinit__(&c_struct_iter) + +        python_list = [] +        while struct_iter.get_arg_type() != TYPE_INVALID: +            value = struct_iter.get() +            python_list.append(value) +             +            struct_iter.next() + +        return tuple(python_list) + +    def python_value_to_dbus_sig(self, value, level = 0): + +        if(level > 32): +            raise TypeError, 'Type recurion is too deep'  + +        level = level + 1 + +        ptype = type(value) +        ret = "" +        if ptype == bool: +            ret = TYPE_BOOL +            ret = str(chr(ret)) +        elif ptype == int: +            ret = TYPE_INT32 +            ret = str(chr(ret)) +        elif ptype == long: +            ret = TYPE_INT64 +            ret = str(chr(ret)) +        elif ptype == str: +            ret = TYPE_STRING +            ret = str(chr(ret)) +        elif ptype == float: +            ret = TYPE_DOUBLE +            ret = str(chr(ret)) +        elif ptype == dict: +            dict_list = value.items() +            key, value = dict_list[0] + +            ret = str(chr(TYPE_ARRAY)) + str(chr(DICT_ENTRY_BEGIN)) +            ret = ret + self.python_value_to_dbus_sig(key, level) +            ret = ret + self.python_value_to_dbus_sig(value, level) +            ret = ret + str(chr(DICT_ENTRY_END)) + +        elif ptype == tuple: +            ret = str(chr(STRUCT_BEGIN)) +            for item in value: +                ret = ret + self.python_value_to_dbus_sig(item, level) +            ret = ret + str(chr(STRUCT_END)) +        elif ptype == list: +            ret = str(chr(TYPE_ARRAY)) +            ret = ret + self.python_value_to_dbus_sig(value[0], level) +        elif isinstance(value, ObjectPath): +            ret = TYPE_OBJECT_PATH +            ret = str(chr(ret)) +        elif isinstance(ByteArray): +            ret = str(chr(TYPE_ARRAY)) + str(chr(TYPE_BYTE)) +        elif isinstance(Signature): +            ret = TYPE_SIGNATURE +            ret = str(chr(ret)) +        elif isinstance(value, Byte): +            ret = TYPE_BYTE +            ret = str(chr(ret)) +        elif isinstance(value, Boolean): +            ret = TYPE_BOOL +            ret = str(chr(ret)) +        elif isinstance(value, Int16): +            ret = TYPE_INT16 +            ret = str(chr(ret)) +        elif isinstance(value, UInt16): +            ret = TYPE_UINT16 +            ret = str(chr(ret)) +        elif isinstance(value, Int32): +            ret = TYPE_INT32 +            ret = str(chr(ret)) +        elif isinstance(value, UInt32): +            ret = TYPE_UINT32 +            ret = str(chr(ret)) +        elif isinstance(value, Int64): +            ret = TYPE_INT64 +            ret = str(chr(ret)) +        elif isinstance(value, UInt64): +            ret = TYPE_UINT64 +            ret = str(chr(ret)) +        elif isinstance(value, Double): +            ret = TYPE_DOUBLE +            ret = str(chr(ret)) +        elif isinstance(value, String): +            ret = TYPE_STRING +            ret = str(chr(ret)) +        elif isinstance(value, Array): +            ret = str(chr(TYPE_ARRAY)) +            ret = ret + self.python_value_to_dbus_sig(value[0], level) +        elif isinstance(value, Struct): +            ret = str(chr(STRUCT_BEGIN)) +            for item in value: +                ret = ret + self.python_value_to_dbus_sig(item, level) +            ret = ret + str(chr(STRUCT_END)) +        elif isinstance(value, Dictionary): +            dict_list = value.items() +            key, value = dict_list[0] + +            ret = str(chr(TYPE_ARRAY)) + str(chr(DICT_ENTRY_BEGIN)) +            ret = ret + self.python_value_to_dbus_sig(key, level) +            ret = ret + self.python_value_to_dbus_sig(value, level) +            ret = ret + str(chr(DICT_ENTRY_END)) +        else: +            raise TypeError, "Argument of unknown type '%s'" % (ptype) + +        return ret + +     +    #FIXME: handle all the different types? +    def append(self, value): +        value_type = type(value) +        if value_type == bool: +            retval = self.append_boolean(value) +        elif value_type == int: +            retval = self.append_int32(value) +        elif value_type == long: +            retval = self.append_int64(value) +        elif value_type == str: +            retval = self.append_string(value) +        elif value_type == float: +            retval = self.append_double(value) +        elif value_type == dict: +            retval = self.append_dict(value) +        elif value_type == tuple: +            retval = self.append_struct(value) +        elif value_type == list: +             retval = self.append_array(value) +        #elif value_type == None.__class__: +        #    retval = self.append_nil() +        elif isinstance(value, ObjectPath): +            retval = self.append_object_path(value) +        elif isinstance(value, ByteArray): +            retval = self.append_array(value) +        elif isinstance(value, Signature): +            retval = self.append_signature(value) +        elif isinstance(value, Byte): +            retval = self.append_byte(value) +        elif isinstance(value, Boolean): +            retval = self.append_boolean(value) +        elif isinstance(value, Int16): +            retval = self.append_int16(value) +        elif isinstance(value, UInt16): +            retval = self.append_uint16(value) +        elif isinstance(value, Int32): +            retval = self.append_int32(value) +        elif isinstance(value, UInt32): +            retval = self.append_uint32(value) +        elif isinstance(value, Int64): +            retval = self.append_int64(value) +        elif isinstance(value, UInt64): +            retval = self.append_uint64(value) +        elif isinstance(value, Double): +            retval = self.append_double(value) +        elif isinstance(value, String): +            retval = self.append_string(value) +        elif isinstance(value, Array): +            retval = self.append_array(value) +        elif isinstance(value, Struct): +            retval = self.append_struct(value) +        elif isinstance(value, Dictionary): +            retval = self.append_dict(value) +        else: +            raise TypeError, "Argument of unknown type '%s'" % (value_type) + +        return retval + +    def append_boolean(self, value): +        cdef dbus_bool_t c_value +        c_value = value +        return dbus_message_iter_append_basic(self.iter, TYPE_BOOLEAN, <dbus_bool_t *>&c_value) + +    def append_byte(self, value): +        cdef char b +        if type(value) != str or len(value) != 1: +            raise TypeError + +        b = ord(value) +        return dbus_message_iter_append_basic(self.iter, TYPE_BYTE, <char *>&b) + +    def append_int16(self, value): +        cdef dbus_int32_t c_value +        c_value = value +        return dbus_message_iter_append_basic(self.iter, TYPE_INT16, <dbus_int32_t *>&c_value) + +    def append_uint16(self, value): +        cdef dbus_uint32_t c_value +        c_value = value +        return dbus_message_iter_append_basic(self.iter, TYPE_UINT16, <dbus_uint32_t *>&c_value) + +    def append_int32(self, value): +        cdef dbus_int32_t c_value +        c_value = value +        return dbus_message_iter_append_basic(self.iter, TYPE_INT32, <dbus_int32_t *>&c_value) + +    def append_uint32(self, value): +        cdef dbus_uint32_t c_value +        c_value = value +        return dbus_message_iter_append_basic(self.iter, TYPE_UINT32, <dbus_uint32_t *>&c_value) + +    def append_int64(self, value): +        cdef dbus_int64_t c_value +        c_value = value +        return dbus_message_iter_append_basic(self.iter, TYPE_INT64, <dbus_int64_t *>&c_value) + +    def append_uint64(self, value): +        cdef dbus_uint64_t c_value +        c_value = value +        return dbus_message_iter_append_basic(self.iter, TYPE_UINT64, <dbus_uint64_t *>&c_value) + +    def append_double(self, value): +        cdef double c_value +        c_value = value +        return dbus_message_iter_append_basic(self.iter, TYPE_DOUBLE, <double *>&c_value) + +    def append_string(self, value): +        cdef char *c_value +        c_value = value +        return dbus_message_iter_append_basic(self.iter, TYPE_STRING, <char **>&c_value)     + +    def append_object_path(self, value): +        cdef char *c_value +        c_value = value +        return dbus_message_iter_append_basic(self.iter, TYPE_OBJECT_PATH, <char **>&c_value) + +    def append_signature(self, value): +        cdef char *c_value +        c_value = value +        return dbus_message_iter_append_basic(self.iter, TYPE_SIGNATURE, <char **>&c_value) + + +    def append_dict(self, python_dict): +        cdef DBusMessageIter c_dict_iter, c_dict_entry_iter +        cdef MessageIter dict_iter, dict_entry_iter +         +        level = self.level + 1 + +        dict_list = python_dict.items() +        key, value = dict_list[0] + +        sig = str(chr(DICT_ENTRY_BEGIN)) +        sig = sig + self.python_value_to_dbus_sig(key) +        sig = sig + self.python_value_to_dbus_sig(value) +        sig = sig + str(chr(DICT_ENTRY_END)) + +        dbus_message_iter_open_container(self.iter, TYPE_ARRAY, sig, <DBusMessageIter *>&c_dict_iter) +        dict_iter = MessageIter(level) +        dict_iter.__cinit__(&c_dict_iter) + +        for key, value in dict_list: +            dbus_message_iter_open_container(dict_iter.iter, TYPE_DICT_ENTRY, sig, <DBusMessageIter *>&c_dict_entry_iter) +            dict_entry_iter = MessageIter(level) +            dict_entry_iter.__cinit__(&c_dict_entry_iter) + +            dict_entry_iter.append(key) +            dict_entry_iter.append(value) + +            dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter) + +        dbus_message_iter_close_container(self.iter, dict_iter.iter) + +    def append_struct(self, python_struct): +        cdef DBusMessageIter c_struct_iter +        cdef MessageIter struct_iter + +        level = self.level + 1 +        dbus_message_iter_open_container(self.iter, TYPE_STRUCT, NULL, <DBusMessageIter *>&c_struct_iter) +        struct_iter = MessageIter(level) +        struct_iter.__cinit__(&c_struct_iter) +         +        for item in python_struct: +            if not struct_iter.append(item): +                dbus_message_iter_close_container(self.iter, struct_iter.iter) +                return False + +        dbus_message_iter_close_container(self.iter, struct_iter.iter) + +    def append_array(self, python_list): +        cdef DBusMessageIter c_array_iter +        cdef MessageIter array_iter + +        level = self.level + 1 +        sig = self.python_value_to_dbus_sig(python_list[0]) + +        dbus_message_iter_open_container(self.iter, TYPE_ARRAY, sig, <DBusMessageIter *>&c_array_iter) +        array_iter = MessageIter(level) +        array_iter.__cinit__(&c_array_iter) + +        length = len(python_list) +        for item in python_list: +            if not array_iter.append(item): +                dbus_message_iter_close_container(self.iter, array_iter.iter) +                return False + +        dbus_message_iter_close_container(self.iter, array_iter.iter) + +        return True + +    def __str__(self): +        cdef DBusMessageIter c_array_iter +        cdef MessageIter array_iter + +        value_at_iter = True +        retval = "" +        while (value_at_iter): +            type = self.get_arg_type() +            if type == TYPE_INVALID: +                break +            elif type == TYPE_STRING: +                str = iter.get_string() +                arg = 'string:%s\n' % (str) +            elif type == TYPE_OBJECT_PATH: +                path = iter.get_object_path() +                arg = 'object_path:%s\n' % (path) +            elif type == TYPE_INT32: +                num = iter.get_int32() +                arg = 'int32:%d\n' % (num) +            elif type == TYPE_UINT32: +                num = iter.get_uint32() +                arg = 'uint32:%u\n' % (num) +            elif type == TYPE_INT64: +                num = iter.get_int64() +                arg = 'int64:%d\n' % (num) +            elif type == TYPE_UINT64: +                num = iter.get_uint64() +                arg = 'uint64:%u\n' % (num) +            elif type == TYPE_DOUBLE: +                num = iter.get_double() +                arg = 'double:%f\n' % (num) +            elif type == TYPE_BYTE: +                num = iter.get_byte() +                arg = 'byte:%x(%s)\n' % (num, str(chr(num))) +            elif type == TYPE_BOOLEAN: +                bool = iter.get_boolean() +                if (bool): +                    str = "true" +                else: +                    str = "false" +                arg = 'boolean:%s\n' % (str) +            elif type == TYPE_ARRAY: +                dbus_message_iter_recurse(self.iter, <DBusMessageIter *>&c_array_iter) +                array_iter = MessageIter(self.level + 1) +                array_iter.__cinit__(&c_array_iter) +                if array_iter.has_next(): +                    arg = 'array [' + str(array_iter) + ']' +                else: +                    arg = 'array []' +            else: +                arg = '(unknown arg type %d)\n' % type + +            retval = retval + arg +            value_at_iter = self.next() + +        return retval + + +(MESSAGE_TYPE_INVALID, MESSAGE_TYPE_METHOD_CALL, MESSAGE_TYPE_METHOD_RETURN, MESSAGE_TYPE_ERROR, MESSAGE_TYPE_SIGNAL) = range(5) +(TYPE_INVALID, TYPE_BYTE, TYPE_BOOLEAN, TYPE_INT16, TYPE_UINT16, TYPE_INT32, TYPE_UINT32, TYPE_INT64, TYPE_UINT64, TYPE_DOUBLE, TYPE_STRING, TYPE_OBJECT_PATH, TYPE_SIGNATURE, TYPE_ARRAY, TYPE_STRUCT, STRUCT_BEGIN, STRUCT_END, TYPE_VARIANT, TYPE_DICT_ENTRY, DICT_ENTRY_BEGIN, DICT_ENTRY_END) = (0, ord('y'), ord('b'), ord('n'), ord('q'), ord('i'), ord('u'), ord('x'), ord('t'), ord('d'), ord('s'), ord('o'), ord('g'), ord('a'), ord('r'), ord('('), ord(')'), ord('v'), ord('e'), ord('{'), ord('}')) +(HANDLER_RESULT_HANDLED, HANDLER_RESULT_NOT_YET_HANDLED, HANDLER_RESULT_NEED_MEMORY) = range(3) +     +cdef class Message: +    cdef DBusMessage *msg + +    def __init__(self, message_type=MESSAGE_TYPE_INVALID, +                 service=None, path=None, dbus_interface=None, method=None, +                 Message method_call=None, +                 name=None, +                 Message reply_to=None, error_name=None, error_message=None, +                 _create=1): + +        self.msg = NULL + +        cdef char *cservice +        cdef char *ciface +        cdef DBusMessage *cmsg + +        ciface = NULL +        if (dbus_interface != None): +            ciface = dbus_interface + +        cservice = NULL +        if (service != None): +            cservice = service +             +        if not _create: +            return + +        if message_type == MESSAGE_TYPE_METHOD_CALL: +            self.msg = dbus_message_new_method_call(cservice, path, ciface, method) +        elif message_type == MESSAGE_TYPE_METHOD_RETURN: +            cmsg = method_call._get_msg() +            self.msg = dbus_message_new_method_return(cmsg) +        elif message_type == MESSAGE_TYPE_SIGNAL: +            self.msg = dbus_message_new_signal(path, ciface, name) +        elif message_type == MESSAGE_TYPE_ERROR: +            cmsg = reply_to._get_msg() +            self.msg = dbus_message_new_error(cmsg, error_name, error_message) + +    def __del__(self): +        if self.msg != NULL: +            dbus_message_unref(self.msg) +             +    def type_to_name(self, type): +        if type == MESSAGE_TYPE_SIGNAL: +            return "signal" +        elif type == MESSAGE_TYPE_METHOD_CALL: +            return "method call" +        elif type == MESSAGE_TYPE_METHOD_RETURN: +            return "method return" +        elif type == MESSAGE_TYPE_ERROR: +            return "error" +        else: +            return "(unknown message type)" + +    def __str__(self): +        message_type = self.get_type() +        sender = self.get_sender() + +        if sender == None: +            sender = "(no sender)" + +        if (message_type == MESSAGE_TYPE_METHOD_CALL) or (message_type == MESSAGE_TYPE_SIGNAL): +            retval = '%s interface=%s; member=%s; sender=%s' % (self.type_to_name(message_type), +                                                                self.get_interface(), +                                                                self.get_member(), +                                                                sender) +        elif message_type == MESSAGE_TYPE_METHOD_RETURN: +            retval = '%s sender=%s' % (self.type_to_name(message_type), +                                        sender) +        elif message_type == MESSAGE_TYPE_ERROR: +            retval = '%s name=%s; sender=%s' % (self.type_to_name(message_type), +                                                self.get_error_name(), +                                                sender) +        else: +            retval = "Message of unknown type %d" % (message_type) + + +        # FIXME: should really use self.convert_to_tuple() here +         +        iter = self.get_iter() + +        retval = retval + "\n" + str(iter)  + +        return retval +     +    cdef _set_msg(self, DBusMessage *msg): +        self.msg = msg + +    cdef DBusMessage *_get_msg(self): +        return self.msg + +    def get_iter(self, append=False): +        cdef DBusMessageIter iter +        cdef MessageIter message_iter +        cdef DBusMessage *msg + +        msg = self._get_msg() + +        if append: +            dbus_message_iter_init_append(msg, &iter) +        else: +            dbus_message_iter_init(msg, &iter) + +        message_iter = MessageIter(0) +        message_iter.__cinit__(&iter) + +        return message_iter + +    def get_args_list(self): +        retval = [ ] + +        iter = self.get_iter() +        try: +            retval.append(iter.get()) +        except TypeError, e: +            return [ ] +             +        value_at_iter = iter.next() +        while (value_at_iter): +            retval.append(iter.get()) +            value_at_iter = iter.next()         + +        return retval +             +    # FIXME: implement dbus_message_copy? + +    def get_type(self): +        return dbus_message_get_type(self.msg) + +    def set_path(self, object_path): +        return dbus_message_set_path(self.msg, object_path) +     +    def get_path(self): +        return dbus_message_get_path(self.msg) +     +    def set_interface(self, interface): +        return dbus_message_set_interface(self.msg, interface) + +    def get_interface(self): +        return dbus_message_get_interface(self.msg)     + +    def set_member(self, member): +        return dbus_message_set_member(self.msg, member) + +    def get_member(self): +        return dbus_message_get_member(self.msg) + +    def set_error_name(self, name): +        return dbus_message_set_error_name(self.msg, name) + +    def get_error_name(self): +        return dbus_message_get_error_name(self.msg) + +    def set_destination(self, destination): +        return dbus_message_set_destination(self.msg, destination) + +    def get_destination(self): +        return dbus_message_get_destination(self.msg) + +    def set_sender(self, sender): +        return dbus_message_set_sender(self.msg, sender) +     +    def get_sender(self): +        cdef char *sender +        sender = dbus_message_get_sender(self.msg) +        if (sender == NULL): +            return None +        else: +            return sender + +    def set_no_reply(self, no_reply): +        dbus_message_set_no_reply(self.msg, no_reply) + +    def get_no_reply(self): +        return dbus_message_get_no_reply(self.msg) + +    def is_method_call(self, interface, method): +        return dbus_message_is_method_call(self.msg, interface, method) + +    def is_signal(self, interface, signal_name): +        return dbus_message_is_signal(self.msg, interface, signal_name) + +    def is_error(self, error_name): +        return dbus_message_is_error(self.msg, error_name) + +    def has_destination(self, service): +        return dbus_message_has_destination(self.msg, service) + +    def has_sender(self, service): +        return dbus_message_has_sender(self.msg, service) + +    def get_serial(self): +        return dbus_message_get_serial(self.msg) + +    def set_reply_serial(self, reply_serial): +        return dbus_message_set_reply_serial(self.msg, reply_serial) + +    def get_reply_serial(self): +        return dbus_message_get_reply_serial(self.msg)     + +    #FIXME: dbus_message_get_path_decomposed +     +    # FIXME: all the different dbus_message_*args* methods + +class Signal(Message): +    def __init__(self, spath, sinterface, sname): +        Message.__init__(self, MESSAGE_TYPE_SIGNAL, path=spath, dbus_interface=sinterface, name=sname) + +class MethodCall(Message): +    def __init__(self, mpath, minterface, mmethod): +        Message.__init__(self, MESSAGE_TYPE_METHOD_CALL, path=mpath, dbus_interface=minterface, method=mmethod) + +class MethodReturn(Message): +    def __init__(self, method_call): +        Message.__init__(self, MESSAGE_TYPE_METHOD_RETURN, method_call=method_call) + +class Error(Message): +    def __init__(self, reply_to, error_name, error_message): +        Message.__init__(self, MESSAGE_TYPE_ERROR, reply_to=reply_to, error_name=error_name, error_message=error_message) +         +cdef class Server: +    cdef DBusServer *server +    def __init__(self, address): +        cdef DBusError error +        dbus_error_init(&error) +        self.server = dbus_server_listen(address, +                                         &error) +        if dbus_error_is_set(&error): +            raise DBusException, error.message + +    def disconnect(self): +        dbus_server_disconnect(self.server) + +    def get_is_connected(self): +        return dbus_server_get_is_connected(self.server) + +#    def set_new_connection_function(self, function, data): +#        dbus_server_set_new_connection_function(self.conn, function, +#                                                data, NULL) +         +#    def set_watch_functions(self, add_function, remove_function, data): +#        dbus_server_set_watch_functions(self.server, +#                                        add_function, remove_function, +#                                        data, NULL) +         +#    def set_timeout_functions(self, add_function, remove_function, data): +#        dbus_server_set_timeout_functions(self.server, +#                                          add_function, remove_function, +#                                          data, NULL) +         +#    def handle_watch(self, watch, condition): +#        dbus_server_handle_watch(self.conn, watch, condition) + +BUS_SESSION = DBUS_BUS_SESSION +BUS_SYSTEM = DBUS_BUS_SYSTEM +BUS_STARTER = DBUS_BUS_STARTER + +def bus_get (bus_type): +    cdef DBusError error +    cdef Connection conn +    dbus_error_init(&error) +    cdef DBusConnection *connection + +    connection = dbus_bus_get(bus_type, +                              &error) + +    if dbus_error_is_set(&error): +        raise DBusException, error.message + +    conn = Connection() +    conn.__cinit__(None, connection) +    return conn  + +def bus_get_unique_name(Connection connection): +    cdef DBusConnection *conn +    conn = connection._get_conn() +    return dbus_bus_get_unique_name(conn) + +def bus_get_unix_user(Connection connection, service_name): +    cdef DBusError error +    dbus_error_init(&error) +    cdef int retval +    cdef DBusConnection *conn + +    conn = connection._get_conn() +    retval = dbus_bus_get_unix_user(conn, service_name, &error) + +    if dbus_error_is_set(&error): +        raise DBusException, error.message +    return retval + +#These are defines, not enums so they aren't auto generated +DBUS_START_REPLY_SUCCESS = 0  +DBUS_START_REPLY_ALREADY_RUNNING = 1  +     +def bus_start_service_by_name(Connection connection, service_name, flags=0): +    cdef DBusError error +    dbus_error_init(&error) +    cdef dbus_bool_t retval +    cdef dbus_uint32_t results +    cdef DBusConnection *conn + +    conn = connection._get_conn() + +    retval = dbus_bus_start_service_by_name(conn, service_name, flags, &results, &error) + +    return (retval, results)  + +def bus_register(Connection connection): +    cdef DBusError error +    dbus_error_init(&error) +    cdef dbus_bool_t retval +    cdef DBusConnection *conn + +    conn = connection._get_conn() +    retval = dbus_bus_register(conn, +                               &error) +    if dbus_error_is_set(&error): +        raise DBusException, error.message + +    return retval + +SERVICE_FLAG_PROHIBIT_REPLACEMENT = 0x1 +SERVICE_FLAG_REPLACE_EXISTING     = 0x2 + +def bus_request_name(Connection connection, service_name, flags=0): +    cdef DBusError error +    dbus_error_init(&error) +    cdef int retval +    cdef DBusConnection *conn + +    conn = connection._get_conn() +    retval = dbus_bus_request_name(conn, +                                   service_name, +                                   flags, +                                   &error) +    if dbus_error_is_set(&error): +        raise DBusException, error.message +    return retval +     +def bus_name_has_owner(Connection connection, service_name): +    cdef DBusError error +    dbus_error_init(&error) +    cdef dbus_bool_t retval +    cdef DBusConnection *conn + +    conn = connection._get_conn() +    retval = dbus_bus_name_has_owner(conn, +                                     service_name, +                                     &error) +    if dbus_error_is_set(&error): +        raise DBusException, error.message +    return retval + +def bus_add_match(Connection connection, rule): +    cdef DBusError error +    cdef DBusConnection *conn + +    dbus_error_init(&error) +     +    conn = connection._get_conn() +    dbus_bus_add_match (conn, rule, &error) +     +    if dbus_error_is_set(&error): +        raise DBusException, error.message + +def bus_remove_match(Connection connection, rule): +    cdef DBusError error +    cdef DBusConnection *conn + +    dbus_error_init(&error) + +    conn = connection._get_conn() +    dbus_bus_remove_match (conn, rule, &error) +     +    if dbus_error_is_set(&error): +        raise DBusException, error.message +  | 
