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 tup = <object>user_data
67 assert (type(tup) == list)
69 args = [Connection(_conn=<object>connection)]
72 cdef DBusHandlerResult cmessage_function_handler (DBusConnection *connection,
75 tup = <object>user_data
76 assert (type(tup) == list)
78 message = Message(_create=0)
79 message._set_msg(<object>msg)
80 args = [Connection(_conn=<object>connection),
82 retval = function(*args)
84 retval = DBUS_HANDLER_RESULT_HANDLED
87 cdef DBusHandlerResult chandle_message_function_handler (DBusConnection *connection,
90 function = <object>user_data
91 assert (type(function) == function)
92 messagein = Message(_create=0)
93 messagein._set_msg(<object>msg)
94 args = [Connection(_conn=<object>connection),
96 retval = function(*args)
98 retval = DBUS_HANDLER_RESULT_HANDLED
101 cdef class Connection:
102 cdef DBusConnection *conn
104 # FIXME: this is a major major hack. We use this because casting values to
105 # python objects and returning seemed to be corrupting them. This is a "global variable" :-(
106 cdef char **_parsed_path
108 def __init__(self, address=None, _conn=None):
110 dbus_error_init(&error)
111 if <DBusConnection*>_conn != NULL:
112 self.conn = <DBusConnection*>_conn
113 dbus_connection_ref(self.conn)
115 self.conn = dbus_connection_open(address,
117 if dbus_error_is_set(&error):
118 raise DBusException, error.message
120 dbus_connection_ref(self.conn)
122 def _set_conn(self, conn):
123 self.conn = <DBusConnection*>conn
126 return <object>self.conn
128 #FIXME: this is totally busted, don't use a class shared member like parsed_path
129 def _build_parsed_path(self, path_element_list):
130 cdef char **cpatharray
131 size = len(path_element_list)
132 cpatharray = <char **>malloc(sizeof(char*) * (size + 1))
134 for i in range(size):
135 path_element = path_element_list[i]
136 cpatharray[i] = path_element
138 cpatharray[size] = NULL
140 self._parsed_path = cpatharray
142 def get_base_service(self):
143 return bus_get_base_service(self)
145 def setup_with_g_main(self):
146 dbus_connection_setup_with_g_main(self.conn, NULL)
148 def disconnect(self):
149 dbus_connection_disconnect(self.conn)
151 def get_is_connected(self):
152 return dbus_connection_get_is_connected(self.conn)
154 def get_is_authenticated(self):
155 return dbus_connection_get_is_authenticated(self.conn)
158 dbus_connection_flush(self.conn)
160 def borrow_message(self):
161 m = Message(_create=0)
162 m._set_msg(<object>dbus_connection_borrow_message(self.conn))
165 def return_message(self, message):
166 msg = message._get_msg()
167 dbus_connection_return_message(self.conn, <DBusMessage*>msg)
169 def steal_borrowed_message(self, message):
170 msg = message._get_msg()
171 dbus_connection_steal_borrowed_message(self.conn,
174 def pop_message(self):
175 cdef DBusMessage *msg
176 msg = dbus_connection_pop_message(self.conn)
178 m = Message(_create=0)
179 m._set_msg(<object>msg)
184 def get_dispatch_status(self):
185 return dbus_connection_get_dispatch_status(self.conn)
188 return dbus_connection_dispatch(self.conn)
190 def send(self, message):
191 #cdef dbus_uint32_t client_serial
192 #if type(message) != Message:
195 msg = message._get_msg()
196 retval = dbus_connection_send(self.conn,
201 def send_with_reply(self, message, timeout_milliseconds):
202 cdef dbus_bool_t retval
203 cdef DBusPendingCall *cpending_call
205 dbus_error_init(&error)
209 msg = message._get_msg()
211 retval = dbus_connection_send_with_reply(self.conn,
214 timeout_milliseconds)
216 if dbus_error_is_set(&error):
217 raise DBusException, error.message
219 if (cpending_call != NULL):
220 pending_call = PendingCall(<object>cpending_call)
224 return (retval, pending_call)
226 def send_with_reply_and_block(self, message,
227 timeout_milliseconds=0):
228 cdef DBusMessage * retval
230 dbus_error_init(&error)
232 msg = message._get_msg()
234 retval = dbus_connection_send_with_reply_and_block(
235 <DBusConnection*>self.conn,
237 <int>timeout_milliseconds,
240 if dbus_error_is_set(&error):
241 raise DBusException, error.message
246 m = Message(_create=0)
247 m._set_msg(<object>retval)
250 def set_watch_functions(self, add_function, remove_function, data):
253 def set_timeout_functions(self, add_function, remove_function, data):
256 def set_wakeup_main_function(self, wakeup_main_function, data):
259 # FIXME: set_dispatch_status_function, get_unix_user, set_unix_user_function
261 def add_filter(self, function):
262 return dbus_connection_add_filter(self.conn,
263 chandle_message_function_handler,
268 #FIXME: remove_filter
269 # this is pretty tricky, we want to only remove the filter
270 # if we truly have no more calls to our message_function_handler...ugh
272 def set_data(self, slot, data):
275 def get_data(self, slot):
278 def set_max_message_size(self, size):
279 dbus_connection_set_max_message_size(self.conn, size)
281 def get_max_message_size(self):
282 return dbus_connection_get_max_message_size(self.conn)
284 def set_max_received_size(self, size):
285 dbus_connection_set_max_received_size(self.conn, size)
287 def get_max_received_size(self):
288 return dbus_connection_get_max_received_size(self.conn)
290 def get_outgoing_size(self):
291 return dbus_connection_get_outgoing_size(self.conn)
293 # preallocate_send, free_preallocated_send, send_preallocated
295 def register_object_path(self, path, unregister_cb, message_cb):
296 cdef DBusObjectPathVTable cvtable
298 cvtable.unregister_function = cunregister_function_handler
299 cvtable.message_function = cmessage_function_handler
301 user_data = [unregister_cb, message_cb]
302 global _user_data_references
303 _user_data_references.append(user_data)
305 path_element_list = path[1:].split('/')
306 self._build_parsed_path(path_element_list)
308 return dbus_connection_register_object_path(self.conn, self._parsed_path, &cvtable,
311 def register_fallback(self, path, unregister_cb, message_cb):
312 cdef DBusObjectPathVTable cvtable
314 cvtable.unregister_function = cunregister_function_handler
315 cvtable.message_function = cmessage_function_handler
317 user_data = [unregister_cb, message_cb]
318 global _user_data_references
319 _user_data_references.append(user_data)
321 path_element_list = path[1:].split('/')
322 self._build_parsed_path(path_element_list)
324 return dbus_connection_register_fallback(self.conn, self._parsed_path, &cvtable,
327 #FIXME: unregister_object_path , see problems with remove_filter
329 def list_registered (self, parent_path):
330 cdef char **cchild_entries
331 cdef dbus_bool_t retval
333 path_element_list = parent_path[1:].split('/')
334 self._build_parsed_path(path_element_list)
336 retval = dbus_connection_list_registered(self.conn, self._parsed_path, &cchild_entries)
339 #FIXME: raise out of memory exception?
345 while (cchild_entries[i] != NULL):
346 child_entries.append(cchild_entries[i])
349 dbus_free_string_array(cchild_entries)
354 cdef class PendingCall:
355 cdef DBusPendingCall *pending_call
357 def __init__(self, _pending_call):
358 self.pending_call = <DBusPendingCall*>_pending_call
359 dbus_pending_call_ref(self.pending_call)
361 def _get_pending_call(self):
362 return <object>self.pending_call
365 dbus_pending_call_cancel(self.pending_call)
367 def get_completed(self):
368 return dbus_pending_call_get_completed(self.pending_call)
371 message = Message(_create=0)
372 message._set_msg(<object>dbus_pending_call_get_reply(self.pending_call))
376 dbus_pending_call_block(self.pending_call)
379 cdef DBusWatch* watch
380 def __init__(self, cwatch):
381 self.watch = <DBusWatch*>cwatch
384 return dbus_watch_get_fd(self.watch)
386 # FIXME: not picked up correctly by extract.py
387 #def get_flags(self):
388 # return dbus_watch_get_flags(self.watch)
390 def handle(self, flags):
391 return dbus_watch_handle(self.watch, flags)
393 def get_enabled(self):
394 return dbus_watch_get_enabled(self.watch)
396 cdef class MessageIter:
397 cdef DBusMessageIter *iter
398 cdef DBusMessageIter real_iter
401 def __init__(self, message):
402 self.iter = &self.real_iter
403 msg = message._get_msg()
404 dbus_message_iter_init(<DBusMessage*>msg, self.iter)
407 return <object>self.iter
410 return dbus_message_iter_has_next(self.iter)
413 return dbus_message_iter_next(self.iter)
416 arg_type = self.get_arg_type()
418 if arg_type == TYPE_INVALID:
419 raise TypeError, 'Invalid arg type in MessageIter'
420 elif arg_type == TYPE_STRING:
421 retval = self.get_string()
422 elif arg_type == TYPE_INT32:
423 retval = self.get_int32()
424 elif arg_type == TYPE_UINT32:
425 retval = self.get_uint32()
426 elif arg_type == TYPE_DOUBLE:
427 retval = self.get_double()
428 elif arg_type == TYPE_BYTE:
429 retval = self.get_byte()
430 elif arg_type == TYPE_BOOLEAN:
431 retval = self.get_boolean()
432 elif arg_type == TYPE_ARRAY:
433 array_type = self.get_array_type()
435 if array_type == TYPE_STRING:
436 retval = self.get_string_array()
437 elif array_type == TYPE_BOOLEAN:
438 retval = self.get_boolean_array()
440 raise TypeError, "Unknown array type %d in MessageIter" % (array_type)
442 raise TypeError, 'Unknown arg type %d in MessageIter' % (argtype)
446 def get_arg_type(self):
447 return dbus_message_iter_get_arg_type(self.iter)
449 def get_array_type(self):
450 return dbus_message_iter_get_array_type(self.iter)
452 #FIXME: implement get_byte
454 # return dbus_message_iter_get_byte(self.iter)
456 def get_boolean(self):
457 return dbus_message_iter_get_boolean(self.iter)
460 return dbus_message_iter_get_int32(self.iter)
462 def get_uint32(self):
463 return dbus_message_iter_get_uint32(self.iter)
465 def get_double(self):
466 return dbus_message_iter_get_double(self.iter)
468 def get_string(self):
469 return dbus_message_iter_get_string(self.iter)
471 def get_dict_key(self):
472 return dbus_message_iter_get_dict_key(self.iter)
474 # FIXME: implement dbus_message_iter_get_named
475 # dbus_message_iter_init_array_iterator
477 def get_byte_array(self):
479 cdef unsigned char *retval
480 dbus_message_iter_get_byte_array(self.iter, &retval, <int*>&len)
482 for i from 0 <= i < len:
483 list.append(chr(retval[i]))
486 # FIXME: implement dbus_message_iter_get_boolean_array
487 # dbus_message_iter_get_int32_array
488 # dbus_message_iter_get_uint32_array
489 # dbus_message_iter_get_double_array
491 def get_string_array(self):
495 dbus_message_iter_get_string_array(self.iter, &retval, <int*>&len)
497 for i from 0 <= i < len:
498 list.append(retval[i])
501 # dbus_message_append_iter_init included in class Message
503 #FIXME: handle all the different types?
504 def append(self, value):
505 value_type = type(value)
507 if value_type == bool:
508 retval = self.append_boolean(value)
509 elif value_type == int:
510 retval = self.append_int32(value)
511 elif value_type == float:
512 retval = self.append_double(value)
513 elif value_type == str:
514 retval = self.append_string(value)
515 elif value_type == list:
517 raise TypeError, "Empty list"
518 list_type = type(list[0])
520 self.append_string_array(list)
522 raise TypeError, "List of unknown type '%s'" % (list_type)
524 raise TypeError, "Argument of unknown type '%s'" % (value_type)
528 def append_nil(self):
529 return dbus_message_iter_append_nil(self.iter)
531 def append_boolean(self, value):
532 return dbus_message_iter_append_boolean(self.iter, value)
534 def append_byte(self, value):
535 return dbus_message_iter_append_byte(self.iter, value)
537 def append_int32(self, value):
538 return dbus_message_iter_append_int32(self.iter, value)
540 def append_uint32(self, value):
541 return dbus_message_iter_append_uint32(self.iter, value)
543 def append_double(self, value):
544 return dbus_message_iter_append_double(self.iter, value)
546 def append_string(self, value):
547 return dbus_message_iter_append_string(self.iter, value)
549 # FIXME: dbus_message_iter_append_named
551 def append_dict_key(self, value):
552 return dbus_message_iter_append_dict_key(self.iter, value)
554 # FIXME: append_array, append_dict_array, append_boolean_array, append_int32_array, append_uint32_array, append_double_array
556 def append_byte_array(self, list):
557 cdef unsigned char * value
560 value = <unsigned char*>malloc(length)
561 for i from 0 <= i < length:
563 if type(item) != str or len(item) != 1:
566 return dbus_message_iter_append_byte_array(self.iter, value, length)
568 def append_string_array(self, list):
572 value = <char**>malloc(length)
573 for i from 0 <= i < length:
575 if type(item) != str:
578 return dbus_message_iter_append_string_array(self.iter, value, length)
581 (MESSAGE_TYPE_INVALID, MESSAGE_TYPE_METHOD_CALL, MESSAGE_TYPE_METHOD_RETURN, MESSAGE_TYPE_ERROR, MESSAGE_TYPE_SIGNAL) = range(5)
582 (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)
585 cdef DBusMessage *msg
587 def __init__(self, message_type=MESSAGE_TYPE_INVALID,
588 service=None, path=None, interface=None, method=None,
591 reply_to=None, error_name=None, error_message=None,
594 if (service == None):
602 if message_type == MESSAGE_TYPE_METHOD_CALL:
603 self.msg = dbus_message_new_method_call(cservice, path, interface, method)
604 elif message_type == MESSAGE_TYPE_METHOD_RETURN:
605 cmsg = method_call._get_msg()
606 self.msg = dbus_message_new_method_return(<DBusMessage*>cmsg)
607 elif message_type == MESSAGE_TYPE_SIGNAL:
608 self.msg = dbus_message_new_signal(path, interface, name)
609 elif message_type == MESSAGE_TYPE_ERROR:
610 cmsg = reply_to._get_msg()
611 self.msg = dbus_message_new_error(<DBusMessage*>cmsg, error_name, error_message)
613 def type_to_name(self, type):
614 if type == MESSAGE_TYPE_SIGNAL:
616 elif type == MESSAGE_TYPE_METHOD_CALL:
618 elif type == MESSAGE_TYPE_METHOD_RETURN:
619 return "method return"
620 elif type == MESSAGE_TYPE_ERROR:
623 return "(unknown message type)"
626 message_type = self.get_type()
627 sender = self.get_sender()
630 sender = "(no sender)"
632 if (message_type == MESSAGE_TYPE_METHOD_CALL) or (message_type == MESSAGE_TYPE_SIGNAL):
633 retval = '%s interface=%s; member=%s; sender=%s' % (self.type_to_name(message_type),
634 self.get_interface(),
637 elif message_type == MESSAGE_TYPE_METHOD_RETURN:
638 retval = '%s sender=%s' % (self.type_to_name(message_type),
640 elif message_type == MESSAGE_TYPE_ERROR:
641 retval = '%s name=%s; sender=%s' % (self.type_to_name(message_type),
642 self.get_error_name(),
645 retval = "Message of unknown type %d" % (message_type)
648 # FIXME: should really use self.convert_to_tuple() here
650 iter = self.get_iter()
653 while (value_at_iter):
654 type = iter.get_arg_type()
656 if type == TYPE_INVALID:
658 elif type == TYPE_STRING:
659 str = iter.get_string()
660 arg = 'string:%s\n' % (str)
661 elif type == TYPE_INT32:
662 num = iter.get_int32()
663 arg = 'int32:%d\n' % (num)
664 elif type == TYPE_UINT32:
665 num = iter.get_uint32()
666 arg = 'uint32:%u\n' % (num)
667 elif type == TYPE_DOUBLE:
668 num = iter.get_double()
669 arg = 'double:%f\n' % (num)
670 elif type == TYPE_BYTE:
671 num = iter.get_byte()
672 arg = 'byte:%d\n' % (num)
673 elif type == TYPE_BOOLEAN:
674 bool = iter.get_boolean()
679 arg = 'boolean:%s\n' % (str)
681 arg = '(unknown arg type %d)\n' % type
683 retval = retval + arg
684 value_at_iter = iter.next()
688 def _set_msg(self, msg):
689 self.msg = <DBusMessage*>msg
692 return <object>self.msg
695 return MessageIter(self)
697 def get_args_list(self):
700 iter = self.get_iter()
702 retval.append(iter.get())
706 value_at_iter = iter.next()
707 while (value_at_iter):
708 retval.append(iter.get())
709 value_at_iter = iter.next()
713 # FIXME: implement dbus_message_copy?
716 return dbus_message_get_type(self.msg)
718 def set_path(self, object_path):
719 return dbus_message_set_path(self.msg, object_path)
722 return dbus_message_get_path(self.msg)
724 def set_interface(self, interface):
725 return dbus_message_set_interface(self.msg, interface)
727 def get_interface(self):
728 return dbus_message_get_interface(self.msg)
730 def set_member(self, member):
731 return dbus_message_set_member(self.msg, member)
733 def get_member(self):
734 return dbus_message_get_member(self.msg)
736 def set_error_name(self, name):
737 return dbus_message_set_error_name(self.msg, name)
739 def get_error_name(self):
740 return dbus_message_get_error_name(self.msg)
742 def set_destination(self, destination):
743 return dbus_message_set_destination(self.msg, destination)
745 def get_destination(self):
746 return dbus_message_get_destination(self.msg)
748 def set_sender(self, sender):
749 return dbus_message_set_sender(self.msg, sender)
751 def get_sender(self):
753 sender = dbus_message_get_sender(self.msg)
759 def set_no_reply(self, no_reply):
760 dbus_message_set_no_reply(self.msg, no_reply)
762 def get_no_reply(self):
763 return dbus_message_get_no_reply(self.msg)
765 def is_method_call(self, interface, method):
766 return dbus_message_is_method_call(self.msg, interface, method)
768 def is_signal(self, interface, signal_name):
769 return dbus_message_is_signal(self.msg, interface, signal_name)
771 def is_error(self, error_name):
772 return dbus_message_is_error(self.msg, error_name)
774 def has_destination(self, service):
775 return dbus_message_has_destination(self.msg, service)
777 def has_sender(self, service):
778 return dbus_message_has_sender(self.msg, service)
780 def get_serial(self):
781 return dbus_message_get_serial(self.msg)
783 def set_reply_serial(self, reply_serial):
784 return dbus_message_set_reply_serial(self.msg, reply_serial)
786 def get_reply_serial(self):
787 return dbus_message_get_reply_serial(self.msg)
789 #FIXME: dbus_message_get_path_decomposed
791 # FIXME: all the different dbus_message_*args* methods
793 class Signal(Message):
794 def __init__(self, spath, sinterface, sname):
795 Message.__init__(self, MESSAGE_TYPE_SIGNAL, path=spath, interface=sinterface, name=sname)
797 class MethodCall(Message):
798 def __init__(self, mpath, minterface, mmethod):
799 Message.__init__(self, MESSAGE_TYPE_METHOD_CALL, path=mpath, interface=minterface, method=mmethod)
801 class MethodReturn(Message):
802 def __init__(self, method_call):
803 Message.__init__(self, MESSAGE_TYPE_METHOD_RETURN, method_call=method_call)
805 class Error(Message):
806 def __init__(self, reply_to, error_name, error_message):
807 Message.__init__(self, MESSAGE_TYPE_ERROR, reply_to=reply_to, error_name=error_name, error_message=error_message)
810 cdef DBusServer *server
811 def __init__(self, address):
813 dbus_error_init(&error)
814 self.server = dbus_server_listen(address,
816 if dbus_error_is_set(&error):
817 raise DBusException, error.message
819 def setup_with_g_main (self):
820 dbus_server_setup_with_g_main(self.server, NULL)
822 def disconnect(self):
823 dbus_server_disconnect(self.server)
825 def get_is_connected(self):
826 return dbus_server_get_is_connected(self.server)
828 # def set_new_connection_function(self, function, data):
829 # dbus_server_set_new_connection_function(self.conn, function,
832 # def set_watch_functions(self, add_function, remove_function, data):
833 # dbus_server_set_watch_functions(self.server,
834 # add_function, remove_function,
837 # def set_timeout_functions(self, add_function, remove_function, data):
838 # dbus_server_set_timeout_functions(self.server,
839 # add_function, remove_function,
842 # def handle_watch(self, watch, condition):
843 # dbus_server_handle_watch(self.conn, watch, condition)
845 BUS_SESSION = DBUS_BUS_SESSION
846 BUS_SYSTEM = DBUS_BUS_SYSTEM
847 BUS_ACTIVATION = DBUS_BUS_ACTIVATION
849 def bus_get (bus_type):
851 dbus_error_init(&error)
852 cdef DBusConnection *connection
854 connection = dbus_bus_get(bus_type,
857 if dbus_error_is_set(&error):
858 raise DBusException, error.message
860 return Connection(_conn=<object>connection)
862 def bus_get_base_service(connection):
863 conn = connection._get_conn()
864 return dbus_bus_get_base_service(<DBusConnection*>conn)
866 def bus_register(connection):
868 dbus_error_init(&error)
869 cdef dbus_bool_t retval
871 conn = connection._get_conn()
872 retval = dbus_bus_register(<DBusConnection*>conn,
874 if dbus_error_is_set(&error):
875 raise DBusException, error.message
879 SERVICE_FLAG_PROHIBIT_REPLACEMENT = 0x1
880 SERVICE_FLAG_REPLACE_EXISTING = 0x2
882 def bus_acquire_service(connection, service_name, flags=0):
884 dbus_error_init(&error)
887 conn = connection._get_conn()
888 retval = dbus_bus_acquire_service(<DBusConnection*>conn,
892 if dbus_error_is_set(&error):
893 raise DBusException, error.message
896 def bus_service_exists(connection, service_name):
898 dbus_error_init(&error)
899 cdef dbus_bool_t retval
901 conn = connection._get_conn()
902 retval = dbus_bus_service_exists(<DBusConnection*>conn,
905 if dbus_error_is_set(&error):
906 raise DBusException, error.message