3 #include "dbus_h_wrapper.h"
5 cdef extern from "stdlib.h":
6 cdef void *malloc(size_t size)
7 cdef void free(void *ptr)
9 cdef extern from "dbus-glib.h":
10 ctypedef struct GMainContext
11 cdef void dbus_connection_setup_with_g_main (DBusConnection *connection,
12 GMainContext *context)
13 cdef void dbus_server_setup_with_g_main (DBusServer *server,
14 GMainContext *context)
16 cdef extern from "Python.h":
17 void Py_XINCREF (object)
18 void Py_XDECREF (object)
21 ctypedef struct DBusError:
31 ctypedef struct DBusMessageIter:
47 ctypedef struct DBusObjectPathVTable:
48 DBusObjectPathUnregisterFunction unregister_function
49 DBusObjectPathMessageFunction message_function
50 void (* dbus_internal_pad1) (void *)
51 void (* dbus_internal_pad2) (void *)
52 void (* dbus_internal_pad3) (void *)
53 void (* dbus_internal_pad4) (void *)
56 _user_data_references = [ ]
58 class DBusException(Exception):
61 class ConnectionError(Exception):
64 cdef void cunregister_function_handler (DBusConnection *connection,
66 print ("cunregister_function_handler() called")
67 tup = <object>user_data
69 args = [Connection(_conn=<object>connection)]
72 cdef DBusHandlerResult cmessage_function_handler (DBusConnection *connection,
75 print ("cmessage_function_handler() called")
76 tup = <object>user_data
80 message = Message(_create=0)
81 message._set_msg(<object>msg)
82 args = [Connection(_conn=<object>connection),
84 retval = function(*args)
86 retval = DBUS_HANDLER_RESULT_HANDLED
89 cdef DBusHandlerResult chandle_message_function_handler (DBusConnection *connection,
92 function = <object>user_data
93 messagein = Message(_create=0)
94 messagein._set_msg(<object>msg)
95 args = [Connection(_conn=<object>connection),
97 retval = function(*args)
99 retval = DBUS_HANDLER_RESULT_HANDLED
102 cdef class Connection:
103 cdef DBusConnection *conn
105 # FIXME: this is a major major hack. We use this because casting values to
106 # python objects and returning seemed to be corrupting them. This is a "global variable" :-(
107 cdef char **_parsed_path
109 def __init__(self, address=None, _conn=None):
111 dbus_error_init(&error)
112 if <DBusConnection*>_conn != NULL:
113 self.conn = <DBusConnection*>_conn
114 dbus_connection_ref(self.conn)
116 self.conn = dbus_connection_open(address,
118 if dbus_error_is_set(&error):
119 raise DBusException, error.message
121 dbus_connection_ref(self.conn)
123 def _set_conn(self, conn):
124 self.conn = <DBusConnection*>conn
127 return <object>self.conn
129 #FIXME: this is totally busted, don't use a class shared member like parsed_path
130 def _build_parsed_path(self, path_element_list):
131 cdef char **cpatharray
132 size = len(path_element_list)
133 cpatharray = <char **>malloc(sizeof(char*) * (size + 1))
135 for i in range(size):
136 path_element = path_element_list[i]
137 cpatharray[i] = path_element
139 cpatharray[size] = NULL
141 self._parsed_path = cpatharray
143 def get_base_service(self):
144 return bus_get_base_service(self)
146 def setup_with_g_main(self):
147 dbus_connection_setup_with_g_main(self.conn, NULL)
149 def disconnect(self):
150 dbus_connection_disconnect(self.conn)
152 def get_is_connected(self):
153 return dbus_connection_get_is_connected(self.conn)
155 def get_is_authenticated(self):
156 return dbus_connection_get_is_authenticated(self.conn)
159 dbus_connection_flush(self.conn)
161 def borrow_message(self):
162 m = Message(_create=0)
163 m._set_msg(<object>dbus_connection_borrow_message(self.conn))
166 def return_message(self, message):
167 msg = message._get_msg()
168 dbus_connection_return_message(self.conn, <DBusMessage*>msg)
170 def steal_borrowed_message(self, message):
171 msg = message._get_msg()
172 dbus_connection_steal_borrowed_message(self.conn,
175 def pop_message(self):
176 cdef DBusMessage *msg
177 msg = dbus_connection_pop_message(self.conn)
179 m = Message(_create=0)
180 m._set_msg(<object>msg)
185 def get_dispatch_status(self):
186 return dbus_connection_get_dispatch_status(self.conn)
189 return dbus_connection_dispatch(self.conn)
191 def send(self, message):
192 #cdef dbus_uint32_t client_serial
193 #if type(message) != Message:
196 msg = message._get_msg()
197 retval = dbus_connection_send(self.conn,
202 def send_with_reply(self, message, timeout_milliseconds):
203 cdef dbus_bool_t retval
204 cdef DBusPendingCall *cpending_call
206 dbus_error_init(&error)
210 msg = message._get_msg()
212 retval = dbus_connection_send_with_reply(self.conn,
215 timeout_milliseconds)
217 if dbus_error_is_set(&error):
218 raise DBusException, error.message
220 if (cpending_call != NULL):
221 pending_call = PendingCall(<object>cpending_call)
225 return (retval, pending_call)
227 def send_with_reply_and_block(self, message,
228 timeout_milliseconds=0):
229 cdef DBusMessage * retval
231 dbus_error_init(&error)
233 msg = message._get_msg()
235 print ("About to block")
237 retval = dbus_connection_send_with_reply_and_block(
238 <DBusConnection*>self.conn,
240 <int>timeout_milliseconds,
245 if dbus_error_is_set(&error):
246 raise DBusException, error.message
251 m = Message(_create=0)
252 m._set_msg(<object>retval)
255 def set_watch_functions(self, add_function, remove_function, data):
258 def set_timeout_functions(self, add_function, remove_function, data):
261 def set_wakeup_main_function(self, wakeup_main_function, data):
264 # FIXME: set_dispatch_status_function, get_unix_user, set_unix_user_function
266 def add_filter(self, function):
267 return dbus_connection_add_filter(self.conn,
268 chandle_message_function_handler,
273 #FIXME: remove_filter
274 # this is pretty tricky, we want to only remove the filter
275 # if we truly have no more calls to our message_function_handler...ugh
277 def set_data(self, slot, data):
280 def get_data(self, slot):
283 def set_max_message_size(self, size):
284 dbus_connection_set_max_message_size(self.conn, size)
286 def get_max_message_size(self):
287 return dbus_connection_get_max_message_size(self.conn)
289 def set_max_received_size(self, size):
290 dbus_connection_set_max_received_size(self.conn, size)
292 def get_max_received_size(self):
293 return dbus_connection_get_max_received_size(self.conn)
295 def get_outgoing_size(self):
296 return dbus_connection_get_outgoing_size(self.conn)
298 # preallocate_send, free_preallocated_send, send_preallocated
300 def register_object_path(self, path, unregister_cb, message_cb):
301 cdef DBusObjectPathVTable cvtable
303 cvtable.unregister_function = cunregister_function_handler
304 cvtable.message_function = cmessage_function_handler
306 user_data = [unregister_cb, message_cb]
307 global _user_data_references
308 _user_data_references.append(user_data)
310 path_element_list = path[1:].split('/')
311 self._build_parsed_path(path_element_list)
313 return dbus_connection_register_object_path(self.conn, self._parsed_path, &cvtable,
316 def register_fallback(self, path, unregister_cb, message_cb):
317 cdef DBusObjectPathVTable cvtable
319 cvtable.unregister_function = cunregister_function_handler
320 cvtable.message_function = cmessage_function_handler
322 user_data = [unregister_cb, message_cb]
323 global _user_data_references
324 _user_data_references.append(user_data)
326 path_element_list = path[1:].split('/')
327 self._build_parsed_path(path_element_list)
329 return dbus_connection_register_fallback(self.conn, self._parsed_path, &cvtable,
332 #FIXME: unregister_object_path , see problems with remove_filter
334 def list_registered (self, parent_path):
335 cdef char **cchild_entries
336 cdef dbus_bool_t retval
338 path_element_list = parent_path[1:].split('/')
339 self._build_parsed_path(path_element_list)
341 retval = dbus_connection_list_registered(self.conn, self._parsed_path, &cchild_entries)
344 #FIXME: raise out of memory exception?
349 print ("cchild_entries[0] is %d" % (<int>cchild_entries[0]))
350 while (cchild_entries[i] != NULL):
351 child_entries.append(cchild_entries[i])
354 dbus_free_string_array(cchild_entries)
359 cdef class PendingCall:
360 cdef DBusPendingCall *pending_call
362 def __init__(self, _pending_call):
363 self.pending_call = <DBusPendingCall*>_pending_call
364 dbus_pending_call_ref(self.pending_call)
366 def _get_pending_call(self):
367 return <object>self.pending_call
370 dbus_pending_call_cancel(self.pending_call)
372 def get_completed(self):
373 return dbus_pending_call_get_completed(self.pending_call)
376 message = Message(_create=0)
377 message._set_msg(<object>dbus_pending_call_get_reply(self.pending_call))
381 dbus_pending_call_block(self.pending_call)
384 cdef DBusWatch* watch
385 def __init__(self, cwatch):
386 self.watch = <DBusWatch*>cwatch
389 return dbus_watch_get_fd(self.watch)
391 # FIXME: not picked up correctly by extract.py
392 #def get_flags(self):
393 # return dbus_watch_get_flags(self.watch)
395 def handle(self, flags):
396 return dbus_watch_handle(self.watch, flags)
398 def get_enabled(self):
399 return dbus_watch_get_enabled(self.watch)
401 cdef class MessageIter:
402 cdef DBusMessageIter *iter
403 cdef DBusMessageIter real_iter
406 def __init__(self, message):
407 self.iter = &self.real_iter
408 msg = message._get_msg()
409 dbus_message_iter_init(<DBusMessage*>msg, self.iter)
412 return <object>self.iter
415 return dbus_message_iter_has_next(self.iter)
418 return dbus_message_iter_next(self.iter)
421 arg_type = self.get_arg_type()
423 if arg_type == TYPE_INVALID:
424 raise TypeError, 'Invalid arg type in MessageIter'
425 elif arg_type == TYPE_STRING:
426 retval = self.get_string()
427 elif arg_type == TYPE_INT32:
428 retval = self.get_int32()
429 elif arg_type == TYPE_UINT32:
430 retval = self.get_uint32()
431 elif arg_type == TYPE_DOUBLE:
432 retval = self.get_double()
433 elif arg_type == TYPE_BYTE:
434 retval = self.get_byte()
435 elif arg_type == TYPE_BOOLEAN:
436 retval = self.get_boolean()
437 elif arg_type == TYPE_ARRAY:
438 array_type = self.get_array_type()
440 if array_type == TYPE_STRING:
441 retval = self.get_string_array()
442 elif array_type == TYPE_BOOLEAN:
443 retval = self.get_boolean_array()
445 raise TypeError, "Unknown array type %d in MessageIter" % (array_type)
447 raise TypeError, 'Unknown arg type %d in MessageIter' % (argtype)
451 def get_arg_type(self):
452 return dbus_message_iter_get_arg_type(self.iter)
454 def get_array_type(self):
455 return dbus_message_iter_get_array_type(self.iter)
457 #FIXME: implement get_byte
459 # return dbus_message_iter_get_byte(self.iter)
461 def get_boolean(self):
462 return dbus_message_iter_get_boolean(self.iter)
465 return dbus_message_iter_get_int32(self.iter)
467 def get_uint32(self):
468 return dbus_message_iter_get_uint32(self.iter)
470 def get_double(self):
471 return dbus_message_iter_get_double(self.iter)
473 def get_string(self):
474 return dbus_message_iter_get_string(self.iter)
476 def get_dict_key(self):
477 return dbus_message_iter_get_dict_key(self.iter)
479 # FIXME: implement dbus_message_iter_get_named
480 # dbus_message_iter_init_array_iterator
482 def get_byte_array(self):
484 cdef unsigned char *retval
485 dbus_message_iter_get_byte_array(self.iter, &retval, <int*>&len)
487 for i from 0 <= i < len:
488 list.append(chr(retval[i]))
491 # FIXME: implement dbus_message_iter_get_boolean_array
492 # dbus_message_iter_get_int32_array
493 # dbus_message_iter_get_uint32_array
494 # dbus_message_iter_get_double_array
496 def get_string_array(self):
500 dbus_message_iter_get_string_array(self.iter, &retval, <int*>&len)
502 for i from 0 <= i < len:
503 list.append(retval[i])
506 # dbus_message_append_iter_init included in class Message
508 #FIXME: handle all the different types?
509 def append(self, value):
510 value_type = type(value)
512 if value_type == bool:
513 retval = self.append_boolean(value)
514 elif value_type == int:
515 retval = self.append_int32(value)
516 elif value_type == float:
517 retval = self.append_double(value)
518 elif value_type == str:
519 retval = self.append_string(value)
520 elif value_type == list:
522 raise TypeError, "Empty list"
523 list_type = type(list[0])
525 self.append_string_array(list)
527 raise TypeError, "List of unknown type '%s'" % (list_type)
529 raise TypeError, "Argument of unknown type '%s'" % (value_type)
533 def append_nil(self):
534 return dbus_message_iter_append_nil(self.iter)
536 def append_boolean(self, value):
537 return dbus_message_iter_append_boolean(self.iter, value)
539 def append_byte(self, value):
540 return dbus_message_iter_append_byte(self.iter, value)
542 def append_int32(self, value):
543 return dbus_message_iter_append_int32(self.iter, value)
545 def append_uint32(self, value):
546 return dbus_message_iter_append_uint32(self.iter, value)
548 def append_double(self, value):
549 return dbus_message_iter_append_double(self.iter, value)
551 def append_string(self, value):
552 return dbus_message_iter_append_string(self.iter, value)
554 # FIXME: dbus_message_iter_append_named
556 def append_dict_key(self, value):
557 return dbus_message_iter_append_dict_key(self.iter, value)
559 # FIXME: append_array, append_dict_array, append_boolean_array, append_int32_array, append_uint32_array, append_double_array
561 def append_byte_array(self, list):
562 cdef unsigned char * value
565 value = <unsigned char*>malloc(length)
566 for i from 0 <= i < length:
568 if type(item) != str or len(item) != 1:
571 return dbus_message_iter_append_byte_array(self.iter, value, length)
573 def append_string_array(self, list):
577 value = <char**>malloc(length)
578 for i from 0 <= i < length:
580 if type(item) != str:
583 return dbus_message_iter_append_string_array(self.iter, value, length)
586 (MESSAGE_TYPE_INVALID, MESSAGE_TYPE_METHOD_CALL, MESSAGE_TYPE_METHOD_RETURN, MESSAGE_TYPE_ERROR, MESSAGE_TYPE_SIGNAL) = range(5)
587 (TYPE_INVALID, TYPE_NIL, TYPE_BYTE, TYPE_BOOLEAN, TYPE_INT32, TYPE_UINT32, TYPE_INT64, TYPE_UINT64, TYPE_DOUBLE, TYPE_STRING, TYPE_NAMED, TYPE_ARRAY, TYPE_DICT, TYPE_OBJECT_PATH) = range(14)
590 cdef DBusMessage *msg
592 def __init__(self, message_type=MESSAGE_TYPE_INVALID,
593 service=None, path=None, interface=None, method=None,
596 reply_to=None, error_name=None, error_message=None,
599 if (service == None):
607 if message_type == MESSAGE_TYPE_METHOD_CALL:
608 self.msg = dbus_message_new_method_call(cservice, path, interface, method)
609 elif message_type == MESSAGE_TYPE_METHOD_RETURN:
611 cmsg = method_call._get_msg()
612 self.msg = dbus_message_new_method_return(<DBusMessage*>cmsg)
614 elif message_type == MESSAGE_TYPE_SIGNAL:
615 self.msg = dbus_message_new_signal(path, interface, name)
616 elif message_type == MESSAGE_TYPE_ERROR:
617 cmsg = reply_to._get_msg()
618 self.msg = dbus_message_new_error(<DBusMessage*>cmsg, error_name, error_message)
620 def type_to_name(self, type):
621 if type == MESSAGE_TYPE_SIGNAL:
623 elif type == MESSAGE_TYPE_METHOD_CALL:
625 elif type == MESSAGE_TYPE_METHOD_RETURN:
626 return "method return"
627 elif type == MESSAGE_TYPE_ERROR:
630 return "(unknown message type)"
633 message_type = self.get_type()
634 sender = self.get_sender()
637 sender = "(no sender)"
639 if (message_type == MESSAGE_TYPE_METHOD_CALL) or (message_type == MESSAGE_TYPE_SIGNAL):
640 retval = '%s interface=%s; member=%s; sender=%s' % (self.type_to_name(message_type),
641 self.get_interface(),
644 elif message_type == MESSAGE_TYPE_METHOD_RETURN:
645 retval = '%s sender=%s' % (self.type_to_name(message_type),
647 elif message_type == MESSAGE_TYPE_ERROR:
648 retval = '%s name=%s; sender=%s' % (self.type_to_name(message_type),
649 self.get_error_name(),
652 retval = "Message of unknown type %d" % (message_type)
655 # FIXME: should really use self.convert_to_tuple() here
657 iter = self.get_iter()
660 while (value_at_iter):
661 type = iter.get_arg_type()
663 if type == TYPE_INVALID:
665 elif type == TYPE_STRING:
666 str = iter.get_string()
667 arg = 'string:%s\n' % (str)
668 elif type == TYPE_INT32:
669 num = iter.get_int32()
670 arg = 'int32:%d\n' % (num)
671 elif type == TYPE_UINT32:
672 num = iter.get_uint32()
673 arg = 'uint32:%u\n' % (num)
674 elif type == TYPE_DOUBLE:
675 num = iter.get_double()
676 arg = 'double:%f\n' % (num)
677 elif type == TYPE_BYTE:
678 num = iter.get_byte()
679 arg = 'byte:%d\n' % (num)
680 elif type == TYPE_BOOLEAN:
681 bool = iter.get_boolean()
686 arg = 'boolean:%s\n' % (str)
688 arg = '(unknown arg type %d)\n' % type
690 retval = retval + arg
691 value_at_iter = iter.next()
695 def _set_msg(self, msg):
696 self.msg = <DBusMessage*>msg
699 return <object>self.msg
702 return MessageIter(self)
704 def get_args_list(self):
707 iter = self.get_iter()
709 retval.append(iter.get())
713 value_at_iter = iter.next()
714 while (value_at_iter):
715 retval.append(iter.get())
716 value_at_iter = iter.next()
720 # FIXME: implement dbus_message_copy?
723 return dbus_message_get_type(self.msg)
725 def set_path(self, object_path):
726 return dbus_message_set_path(self.msg, object_path)
729 return dbus_message_get_path(self.msg)
731 def set_interface(self, interface):
732 return dbus_message_set_interface(self.msg, interface)
734 def get_interface(self):
735 return dbus_message_get_interface(self.msg)
737 def set_member(self, member):
738 return dbus_message_set_member(self.msg, member)
740 def get_member(self):
741 return dbus_message_get_member(self.msg)
743 def set_error_name(self, name):
744 return dbus_message_set_error_name(self.msg, name)
746 def get_error_name(self):
747 return dbus_message_get_error_name(self.msg)
749 def set_destination(self, destination):
750 return dbus_message_set_destination(self.msg, destination)
752 def get_destination(self):
753 return dbus_message_get_destination(self.msg)
755 def set_sender(self, sender):
756 return dbus_message_set_sender(self.msg, sender)
758 def get_sender(self):
760 sender = dbus_message_get_sender(self.msg)
766 def set_no_reply(self, no_reply):
767 dbus_message_set_no_reply(self.msg, no_reply)
769 def get_no_reply(self):
770 return dbus_message_get_no_reply(self.msg)
772 def is_method_call(self, interface, method):
773 return dbus_message_is_method_call(self.msg, interface, method)
775 def is_signal(self, interface, signal_name):
776 return dbus_message_is_signal(self.msg, interface, signal_name)
778 def is_error(self, error_name):
779 return dbus_message_is_error(self.msg, error_name)
781 def has_destination(self, service):
782 return dbus_message_has_destination(self.msg, service)
784 def has_sender(self, service):
785 return dbus_message_has_sender(self.msg, service)
787 def get_serial(self):
788 return dbus_message_get_serial(self.msg)
790 def set_reply_serial(self, reply_serial):
791 return dbus_message_set_reply_serial(self.msg, reply_serial)
793 def get_reply_serial(self):
794 return dbus_message_get_reply_serial(self.msg)
796 #FIXME: dbus_message_get_path_decomposed
798 # FIXME: all the different dbus_message_*args* methods
800 class Signal(Message):
801 def __init__(self, spath, sinterface, sname):
802 Message.__init__(self, MESSAGE_TYPE_SIGNAL, path=spath, interface=sinterface, name=sname)
804 class MethodCall(Message):
805 def __init__(self, mpath, minterface, mmethod):
806 Message.__init__(self, MESSAGE_TYPE_METHOD_CALL, path=mpath, interface=minterface, method=mmethod)
808 class MethodReturn(Message):
809 def __init__(self, method_call):
810 Message.__init__(self, MESSAGE_TYPE_METHOD_RETURN, method_call=method_call)
812 class Error(Message):
813 def __init__(self, reply_to, error_name, error_message):
814 Message.__init__(self, MESSAGE_TYPE_ERROR, reply_to=reply_to, error_name=error_name, error_message=error_message)
817 cdef DBusServer *server
818 def __init__(self, address):
820 dbus_error_init(&error)
821 self.server = dbus_server_listen(address,
823 if dbus_error_is_set(&error):
824 raise DBusException, error.message
826 def setup_with_g_main (self):
827 dbus_server_setup_with_g_main(self.server, NULL)
829 def disconnect(self):
830 dbus_server_disconnect(self.server)
832 def get_is_connected(self):
833 return dbus_server_get_is_connected(self.server)
835 # def set_new_connection_function(self, function, data):
836 # dbus_server_set_new_connection_function(self.conn, function,
839 # def set_watch_functions(self, add_function, remove_function, data):
840 # dbus_server_set_watch_functions(self.server,
841 # add_function, remove_function,
844 # def set_timeout_functions(self, add_function, remove_function, data):
845 # dbus_server_set_timeout_functions(self.server,
846 # add_function, remove_function,
849 # def handle_watch(self, watch, condition):
850 # dbus_server_handle_watch(self.conn, watch, condition)
852 BUS_SESSION = DBUS_BUS_SESSION
853 BUS_SYSTEM = DBUS_BUS_SYSTEM
854 BUS_ACTIVATION = DBUS_BUS_ACTIVATION
856 def bus_get (bus_type):
858 dbus_error_init(&error)
859 cdef DBusConnection *connection
861 connection = dbus_bus_get(bus_type,
864 if dbus_error_is_set(&error):
865 raise DBusException, error.message
867 return Connection(_conn=<object>connection)
869 def bus_get_base_service(connection):
870 conn = connection._get_conn()
871 return dbus_bus_get_base_service(<DBusConnection*>conn)
873 def bus_register(connection):
875 dbus_error_init(&error)
876 cdef dbus_bool_t retval
878 conn = connection._get_conn()
879 retval = dbus_bus_register(<DBusConnection*>conn,
881 if dbus_error_is_set(&error):
882 raise DBusException, error.message
886 SERVICE_FLAG_PROHIBIT_REPLACEMENT = 0x1
887 SERVICE_FLAG_REPLACE_EXISTING = 0x2
889 def bus_acquire_service(connection, service_name, flags=0):
891 dbus_error_init(&error)
894 conn = connection._get_conn()
895 retval = dbus_bus_acquire_service(<DBusConnection*>conn,
899 if dbus_error_is_set(&error):
900 raise DBusException, error.message
903 def bus_service_exists(connection, service_name):
905 dbus_error_init(&error)
906 cdef dbus_bool_t retval
908 conn = connection._get_conn()
909 retval = dbus_bus_service_exists(<DBusConnection*>conn,
912 if dbus_error_is_set(&error):
913 raise DBusException, error.message