From d06bfe528bb8d5e2ad2b4844c36fe43155739b3d Mon Sep 17 00:00:00 2001 From: "John (J5) Palmieri" Date: Tue, 12 Jul 2005 18:16:07 +0000 Subject: * python/dbus_bindings.pyx.in: removed * python/dbus_bindings.pyx: Added. - Fixed some memleaks (patch from Sean Meiners ) - Broke out the #include "dbus_h_wrapper.h" and put it in its own pxd file (Pyrex definition) - Broke out glib dependancies into its own pyx module * python/dbus_bindings.pdx: Added. - Defines C class Connection for exporting to other modules * python/dbus_glib_bindings.pyx: Added. - New module to handle lowlevel dbus-glib mainloop integration * python/glib.py: Added. - Registers the glib mainloop when you import this module * python/services.py: Removed (renamed to service.py) * python/service.py: Added. - (class Server): renamed Name * python/__init__.py: Bump ro version (0,41,0) - don't import the decorators or service module by default. These now reside in the dbus.service namespace * python/_dbus.py (Bus::__init__): Add code run the main loop setup function on creation * python/examples/example-service.py, python/examples/example-signal-emitter.py: update examples * python/examples/gconf-proxy-service.py, python/examples/gconf-proxy-service2.py: TODO fix these up * doc/TODO: Addition - Added a Python Bindings 1.0 section - added "Add match on args or match on details to match rules" --- ChangeLog | 42 + doc/TODO | 13 + python/Makefile.am | 34 +- python/__init__.py | 5 +- python/_dbus.py | 19 +- python/dbus_bindings.pxd.in | 8 + python/dbus_bindings.pyx | 1488 ++++++++++++++++++++++++++++ python/dbus_bindings.pyx.in | 1494 ----------------------------- python/dbus_glib_bindings.pyx | 19 + python/examples/example-service.py | 19 +- python/examples/example-signal-emitter.py | 15 +- python/examples/gconf-proxy-service.py | 2 +- python/examples/gconf-proxy-service2.py | 2 +- python/glib.py | 15 + python/service.py | 187 ++++ python/services.py | 187 ---- 16 files changed, 1826 insertions(+), 1723 deletions(-) create mode 100644 python/dbus_bindings.pxd.in create mode 100644 python/dbus_bindings.pyx delete mode 100644 python/dbus_bindings.pyx.in create mode 100644 python/dbus_glib_bindings.pyx create mode 100644 python/glib.py create mode 100644 python/service.py delete mode 100644 python/services.py diff --git a/ChangeLog b/ChangeLog index 97c64178..01fbb957 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,45 @@ +2005-07-12 John (J5) Palmieri + * python/dbus_bindings.pyx.in: removed + + * python/dbus_bindings.pyx: Added. + - Fixed some memleaks (patch from + Sean Meiners ) + - Broke out the #include "dbus_h_wrapper.h" and put it in its + own pxd file (Pyrex definition) + - Broke out glib dependancies into its own pyx module + + * python/dbus_bindings.pdx: Added. + - Defines C class Connection for exporting to other modules + + * python/dbus_glib_bindings.pyx: Added. + - New module to handle lowlevel dbus-glib mainloop integration + + * python/glib.py: Added. + - Registers the glib mainloop when you import this module + + * python/services.py: Removed (renamed to service.py) + + * python/service.py: Added. + - (class Server): renamed Name + + * python/__init__.py: Bump ro version (0,41,0) + -don't import the decorators or service module + by default. These now reside in the dbus.service namespace + + * python/_dbus.py (Bus::__init__): Add code run the main loop + setup function on creation + + * python/examples/example-service.py, + python/examples/example-signal-emitter.py: update examples + + * python/examples/gconf-proxy-service.py, + python/examples/gconf-proxy-service2.py: TODO fix these up + + * doc/TODO: Addition + - Added a Python Bindings 1.0 section + - added "Add match on args or match on details to match rules" + + 2005-07-12 Colin Walters * glib/examples/statemachine/Makefile.am (statemachine-server-glue.h) diff --git a/doc/TODO b/doc/TODO index 38fbe57c..03e156dc 100644 --- a/doc/TODO +++ b/doc/TODO @@ -25,6 +25,8 @@ Important for 1.0 - Add a test case for handling the Ping message + - Add match on args or match on details to match rules + Important for 1.0 GLib Bindings === @@ -32,6 +34,17 @@ Important for 1.0 GLib Bindings - Add support for getting sender +Important for 1.0 Python bindings +=== + + - Hammer down API + + - Fix removing of signals from the match tree + + - Fix refcounting and userdata lifecycles + + - Write a generic mainloop + Might as Well for 1.0 === diff --git a/python/Makefile.am b/python/Makefile.am index b5ee4243..81a8367a 100644 --- a/python/Makefile.am +++ b/python/Makefile.am @@ -1,30 +1,42 @@ SUBDIRS=examples -INCLUDES=-I$(top_builddir) -I$(top_builddir)/dbus $(DBUS_CLIENT_CFLAGS) $(DBUS_GLIB_CFLAGS) $(DBUS_GLIB_TOOL_CFLAGS) $(PYTHON_INCLUDES) -DDBUS_COMPILATION=1 +INCLUDES=-I$(top_builddir) -I$(top_builddir)/dbus $(DBUS_CLIENT_CFLAGS) $(PYTHON_INCLUDES) -DDBUS_COMPILATION=1 dbusdir = $(pythondir)/dbus -dbus_PYTHON = __init__.py _dbus.py decorators.py exceptions.py services.py proxies.py _util.py types.py matchrules.py +dbus_PYTHON = __init__.py _dbus.py decorators.py exceptions.py service.py proxies.py _util.py types.py matchrules.py glib.py dbusbindingsdir = $(pyexecdir)/dbus -dbusbindings_LTLIBRARIES = dbus_bindings.la +dbusbindings_LTLIBRARIES = dbus_bindings.la dbus_glib_bindings.la dbus_bindings_la_LDFLAGS = -module -avoid-version -fPIC -export-symbols-regex initdbus_bindings -dbus_bindings_la_LIBADD = $(top_builddir)/dbus/libdbus-1.la $(top_builddir)/glib/libdbus-glib-1.la +dbus_bindings_la_LIBADD = $(top_builddir)/dbus/libdbus-1.la nodist_dbus_bindings_la_SOURCES = dbus_bindings.c +dbus_glib_bindings_la_LDFLAGS = -module -avoid-version -fPIC -export-symbols-regex initdbus_glib_bindings +dbus_glib_bindings_la_LIBADD = $(top_builddir)/dbus/libdbus-1.la $(top_builddir)/glib/libdbus-glib-1.la +dbus_glib_bindings_la_CFLAGS = $(DBUS_GLIB_CFLAGS) $(DBUS_GLIB_TOOL_CFLAGS) +nodist_dbus_glib_bindings_la_SOURCES = dbus_glib_bindings.c + EXTRA_DIST = \ dbus_h_wrapper.h \ - dbus_bindings.pyx.in \ + dbus_bindings.pyx \ + dbus_glib_bindings.pyx \ + dbus_bindings.pxd \ extract.py CLEANFILES = \ - dbus_bindings.pyx \ - dbus_bindings.c + dbus_bindings.pxd \ + dbus_bindings.c \ + dbus_glib_bindings.c + +dbus_bindings.pxd: dbus_bindings.pxd.in extract.py + -$(PYTHON) extract.py dbus_bindings.pxd.in -I$(top_builddir) > dbus_bindings.pxd -dbus_bindings.pyx: dbus_bindings.pyx.in extract.py - -$(PYTHON) extract.py dbus_bindings.pyx.in -I$(top_builddir) > dbus_bindings.pyx +dbus_bindings.c: dbus_bindings.pyx dbus_bindings.pxd + -pyrexc dbus_bindings.pyx -dbus_bindings.c: dbus_bindings.pyx - -pyrexc dbus_bindings.pyx +dbus_glib_bindings.c: dbus_glib_bindings.pyx dbus_bindings.pxd + -pyrexc dbus_glib_bindings.pyx + diff --git a/python/__init__.py b/python/__init__.py index ebeb4208..069a432b 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -1,6 +1,5 @@ from _dbus import * -from decorators import * -from services import * from types import * -version = (0, 40, 2) +version = (0, 41, 0) +_dbus_main_loop_setup_function = None diff --git a/python/_dbus.py b/python/_dbus.py index d559ce18..d52aa8fc 100644 --- a/python/_dbus.py +++ b/python/_dbus.py @@ -42,7 +42,8 @@ print(dbus_object.ListServices()) """ import dbus_bindings -from decorators import * + +import dbus from proxies import * from exceptions import * from services import * @@ -51,13 +52,6 @@ from matchrules import * import re import inspect -_threads_initialized = 0 -def init_gthreads (): - global _threads_initialized - if not _threads_initialized: - dbus_bindings.init_gthreads () - _threads_initialized = 1 - class Bus: """A connection to a DBus daemon. @@ -76,13 +70,16 @@ class Bus: START_REPLY_SUCCESS = dbus_bindings.DBUS_START_REPLY_SUCCESS START_REPLY_ALREADY_RUNNING = dbus_bindings.DBUS_START_REPLY_ALREADY_RUNNING - def __init__(self, bus_type=TYPE_SESSION, glib_mainloop=True): + def __init__(self, bus_type=TYPE_SESSION, use_default_mainloop=True): self._connection = dbus_bindings.bus_get(bus_type) self._connection.add_filter(self._signal_func) self._match_rule_tree = SignalMatchTree() - if (glib_mainloop): - self._connection.setup_with_g_main() + + if use_default_mainloop: + func = getattr(dbus, "_dbus_mainloop_setup_function", None) + if func != None: + func(self) def get_connection(self): return self._connection diff --git a/python/dbus_bindings.pxd.in b/python/dbus_bindings.pxd.in new file mode 100644 index 00000000..f1707208 --- /dev/null +++ b/python/dbus_bindings.pxd.in @@ -0,0 +1,8 @@ +#include "dbus_h_wrapper.h" + +cdef class Connection: + cdef DBusConnection *conn + + cdef __cinit__(self, address, DBusConnection *_conn) + cdef _set_conn(self, DBusConnection *conn) + cdef DBusConnection *_get_conn(self) 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 = 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 = 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, + 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, + 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, + 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) = 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 = 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, + 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, &c_val) + return c_val + + def get_boolean(self): + cdef dbus_bool_t c_val + dbus_message_iter_get_basic(self.iter, &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, &c_val) + return c_val + + def get_uint16(self): + cdef dbus_uint16_t c_val + dbus_message_iter_get_basic(self.iter, &c_val) + return c_val + + def get_int32(self): + cdef dbus_int32_t c_val + dbus_message_iter_get_basic(self.iter, &c_val) + return c_val + + def get_uint32(self): + cdef dbus_uint32_t c_val + dbus_message_iter_get_basic(self.iter, &c_val) + return c_val + + def get_int64(self): + cdef dbus_int64_t c_val + dbus_message_iter_get_basic(self.iter, &c_val) + return c_val + + def get_uint64(self): + cdef dbus_uint64_t c_val + dbus_message_iter_get_basic(self.iter, &c_val) + return c_val + + def get_double(self): + cdef double c_val + dbus_message_iter_get_basic(self.iter, &c_val) + return c_val + + def get_string(self): + cdef char *c_str + dbus_message_iter_get_basic(self.iter, &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, &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, &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, &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, &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, &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, &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, &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, &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, &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, &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, &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, &c_value) + + def append_double(self, value): + cdef double c_value + c_value = value + return dbus_message_iter_append_basic(self.iter, TYPE_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, &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, &c_value) + + def append_signature(self, value): + cdef char *c_value + c_value = value + return dbus_message_iter_append_basic(self.iter, TYPE_SIGNATURE, &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, &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, &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, &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, &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, &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 + diff --git a/python/dbus_bindings.pyx.in b/python/dbus_bindings.pyx.in deleted file mode 100644 index 34341c4a..00000000 --- a/python/dbus_bindings.pyx.in +++ /dev/null @@ -1,1494 +0,0 @@ -# -*- 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 - -#include "dbus_h_wrapper.h" - -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 "dbus-glib.h": - ctypedef struct GMainContext - cdef void dbus_connection_setup_with_g_main (DBusConnection *connection, - GMainContext *context) - cdef void dbus_server_setup_with_g_main (DBusServer *server, - GMainContext *context) - cdef void dbus_g_thread_init () - -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 Connection -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 = 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 = 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: - cdef DBusConnection *conn - - def __init__(self, address=None, Connection _conn=None): - cdef DBusConnection *c_conn - cdef char *c_address - c_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 - - - 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 setup_with_g_main(self): - dbus_connection_setup_with_g_main(self.conn, NULL) - - 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, - 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, - 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, - 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) = 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 = data - Py_XDECREF(call_tuple) - -cdef class PendingCall: - cdef DBusPendingCall *pending_call - - def __init__(self, PendingCall _pending_call=None): - 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) - - 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, - 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, &c_val) - return c_val - - def get_boolean(self): - cdef dbus_bool_t c_val - dbus_message_iter_get_basic(self.iter, &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, &c_val) - return c_val - - def get_uint16(self): - cdef dbus_uint16_t c_val - dbus_message_iter_get_basic(self.iter, &c_val) - return c_val - - def get_int32(self): - cdef dbus_int32_t c_val - dbus_message_iter_get_basic(self.iter, &c_val) - return c_val - - def get_uint32(self): - cdef dbus_uint32_t c_val - dbus_message_iter_get_basic(self.iter, &c_val) - return c_val - - def get_int64(self): - cdef dbus_int64_t c_val - dbus_message_iter_get_basic(self.iter, &c_val) - return c_val - - def get_uint64(self): - cdef dbus_uint64_t c_val - dbus_message_iter_get_basic(self.iter, &c_val) - return c_val - - def get_double(self): - cdef double c_val - dbus_message_iter_get_basic(self.iter, &c_val) - return c_val - - def get_string(self): - cdef char *c_str - dbus_message_iter_get_basic(self.iter, &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, &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, &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, &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, &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, &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, &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, &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, &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, &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, &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, &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, &c_value) - - def append_double(self, value): - cdef double c_value - c_value = value - return dbus_message_iter_append_basic(self.iter, TYPE_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, &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, &c_value) - - def append_signature(self, value): - cdef char *c_value - c_value = value - return dbus_message_iter_append_basic(self.iter, TYPE_SIGNATURE, &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, &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, &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, &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, &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, &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): - - 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 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 setup_with_g_main (self): - dbus_server_setup_with_g_main(self.server, NULL) - - 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 - -def init_gthreads (): - dbus_g_thread_init () diff --git a/python/dbus_glib_bindings.pyx b/python/dbus_glib_bindings.pyx new file mode 100644 index 00000000..314fadad --- /dev/null +++ b/python/dbus_glib_bindings.pyx @@ -0,0 +1,19 @@ +cdef extern from "dbus.h": + ctypedef struct DBusConnection + +cdef extern from "dbus-glib.h": + ctypedef struct GMainContext + cdef void dbus_connection_setup_with_g_main (DBusConnection *connection, + GMainContext *context) + cdef void dbus_g_thread_init () + +cimport dbus_bindings +import dbus_bindings + +def setup_with_g_main(conn): + cdef dbus_bindings.Connection connection + connection = conn + dbus_connection_setup_with_g_main(connection._get_conn(), NULL) + +def init_gthreads (): + dbus_g_thread_init () diff --git a/python/examples/example-service.py b/python/examples/example-service.py index 9963454f..9e2f193b 100644 --- a/python/examples/example-service.py +++ b/python/examples/example-service.py @@ -1,29 +1,32 @@ #!/usr/bin/env python import dbus +import dbus.service + +import dbus.glib import pygtk import gtk -class SomeObject(dbus.Object): - def __init__(self, service): - dbus.Object.__init__(self, "/SomeObject", service) +class SomeObject(dbus.service.Object): + def __init__(self, name): + dbus.service.Object.__init__(self, "/SomeObject", name) - @dbus.method("org.designfu.SampleInterface") + @dbus.service.method("org.designfu.SampleInterface") def HelloWorld(self, hello_message): print (str(hello_message)) return ["Hello", " from example-service.py"] - @dbus.method("org.designfu.SampleInterface") + @dbus.service.method("org.designfu.SampleInterface") def GetTuple(self): return ("Hello Tuple", " from example-service.py") - @dbus.method("org.designfu.SampleInterface") + @dbus.service.method("org.designfu.SampleInterface") def GetDict(self): return {"first": "Hello Dict", "second": " from example-service.py"} session_bus = dbus.SessionBus() -service = dbus.Service("org.designfu.SampleService", bus=session_bus) -object = SomeObject(service) +name = dbus.service.Name("org.designfu.SampleService", bus=session_bus) +object = SomeObject(name) gtk.main() diff --git a/python/examples/example-signal-emitter.py b/python/examples/example-signal-emitter.py index 428f1440..64c7f177 100644 --- a/python/examples/example-signal-emitter.py +++ b/python/examples/example-signal-emitter.py @@ -1,26 +1,27 @@ #!/usr/bin/env python import dbus +import dbus.service import gtk -class TestObject(dbus.Object): - def __init__(self, service): - dbus.Object.__init__(self, "/org/designfu/TestService/object", service) +class TestObject(dbus.service.Object): + def __init__(self, name): + dbus.service.Object.__init__(self, "/org/designfu/TestService/object", name) - @dbus.signal('org.designfu.TestService') + @dbus.service.signal('org.designfu.TestService') def HelloSignal(self, message): # The signal is emitted when this method exits # You can have code here if you wish pass - @dbus.method('org.designfu.TestService') + @dbus.service.method('org.designfu.TestService') def emitHelloSignal(self): #you emit signals by calling the signal's skeleton method self.HelloSignal("Hello") return "Signal emitted" session_bus = dbus.SessionBus() -service = dbus.Service("org.designfu.TestService", bus=session_bus) -object = TestObject(service) +name = dbus.service.Name("org.designfu.TestService", bus=session_bus) +object = TestObject(name) gtk.main() diff --git a/python/examples/gconf-proxy-service.py b/python/examples/gconf-proxy-service.py index 18c8047f..b9bdef14 100644 --- a/python/examples/gconf-proxy-service.py +++ b/python/examples/gconf-proxy-service.py @@ -1,5 +1,5 @@ #!/usr/bin/env python - +#FIXME: Doesn't work with the new bindings import dbus import gtk diff --git a/python/examples/gconf-proxy-service2.py b/python/examples/gconf-proxy-service2.py index 3667a853..ba8d249b 100644 --- a/python/examples/gconf-proxy-service2.py +++ b/python/examples/gconf-proxy-service2.py @@ -1,5 +1,5 @@ #!/usr/bin/env python - +#FIXME: doesn't work with the new bindings import dbus import gtk diff --git a/python/glib.py b/python/glib.py new file mode 100644 index 00000000..8e781422 --- /dev/null +++ b/python/glib.py @@ -0,0 +1,15 @@ +import dbus +import dbus_glib_bindings + +def _setup_with_g_main(conn): + dbus_glib_bindings.setup_with_g_main(conn._connection) + +_dbus_gthreads_initialized = False +def init_threads(): + global _dbus_gthreads_initialized + if not _dbus_gthreads_initialized: + dbus_glib_bindings.init_gthreads () + _dbus_gthreads_initialized = True + + +setattr(dbus, "_dbus_mainloop_setup_function", _setup_with_g_main) diff --git a/python/service.py b/python/service.py new file mode 100644 index 00000000..fc044af0 --- /dev/null +++ b/python/service.py @@ -0,0 +1,187 @@ +from decorators import * + +import dbus_bindings + +class Name: + """A base class for exporting your own Named Services across the Bus + + Just inherit from Name, providing the name of your service + (e.g. org.designfu.SampleService). + """ + def __init__(self, named_service, bus=None): + self._named_service = named_service + + if bus == None: + # Get the default bus + self._bus = Bus() + else: + self._bus = bus + + dbus_bindings.bus_request_name(self._bus.get_connection(), named_service) + + def get_bus(self): + """Get the Bus this Service is on""" + return self._bus + + def get_name(self): + """Get the name of this service""" + return self._named_service + +def _dispatch_dbus_method_call(target_methods, self, argument_list, message): + """Calls method_to_call using argument_list, but handles + exceptions, etc, and generates a reply to the DBus Message message + """ + try: + target_method = None + + dbus_interface = message.get_interface() + if dbus_interface == None: + if target_methods: + target_method = target_methods[0] + else: + for dbus_method in target_methods: + if dbus_method._dbus_interface == dbus_interface: + target_method = dbus_method + break + + if target_method: + retval = target_method(self, *argument_list) + else: + if not dbus_interface: + raise UnknownMethodException('%s is not a valid method'%(message.get_member())) + else: + raise UnknownMethodException('%s is not a valid method of interface %s'%(message.get_member(), dbus_interface)) + except Exception, e: + if e.__module__ == '__main__': + # FIXME: is it right to use .__name__ here? + error_name = e.__class__.__name__ + else: + error_name = e.__module__ + '.' + str(e.__class__.__name__) + error_contents = str(e) + reply = dbus_bindings.Error(message, error_name, error_contents) + else: + reply = dbus_bindings.MethodReturn(message) + if retval != None: + iter = reply.get_iter(append=True) + iter.append(retval) + + return reply + +class ObjectType(type): + def __init__(cls, name, bases, dct): + + #generate out vtable + method_vtable = getattr(cls, '_dbus_method_vtable', {}) + reflection_data = getattr(cls, '_dbus_reflection_data', "") + + reflection_interface_method_hash = {} + reflection_interface_signal_hash = {} + + for func in dct.values(): + if getattr(func, '_dbus_is_method', False): + if method_vtable.has_key(func.__name__): + method_vtable[func.__name__].append(func) + else: + method_vtable[func.__name__] = [func] + + #generate a hash of interfaces so we can group + #methods in the xml data + if reflection_interface_method_hash.has_key(func._dbus_interface): + reflection_interface_method_hash[func._dbus_interface].append(func) + else: + reflection_interface_method_hash[func._dbus_interface] = [func] + + elif getattr(func, '_dbus_is_signal', False): + if reflection_interface_signal_hash.has_key(func._dbus_interface): + reflection_interface_signal_hash[func._dbus_interface].append(func) + else: + reflection_interface_signal_hash[func._dbus_interface] = [func] + + for interface in reflection_interface_method_hash.keys(): + reflection_data = reflection_data + ' \n'%(interface) + for func in reflection_interface_method_hash[interface]: + reflection_data = reflection_data + cls._reflect_on_method(func) + + if reflection_interface_signal_hash.has_key(interface): + for func in reflection_interface_signal_hash[interface]: + reflection_data = reflection_data + cls._reflect_on_signal(func) + + del reflection_interface_signal_hash[interface] + + reflection_data = reflection_data + ' \n' + + for interface in reflection_interface_signal_hash.keys(): + reflection_data = reflection_data + ' \n'%(interface) + + for func in reflection_interface_signal_hash[interface]: + reflection_data = reflection_data + cls._reflect_on_signal(func) + + reflection_data = reflection_data + ' \n' + + cls._dbus_reflection_data = reflection_data + cls._dbus_method_vtable = method_vtable + + super(ObjectType, cls).__init__(name, bases, dct) + + #reflections on methods and signals may look like similar code but may in fact + #diverge in the future so keep them seperate + def _reflect_on_method(cls, func): + reflection_data = ' \n'%(func.__name__) + for arg in func._dbus_args: + reflection_data = reflection_data + ' \n'%(arg) + + #reclaim some memory + func._dbus_args = None + reflection_data = reflection_data + ' \n' + + return reflection_data + + def _reflect_on_signal(cls, func): + reflection_data = ' \n'%(func.__name__) + for arg in func._dbus_args: + reflection_data = reflection_data + ' \n'%(arg) + #reclaim some memory + func._dbus_args = None + reflection_data = reflection_data + ' \n' + + return reflection_data + +class Object: + """A base class for exporting your own Objects across the Bus. + + Just inherit from Object and provide a list of methods to share + across the Bus. These will appear as member functions of your + ServiceObject. + """ + __metaclass__ = ObjectType + + def __init__(self, object_path, name): + self._object_path = object_path + self._name = name + self._bus = name.get_bus() + + self._connection = self._bus.get_connection() + + self._connection.register_object_path(object_path, self._unregister_cb, self._message_cb) + + def _unregister_cb(self, connection): + print ("Unregister") + + def _message_cb(self, connection, message): + target_method_name = message.get_member() + target_methods = self._dbus_method_vtable[target_method_name] + args = message.get_args_list() + + reply = _dispatch_dbus_method_call(target_methods, self, args, message) + + self._connection.send(reply) + + @method('org.freedesktop.DBus.Introspectable') + def Introspect(self): + reflection_data = '\n' + reflection_data = reflection_data + '\n'%(self._object_path) + reflection_data = reflection_data + self._dbus_reflection_data + reflection_data = reflection_data + '\n' + + return reflection_data + diff --git a/python/services.py b/python/services.py deleted file mode 100644 index 7e0b58b7..00000000 --- a/python/services.py +++ /dev/null @@ -1,187 +0,0 @@ -from decorators import * - -import dbus_bindings - -class Service: - """A base class for exporting your own Services across the Bus - - Just inherit from Service, providing the name of your service - (e.g. org.designfu.SampleService). - """ - def __init__(self, named_service, bus=None): - self._named_service = named_service - - if bus == None: - # Get the default bus - self._bus = Bus() - else: - self._bus = bus - - dbus_bindings.bus_request_name(self._bus.get_connection(), named_service) - - def get_bus(self): - """Get the Bus this Service is on""" - return self._bus - - def get_name(self): - """Get the name of this service""" - return self._named_service - -def _dispatch_dbus_method_call(target_methods, self, argument_list, message): - """Calls method_to_call using argument_list, but handles - exceptions, etc, and generates a reply to the DBus Message message - """ - try: - target_method = None - - dbus_interface = message.get_interface() - if dbus_interface == None: - if target_methods: - target_method = target_methods[0] - else: - for dbus_method in target_methods: - if dbus_method._dbus_interface == dbus_interface: - target_method = dbus_method - break - - if target_method: - retval = target_method(self, *argument_list) - else: - if not dbus_interface: - raise UnknownMethodException('%s is not a valid method'%(message.get_member())) - else: - raise UnknownMethodException('%s is not a valid method of interface %s'%(message.get_member(), dbus_interface)) - except Exception, e: - if e.__module__ == '__main__': - # FIXME: is it right to use .__name__ here? - error_name = e.__class__.__name__ - else: - error_name = e.__module__ + '.' + str(e.__class__.__name__) - error_contents = str(e) - reply = dbus_bindings.Error(message, error_name, error_contents) - else: - reply = dbus_bindings.MethodReturn(message) - if retval != None: - iter = reply.get_iter(append=True) - iter.append(retval) - - return reply - -class ObjectType(type): - def __init__(cls, name, bases, dct): - - #generate out vtable - method_vtable = getattr(cls, '_dbus_method_vtable', {}) - reflection_data = getattr(cls, '_dbus_reflection_data', "") - - reflection_interface_method_hash = {} - reflection_interface_signal_hash = {} - - for func in dct.values(): - if getattr(func, '_dbus_is_method', False): - if method_vtable.has_key(func.__name__): - method_vtable[func.__name__].append(func) - else: - method_vtable[func.__name__] = [func] - - #generate a hash of interfaces so we can group - #methods in the xml data - if reflection_interface_method_hash.has_key(func._dbus_interface): - reflection_interface_method_hash[func._dbus_interface].append(func) - else: - reflection_interface_method_hash[func._dbus_interface] = [func] - - elif getattr(func, '_dbus_is_signal', False): - if reflection_interface_signal_hash.has_key(func._dbus_interface): - reflection_interface_signal_hash[func._dbus_interface].append(func) - else: - reflection_interface_signal_hash[func._dbus_interface] = [func] - - for interface in reflection_interface_method_hash.keys(): - reflection_data = reflection_data + ' \n'%(interface) - for func in reflection_interface_method_hash[interface]: - reflection_data = reflection_data + cls._reflect_on_method(func) - - if reflection_interface_signal_hash.has_key(interface): - for func in reflection_interface_signal_hash[interface]: - reflection_data = reflection_data + cls._reflect_on_signal(func) - - del reflection_interface_signal_hash[interface] - - reflection_data = reflection_data + ' \n' - - for interface in reflection_interface_signal_hash.keys(): - reflection_data = reflection_data + ' \n'%(interface) - - for func in reflection_interface_signal_hash[interface]: - reflection_data = reflection_data + cls._reflect_on_signal(func) - - reflection_data = reflection_data + ' \n' - - cls._dbus_reflection_data = reflection_data - cls._dbus_method_vtable = method_vtable - - super(ObjectType, cls).__init__(name, bases, dct) - - #reflections on methods and signals may look like similar code but may in fact - #diverge in the future so keep them seperate - def _reflect_on_method(cls, func): - reflection_data = ' \n'%(func.__name__) - for arg in func._dbus_args: - reflection_data = reflection_data + ' \n'%(arg) - - #reclaim some memory - func._dbus_args = None - reflection_data = reflection_data + ' \n' - - return reflection_data - - def _reflect_on_signal(cls, func): - reflection_data = ' \n'%(func.__name__) - for arg in func._dbus_args: - reflection_data = reflection_data + ' \n'%(arg) - #reclaim some memory - func._dbus_args = None - reflection_data = reflection_data + ' \n' - - return reflection_data - -class Object: - """A base class for exporting your own Objects across the Bus. - - Just inherit from Object and provide a list of methods to share - across the Bus. These will appear as member functions of your - ServiceObject. - """ - __metaclass__ = ObjectType - - def __init__(self, object_path, service): - self._object_path = object_path - self._service = service - self._bus = service.get_bus() - - self._connection = self._bus.get_connection() - - self._connection.register_object_path(object_path, self._unregister_cb, self._message_cb) - - def _unregister_cb(self, connection): - print ("Unregister") - - def _message_cb(self, connection, message): - target_method_name = message.get_member() - target_methods = self._dbus_method_vtable[target_method_name] - args = message.get_args_list() - - reply = _dispatch_dbus_method_call(target_methods, self, args, message) - - self._connection.send(reply) - - @method('org.freedesktop.DBus.Introspectable') - def Introspect(self): - reflection_data = '\n' - reflection_data = reflection_data + '\n'%(self._object_path) - reflection_data = reflection_data + self._dbus_reflection_data - reflection_data = reflection_data + '\n' - - return reflection_data - -- cgit