0060373460c1a3815fb84f29fe1ba9f42beeb083
[platform/upstream/dbus.git] / python / dbus_bindings.pyx
1 # -*- Mode: Python -*-
2
3 # jdahlin is the most coolest and awesomest person in the world
4 # and wrote all the good parts of this code. all the bad parts
5 # where python conditionals have a ( ) around them, thus violating
6 # PEP-8 were written by the lame wannabe python programmer seth
7
8 #FIXME: find memory leaks that I am sure exist
9
10 cdef extern from "sys/types.h":
11     ctypedef size_t
12     ctypedef __int64_t
13     ctypedef __uint64_t
14
15 cdef extern from "sys/cdefs.h":
16     ctypedef __signed
17
18 cdef extern from "stdlib.h":
19     cdef void *malloc(size_t size)
20     cdef void free(void *ptr)
21     cdef void *calloc(size_t nmemb, size_t size)
22
23 cdef extern from "Python.h":
24     void Py_XINCREF (object)
25     void Py_XDECREF (object)
26     object PyString_FromStringAndSize(char *, int)
27     ctypedef void *PyGILState_STATE
28     void PyErr_Clear()
29     PyGILState_STATE PyGILState_Ensure()
30     void PyGILState_Release(PyGILState_STATE)
31
32 ctypedef struct DBusError:
33     char *name
34     char *message
35     unsigned int dummy1 
36     unsigned int dummy2
37     unsigned int dummy3
38     unsigned int dummy4
39     unsigned int dummy5
40     void *padding1
41     
42 ctypedef struct DBusMessageIter:
43     void *dummy1
44     void *dummy2
45     dbus_uint32_t dummy3
46     int dummy4
47     int dummy5
48     int dummy6
49     int dummy7
50     int dummy8
51     int dummy9
52     int dummy10
53     int dummy11
54     int pad1
55     int pad2
56     void *pad3
57
58 ctypedef struct DBusObjectPathVTable:
59   DBusObjectPathUnregisterFunction   unregister_function
60   DBusObjectPathMessageFunction      message_function
61   void (* dbus_internal_pad1) (void *)
62   void (* dbus_internal_pad2) (void *)
63   void (* dbus_internal_pad3) (void *)
64   void (* dbus_internal_pad4) (void *)
65
66 class DBusException(Exception):
67     pass
68
69 class ConnectionError(Exception):
70     pass
71
72 class ObjectPath(str):
73     def __init__(self, value):
74         str.__init__(self, value)
75
76 class ByteArray(str):
77     def __init__(self, value):
78         str.__init__(self, value)
79
80 class Signature(str):
81     def __init__(self, value):
82         str.__init__(self, value)
83
84 class Byte(int):
85     def __init__(self, value):
86         int.__init__(self, value)
87
88 class Boolean(int):
89     def __init__(self, value):
90         int.__init__(self, value)
91
92 class Int16(int):
93     def __init__(self, value):
94         int.__init__(self, value)
95
96 class UInt16(int):
97     def __init__(self, value):
98         if value < 0:
99             raise TypeError('Unsigned integers must not have a negitive value') 
100         int.__init__(self, value)
101
102 class Int32(int):
103     def __init__(self, value):
104         int.__init__(self, value)
105
106 class UInt32(long):
107     def __init__(self, value):
108         if value < 0:
109             raise TypeError('Unsigned integers must not have a negitive value') 
110         long.__init__(self, value)
111
112 class Int64(long):
113     def __init__(self, value):
114         long.__init__(self, value)
115
116 class UInt64(long):
117     def __init__(self, value):
118         if value < 0:
119             raise TypeError('Unsigned integers must not have a negitive value') 
120         long.__init__(self, value)
121
122 class Double(float):
123     def __init__(self, value):
124         float.__init__(self, value)
125
126 class String(str):
127     def __init__(self, value):
128         str.__init__(self, value)
129
130 class Array(list):
131     def __init__(self, value, type=None, signature=None):
132         if signature and type:
133             raise TypeError('Can not mix type and signature arguments in a D-BUS Array')
134     
135         self.type = type
136         self.signature = signature
137         list.__init__(self, value)
138
139 class Variant:
140     def __init__(self, value, type=None, signature=None):
141         self.value = value
142         if signature and type:
143             raise TypeError('Can not mix type and signature arguments in a D-BUS Variant')
144
145         self.type = type
146         self.signature = signature
147
148     def __repr__(self):
149         return repr(self.value)
150
151     def __str__(self):
152         return str(self.value)
153
154 class Struct(tuple):
155     def __init__(self, value):
156         tuple.__init__(self, value)
157
158 class Dictionary(dict):
159     def __init__(self, value, key_type=None, value_type=None, signature=None):
160         if key_type and not value_type:
161              raise TypeError('When specifying a key_type you must also have a value_type in a D-BUS Dictionary')
162         elif value_type and not key_type:
163              raise TypeError('When specifying a value_type you must also have a key_type in a D-BUS Dictionary')
164         elif key_type and signature:
165               raise TypeError('Can not mix type arguments with signature arguments in a D-BUS Dictionary')
166               
167         self.key_type = key_type
168         self.value_type = value_type
169         self.signature = signature
170         dict.__init__(self, value)
171
172 #forward delcerations
173 cdef class Message
174 cdef class PendingCall
175 cdef class Watch
176 cdef class MessageIter
177
178 cdef void _GIL_safe_cunregister_function_handler (DBusConnection *connection,
179                                                   void *user_data):
180     cdef Connection conn
181
182     tup = <object>user_data
183     assert (type(tup) == tuple)    
184     function = tup[1]
185     conn = Connection()
186     conn.__cinit__(None, connection)
187
188     args = (conn)
189     function(*args)
190     Py_XDECREF(tup) 
191
192 cdef void cunregister_function_handler (DBusConnection *connection,
193                                         void *user_data):
194     cdef PyGILState_STATE gil
195     gil = PyGILState_Ensure()
196     try:
197         _GIL_safe_cunregister_function_handler (connection, user_data);
198     finally:
199         PyGILState_Release(gil)
200
201
202
203 cdef DBusHandlerResult _GIL_safe_cmessage_function_handler ( 
204                                                   DBusConnection *connection,
205                                                   DBusMessage *msg,
206                                                   void *user_data):
207     cdef Connection conn
208     cdef Message message
209
210     tup = <object>user_data
211     assert (type(tup) == tuple)
212     function = tup[0]
213     message = EmptyMessage()
214
215     #we don't own the message so we need to ref it
216     dbus_message_ref(msg)
217     message._set_msg(msg)
218     conn = Connection()
219     conn.__cinit__(None, connection)
220     args = (conn,
221             message)
222  
223     retval = function(*args)
224
225     if (retval == None):
226         retval = DBUS_HANDLER_RESULT_HANDLED
227     return retval
228
229 cdef DBusHandlerResult cmessage_function_handler (DBusConnection *connection,
230                                                   DBusMessage *msg,
231                                                   void *user_data):
232     cdef PyGILState_STATE gil
233     gil = PyGILState_Ensure()
234     try:
235         return _GIL_safe_cmessage_function_handler (connection, msg, user_data);
236     finally:
237         PyGILState_Release(gil)
238
239
240 cdef class Connection:
241     def __init__(self, address=None, Connection _conn=None):
242         cdef DBusConnection *c_conn
243         cdef char *c_address
244         c_conn=NULL
245         self.conn = NULL
246         if (_conn != None):
247             c_conn = _conn.conn
248
249         if (address != None or _conn != None):
250             self.__cinit__(c_address, c_conn)
251
252     # hack to be able to pass in a c pointer to the constructor
253     # while still alowing python programs to create a Connection object
254     cdef __cinit__(self, address, DBusConnection *_conn):
255         cdef DBusError error
256         dbus_error_init(&error)
257         if _conn != NULL:
258             self.conn = _conn
259             dbus_connection_ref(self.conn)
260         else:
261             self.conn = dbus_connection_open(address,
262                                          &error)
263             if dbus_error_is_set(&error):
264                 errormsg = error.message
265                 dbus_error_free (&error)
266                 raise DBusException, errormsg
267
268     def __dealloc__(self):
269         if self.conn != NULL:
270             dbus_connection_unref(self.conn)
271
272     cdef _set_conn(self, DBusConnection *conn):
273         self.conn = conn
274     
275     cdef DBusConnection *_get_conn(self):
276         return self.conn
277     
278     def get_unique_name(self):
279         return bus_get_unique_name(self)
280
281     def disconnect(self):
282         dbus_connection_disconnect(self.conn)
283
284     def get_is_connected(self):
285         return dbus_connection_get_is_connected(self.conn)
286     
287     def get_is_authenticated(self):
288         return dbus_connection_get_is_authenticated(self.conn)
289
290     def flush(self):
291         dbus_connection_flush(self.conn)
292
293     def borrow_message(self):
294         cdef Message m
295         m = EmptyMessage()
296         m._set_msg(dbus_connection_borrow_message(self.conn))
297         return m
298     
299     def return_message(self, Message message):
300         cdef DBusMessage *msg
301         msg = message._get_msg()
302         dbus_connection_return_message(self.conn, msg)
303
304     def steal_borrowed_message(self, Message message):
305         cdef DBusMessage *msg
306         msg = message._get_msg()
307         dbus_connection_steal_borrowed_message(self.conn,
308                                                msg)
309     
310     def pop_message(self):
311         cdef DBusMessage *msg
312         cdef Message m
313  
314         msg = dbus_connection_pop_message(self.conn)
315         if msg != NULL:
316             m = EmptyMessage()
317             m._set_msg(msg)
318         else:
319             m = None
320         return m        
321
322     def get_dispatch_status(self):
323         return dbus_connection_get_dispatch_status(self.conn)
324     
325     def dispatch(self):
326         return dbus_connection_dispatch(self.conn)
327
328     def send(self, Message message):
329         #cdef dbus_uint32_t client_serial
330         #if type(message) != Message:
331         #    raise TypeError
332         cdef DBusMessage *msg
333         msg = message._get_msg()
334         retval = dbus_connection_send(self.conn,
335                                       msg,
336                                       NULL)
337         return retval
338
339     def send_with_reply_handlers(self, Message message, timeout_milliseconds, reply_handler, error_handler):
340         retval = False
341         try:
342             (retval, pending_call) = self.send_with_reply(message, timeout_milliseconds)
343             if pending_call:
344                 pending_call.set_notify(reply_handler, error_handler)
345         except Exception, e:
346             error_handler(e)
347             
348         return (retval, pending_call)
349
350     def send_with_reply(self, Message message, timeout_milliseconds):
351         cdef dbus_bool_t retval
352         cdef DBusPendingCall *cpending_call
353         cdef DBusMessage *msg
354         cdef PendingCall pending_call
355
356         cpending_call = NULL
357         
358         msg = message._get_msg()
359
360         retval = dbus_connection_send_with_reply(self.conn,
361                                                  msg,
362                                                  &cpending_call,
363                                                  timeout_milliseconds)
364
365         if (cpending_call != NULL):
366             pending_call = PendingCall()
367             pending_call.__cinit__(cpending_call)
368         else:
369             pending_call = None
370
371         return (retval, pending_call)
372                                 
373     def send_with_reply_and_block(self, Message message,
374                                   timeout_milliseconds=-1):
375         cdef DBusMessage * retval
376         cdef DBusError error
377         cdef DBusMessage *msg
378         cdef Message m
379
380         dbus_error_init(&error)
381
382         msg = message._get_msg()
383
384         retval = dbus_connection_send_with_reply_and_block(
385             self.conn,
386             msg,
387             timeout_milliseconds,
388             &error)
389
390         if dbus_error_is_set(&error):
391             errormsg = error.message
392             dbus_error_free (&error)
393             raise DBusException, errormsg
394
395         if retval == NULL:
396             raise AssertionError
397         
398         m = EmptyMessage()
399         m._set_msg(retval)
400
401         return m 
402
403     def set_watch_functions(self, add_function, remove_function, data):
404         pass
405
406     def set_timeout_functions(self, add_function, remove_function, data):
407         pass
408
409     def set_wakeup_main_function(self, wakeup_main_function, data):
410         pass
411
412     # FIXME: set_dispatch_status_function, get_unix_user, set_unix_user_function
413
414     def add_filter(self, filter_function):
415         user_data = (filter_function,)
416         Py_XINCREF(user_data)
417        
418         return dbus_connection_add_filter(self.conn,
419                                           cmessage_function_handler,
420                                           <void*>user_data,
421                                           NULL)
422
423
424     #FIXME: remove_filter
425     #       this is pretty tricky, we want to only remove the filter
426     #       if we truly have no more calls to our message_function_handler...ugh
427
428     def set_data(self, slot, data):
429         pass
430
431     def get_data(self, slot):
432         pass
433
434     def set_max_message_size(self, size):
435         dbus_connection_set_max_message_size(self.conn, size)
436
437     def get_max_message_size(self):
438         return dbus_connection_get_max_message_size(self.conn)
439
440     def set_max_received_size(self, size):
441         dbus_connection_set_max_received_size(self.conn, size)
442
443     def get_max_received_size(self):
444         return dbus_connection_get_max_received_size(self.conn)
445
446     def get_outgoing_size(self):
447         return dbus_connection_get_outgoing_size(self.conn)    
448
449     # preallocate_send, free_preallocated_send, send_preallocated
450
451     def register_object_path(self, path, unregister_cb, message_cb):
452         cdef DBusObjectPathVTable cvtable
453         
454         cvtable.unregister_function = cunregister_function_handler 
455         cvtable.message_function    = cmessage_function_handler
456
457         user_data = (message_cb, unregister_cb)
458         Py_XINCREF(user_data)
459         
460         return dbus_connection_register_object_path(self.conn, path, &cvtable,
461                                                     <void*>user_data) 
462
463     def register_fallback(self, path, unregister_cb, message_cb):
464         cdef DBusObjectPathVTable cvtable
465
466         cvtable.unregister_function = cunregister_function_handler 
467         cvtable.message_function    = cmessage_function_handler
468
469         user_data = (message_cb, unregister_cb)
470         Py_XINCREF(user_data)
471        
472         return dbus_connection_register_fallback(self.conn, path, &cvtable,
473                                                  <void*>user_data) 
474
475     #FIXME: unregister_object_path , see problems with remove_filter
476
477     def list_registered (self, parent_path):
478         cdef char **cchild_entries
479         cdef dbus_bool_t retval
480         
481         retval = dbus_connection_list_registered(self.conn, parent_path, &cchild_entries)
482
483         if (not retval):
484             #FIXME: raise out of memory exception?
485             return None
486
487         i = 0
488         child_entries = []
489
490         while (cchild_entries[i] != NULL):
491             child_entries.append(cchild_entries[i])
492             i = i + 1
493
494         dbus_free_string_array(cchild_entries)
495
496         return child_entries
497
498 cdef void _GIL_safe_pending_call_notification (DBusPendingCall *pending_call, 
499                                                void *user_data):
500     cdef DBusMessage *dbus_message
501     cdef Message message
502   
503     (reply_handler, error_handler) = <object>user_data
504    
505     dbus_message = dbus_pending_call_steal_reply(pending_call)
506     message = EmptyMessage()
507     message._set_msg(dbus_message)
508
509     type = message.get_type()
510
511     if type == MESSAGE_TYPE_METHOD_RETURN:
512         args = message.get_args_list()
513         reply_handler(*args)
514     elif type == MESSAGE_TYPE_ERROR:
515         args = message.get_args_list()
516         if len(args) > 0:
517             error_handler(DBusException(args[0]))
518         else:
519             error_handler(DBusException(""))
520     else:
521         error_handler(DBusException('Unexpected Message Type: ' + message.type_to_name(type)))
522
523     dbus_pending_call_unref(pending_call)
524     Py_XDECREF(<object>user_data)
525
526 cdef void _pending_call_notification(DBusPendingCall *pending_call, 
527                                      void *user_data):
528     cdef PyGILState_STATE gil
529     gil = PyGILState_Ensure()
530     try:
531         _GIL_safe_pending_call_notification (pending_call, user_data);
532     finally:
533         PyGILState_Release(gil)
534
535 cdef void _pending_call_free_user_data(void *data):
536     call_tuple = <object>data
537     Py_XDECREF(call_tuple)
538
539 cdef class PendingCall:
540     cdef DBusPendingCall *pending_call
541
542     def __init__(self, PendingCall _pending_call=None):
543         self.pending_call = NULL
544         if (_pending_call != None):
545             self.__cinit__(_pending_call.pending_call)
546
547     cdef void __cinit__(self, DBusPendingCall *_pending_call):
548         self.pending_call = _pending_call
549         dbus_pending_call_ref(self.pending_call)
550
551     def __dealloc__(self):
552         if self.pending_call != NULL:
553             dbus_pending_call_unref(self.pending_call)
554
555     cdef DBusPendingCall *_get_pending_call(self):
556         return self.pending_call
557
558     def cancel(self):
559         dbus_pending_call_cancel(self.pending_call)
560
561     def get_completed(self):
562         return dbus_pending_call_get_completed(self.pending_call)
563
564     def get_reply(self):
565         cdef Message message
566         message = EmptyMessage()
567         message._set_msg(dbus_pending_call_steal_reply(self.pending_call))
568         return message
569
570     def block(self):
571         dbus_pending_call_block(self.pending_call)
572
573     def set_notify(self, reply_handler, error_handler):
574         user_data = (reply_handler, error_handler)
575         Py_XINCREF(user_data)
576         dbus_pending_call_ref(self.pending_call)
577         dbus_pending_call_set_notify(self.pending_call, _pending_call_notification, 
578                                      <void *>user_data, _pending_call_free_user_data)
579         
580
581 cdef class Watch:
582     cdef DBusWatch* watch
583
584     def __init__(self):
585         pass
586
587     cdef __cinit__(self, DBusWatch *cwatch):
588         self.watch = cwatch
589
590     def get_fd(self):
591         return dbus_watch_get_fd(self.watch)
592
593     # FIXME: not picked up correctly by extract.py
594     #def get_flags(self):
595     #    return dbus_watch_get_flags(self.watch)
596
597     def handle(self, flags):
598         return dbus_watch_handle(self.watch, flags)
599
600     def get_enabled(self):
601         return dbus_watch_get_enabled(self.watch)
602     
603 cdef class MessageIter:
604     cdef DBusMessageIter *iter
605     cdef DBusMessageIter real_iter
606     cdef dbus_uint32_t level
607
608     def __init__(self, level=0):
609         self.iter = &self.real_iter
610         self.level = level
611         if(self.level > 32):
612             raise TypeError, 'Type recurion is too deep' 
613
614     cdef __cinit__(self, DBusMessageIter *iter):
615         self.real_iter = iter[0]
616
617     cdef DBusMessageIter *_get_iter(self):
618         return self.iter
619
620     def has_next(self):
621         return dbus_message_iter_has_next(self.iter)
622     
623     def next(self):
624         return dbus_message_iter_next(self.iter)
625
626     def get(self, arg_type=None):
627         if(arg_type == None):
628             arg_type = self.get_arg_type()
629
630         if arg_type == TYPE_INVALID:
631             raise TypeError, 'Invalid arg type in MessageIter'
632         elif arg_type == TYPE_STRING:
633             retval = self.get_string()
634         elif arg_type == TYPE_INT16:
635             retval = self.get_int16()
636         elif arg_type == TYPE_UINT16:
637             retval = self.get_uint16()
638         elif arg_type == TYPE_INT32:
639             retval = self.get_int32()
640         elif arg_type == TYPE_UINT32:
641             retval = self.get_uint32()
642         elif arg_type == TYPE_INT64:
643             retval = self.get_int64()
644         elif arg_type == TYPE_UINT64:
645             retval = self.get_uint64()
646         elif arg_type == TYPE_DOUBLE:
647             retval = self.get_double()
648         elif arg_type == TYPE_BYTE:
649             retval = self.get_byte()
650         elif arg_type == TYPE_BOOLEAN:
651             retval = self.get_boolean()
652         elif arg_type == TYPE_SIGNATURE:
653             retval = self.get_signature()
654         elif arg_type == TYPE_ARRAY:
655             array_type = self.get_element_type()
656             if array_type == TYPE_DICT_ENTRY:
657                 retval = self.get_dict()
658             else:
659                 retval = self.get_array(array_type)
660         elif arg_type == TYPE_OBJECT_PATH:
661             retval = self.get_object_path()
662         elif arg_type == TYPE_STRUCT:
663             retval = self.get_struct()
664         elif arg_type == TYPE_VARIANT:
665             retval = self.get_variant()
666         elif arg_type == TYPE_DICT_ENTRY:
667             raise TypeError, 'Dictionary Entries can only appear as part of an array container'
668         else:
669             raise TypeError, 'Unknown arg type %d in MessageIter' % (arg_type)
670
671         return retval
672
673     def get_arg_type(self):
674         return dbus_message_iter_get_arg_type(self.iter)
675
676     def get_element_type(self):
677         return dbus_message_iter_get_element_type(self.iter)
678
679     def get_byte(self):
680         cdef char c_val
681         dbus_message_iter_get_basic(self.iter, <char *>&c_val)
682         return c_val
683         
684     def get_boolean(self):
685         cdef dbus_bool_t c_val
686         dbus_message_iter_get_basic(self.iter, <dbus_bool_t *>&c_val)
687
688         if c_val:
689             return True
690         else:
691             return False 
692
693     def get_signature(self):
694         signature_string = self.get_string()
695         return Signature(signature_string)
696
697     def get_int16(self):
698         cdef dbus_int16_t c_val
699         dbus_message_iter_get_basic(self.iter, <dbus_int16_t *>&c_val)
700
701         return c_val
702
703     def get_uint16(self):
704         cdef dbus_uint16_t c_val
705         dbus_message_iter_get_basic(self.iter, <dbus_uint16_t *>&c_val)
706         return c_val
707
708     def get_int32(self):
709         cdef dbus_int32_t c_val
710         dbus_message_iter_get_basic(self.iter, <dbus_int32_t *>&c_val)
711         return c_val
712         
713     def get_uint32(self):
714         cdef dbus_uint32_t c_val
715         dbus_message_iter_get_basic(self.iter, <dbus_uint32_t *>&c_val)
716         return c_val
717         
718     def get_int64(self):
719         cdef dbus_int64_t c_val
720         dbus_message_iter_get_basic(self.iter, <dbus_int64_t *>&c_val)
721         return c_val
722
723     def get_uint64(self):
724         cdef dbus_uint64_t c_val
725         dbus_message_iter_get_basic(self.iter, <dbus_uint64_t *>&c_val)
726         return c_val
727
728     def get_double(self):
729         cdef double c_val
730         dbus_message_iter_get_basic(self.iter, <double *>&c_val)
731         return c_val
732
733     def get_string(self):
734         cdef char *c_str
735         dbus_message_iter_get_basic(self.iter, <char **>&c_str)
736
737         return c_str
738
739     def get_object_path(self):
740         object_path_string = self.get_string()
741         return ObjectPath(object_path_string)
742
743     def get_dict(self):
744         cdef DBusMessageIter c_dict_iter
745         cdef MessageIter dict_iter
746         level = self.level + 1
747
748         dbus_message_iter_recurse(self.iter, <DBusMessageIter *>&c_dict_iter)
749         dict_iter = MessageIter(level)
750         dict_iter.__cinit__(&c_dict_iter)
751         
752         python_dict = {}
753         cur_arg_type = dict_iter.get_arg_type()
754         while cur_arg_type == TYPE_DICT_ENTRY:
755             if cur_arg_type != TYPE_DICT_ENTRY:
756                 raise TypeError, "Dictionary elements must be of type TYPE_DICT_ENTRY '%s != %s'" % (TYPE_DICT_ENTRY, cur_arg_type)
757                 
758             dict_entry = dict_iter.get_struct()
759             if len(dict_entry) != 2:
760                 raise TypeError, "Dictionary entries must be structs of two elements.  This entry had %i elements.'" % (len(dict_entry))
761
762             python_dict[dict_entry[0]] = dict_entry[1]
763             
764             dict_iter.next()
765             cur_arg_type = dict_iter.get_arg_type()
766
767         return python_dict
768    
769     def get_array(self, type):
770         cdef DBusMessageIter c_array_iter
771         cdef MessageIter array_iter
772         level = self.level + 1
773
774         dbus_message_iter_recurse(self.iter, <DBusMessageIter *>&c_array_iter)
775         array_iter = MessageIter(level)
776         array_iter.__cinit__(&c_array_iter)
777         
778         python_list = []
779         cur_arg_type = array_iter.get_arg_type()
780         while cur_arg_type != TYPE_INVALID:
781             if cur_arg_type != type:
782                 raise TypeError, "Array elements must be of the same type '%s != %s'" % (type, cur_arg_type)
783                 
784             value = array_iter.get(type)
785             python_list.append(value)
786             
787             array_iter.next()
788             cur_arg_type = array_iter.get_arg_type()
789
790         return python_list
791
792     def get_variant(self):
793         cdef DBusMessageIter c_var_iter
794         cdef MessageIter var_iter
795         level = self.level + 1
796
797         dbus_message_iter_recurse(self.iter, <DBusMessageIter *>&c_var_iter)
798         var_iter = MessageIter(level)
799         var_iter.__cinit__(&c_var_iter)
800         
801         return var_iter.get() 
802
803     def get_struct(self):
804         cdef DBusMessageIter c_struct_iter
805         cdef MessageIter struct_iter
806         level = self.level + 1
807
808         dbus_message_iter_recurse(self.iter, <DBusMessageIter *>&c_struct_iter)
809         struct_iter = MessageIter(level)
810         struct_iter.__cinit__(&c_struct_iter)
811
812         python_list = []
813         while struct_iter.get_arg_type() != TYPE_INVALID:
814             value = struct_iter.get()
815             python_list.append(value)
816             
817             struct_iter.next()
818
819         return tuple(python_list)
820
821     def python_value_to_dbus_sig(self, value, level = 0):
822
823         if(level > 32):
824             raise TypeError, 'Type recurion is too deep' 
825
826         level = level + 1
827
828         ptype = type(value)
829         ret = ""
830         if ptype == bool:
831             ret = TYPE_BOOL
832             ret = str(chr(ret))
833         elif ptype == int:
834             ret = TYPE_INT32
835             ret = str(chr(ret))
836         elif ptype == long:
837             ret = TYPE_INT64
838             ret = str(chr(ret))
839         elif ptype == str:
840             ret = TYPE_STRING
841             ret = str(chr(ret))
842         elif ptype == float:
843             ret = TYPE_DOUBLE
844             ret = str(chr(ret))
845         elif ptype == dict:
846             dict_list = value.items()
847             key, value = dict_list[0]
848
849             ret = str(chr(TYPE_ARRAY)) + str(chr(DICT_ENTRY_BEGIN))
850             ret = ret + self.python_value_to_dbus_sig(key, level)
851             ret = ret + self.python_value_to_dbus_sig(value, level)
852             ret = ret + str(chr(DICT_ENTRY_END))
853
854         elif ptype == tuple:
855             ret = str(chr(STRUCT_BEGIN))
856             for item in value:
857                 ret = ret + self.python_value_to_dbus_sig(item, level)
858             ret = ret + str(chr(STRUCT_END))
859         elif ptype == list:
860             ret = str(chr(TYPE_ARRAY))
861             ret = ret + self.python_value_to_dbus_sig(value[0], level)
862         elif isinstance(value, ObjectPath) or value == ObjectPath:
863
864             ret = TYPE_OBJECT_PATH
865             ret = str(chr(ret))
866         elif isinstance(value, ByteArray) or value == ByteArray:
867             ret = str(chr(TYPE_ARRAY)) + str(chr(TYPE_BYTE))
868         elif isinstance(value, Signature) or value == Signature:
869             ret = TYPE_SIGNATURE
870             ret = str(chr(ret))
871         elif isinstance(value, Byte) or value == Byte:
872             ret = TYPE_BYTE
873             ret = str(chr(ret))
874         elif isinstance(value, Boolean) or value == Boolean:
875             ret = TYPE_BOOL
876             ret = str(chr(ret))
877         elif isinstance(value, Int16) or value == Int16:
878             ret = TYPE_INT16
879             ret = str(chr(ret))
880         elif isinstance(value, UInt16) or value == UInt16:
881             ret = TYPE_UINT16
882             ret = str(chr(ret))
883         elif isinstance(value, Int32) or value == Int32:
884             ret = TYPE_INT32
885             ret = str(chr(ret))
886         elif isinstance(value, UInt32) or value == UInt32:
887             ret = TYPE_UINT32
888             ret = str(chr(ret))
889         elif isinstance(value, Int64) or value == Int64:
890             ret = TYPE_INT64
891             ret = str(chr(ret))
892         elif isinstance(value, UInt64) or value == UInt64:
893             ret = TYPE_UINT64
894             ret = str(chr(ret))
895         elif isinstance(value, Double) or value == Double:
896             ret = TYPE_DOUBLE
897             ret = str(chr(ret))
898         elif isinstance(value, String) or value == String:
899             ret = TYPE_STRING
900             ret = str(chr(ret))
901         elif isinstance(value, Array):
902             ret = str(chr(TYPE_ARRAY))
903             if value.type == None:
904                 if value.signature:
905                     ret = ret + value.signature
906                 else:
907                     ret = ret + self.python_value_to_dbus_sig(value[0], level)
908             else:
909                 ret = ret + self.python_value_to_dbus_sig(value.type, level)
910
911         elif isinstance(value, Struct) or value == Struct:
912             ret = str(chr(STRUCT_BEGIN))
913             for item in value:
914                 ret = ret + self.python_value_to_dbus_sig(item, level)
915             ret = ret + str(chr(STRUCT_END))
916         elif isinstance(value, Dictionary):
917             ret = str(chr(TYPE_ARRAY)) + str(chr(DICT_ENTRY_BEGIN))
918             
919             if value.key_type and value.value_type:
920                 ret = ret + self.python_value_to_dbus_sig(value.key_type, level)
921                 ret = ret + self.python_value_to_dbus_sig(value.value_type, level)
922             elif value.signature:
923                 ret = ret + value.signature
924             else:
925                 dict_list = value.items()
926
927                 key, val = dict_list[0]
928                 ret = ret + self.python_value_to_dbus_sig(key, level)
929                 ret = ret + self.python_value_to_dbus_sig(val, level)
930                 
931             ret = ret + str(chr(DICT_ENTRY_END))
932         elif isinstance(value, Variant) or value == Variant:
933             ret = ret + str(chr(TYPE_VARIANT))
934         else:
935             raise TypeError, "Argument of unknown type '%s'" % (ptype)
936
937         return ret
938
939     def parse_signature_block(self, signature):
940         remainder = ''
941         sig = ''
942         block_depth = 0
943         block_type = None
944        
945         for marker in range(0, len(signature)):
946             cur_sig = ord(signature[marker])
947
948             if cur_sig == TYPE_ARRAY:
949                 pass
950             elif cur_sig == DICT_ENTRY_BEGIN or cur_sig == STRUCT_BEGIN:
951                 if block_type == None:
952                     block_type = cur_sig
953
954                 if block_type == cur_sig:
955                     block_depth = block_depth + 1
956
957             elif cur_sig == DICT_ENTRY_END:
958                 if block_type == DICT_ENTRY_BEGIN:
959                     block_depth = block_depth - 1
960
961                 if block_depth == 0:
962                     break
963
964             elif cur_sig == STRUCT_END:
965                 if block_type == STRUCT_BEGIN:
966                     block_depth = block_depth - 1
967
968                 if block_depth == 0:
969                     break
970
971             else:
972                 if block_depth == 0:
973                     break
974         
975         marker = marker + 1
976         sig = signature[0:marker]
977         remainder = signature[marker:]
978         return (sig, remainder)
979   
980     def append_strict(self, value, sig):
981         
982     
983         if sig == TYPE_INVALID or sig == None:
984             raise TypeError, 'Invalid arg type sent to append_strict'
985
986         sig_type = ord(sig[0])
987             
988         if sig_type == TYPE_STRING:
989             retval = self.append(value)
990         elif sig_type == TYPE_INT16:
991             retval = self.append_int16(value)
992         elif sig_type == TYPE_UINT16:
993             retval = self.append_uint16(value)
994         elif sig_type == TYPE_INT32:
995             retval = self.append_int32(value)
996         elif sig_type == TYPE_UINT32:
997             retval = self.append_uint32(value)
998         elif sig_type == TYPE_INT64:
999             retval = self.append_int64(value)
1000         elif sig_type == TYPE_UINT64:
1001             retval = self.append_uint64(value)
1002         elif sig_type == TYPE_DOUBLE:
1003             retval = self.append_double(value)
1004         elif sig_type == TYPE_BYTE:
1005             retval = self.append_byte(value)
1006         elif sig_type == TYPE_BOOLEAN:
1007             retval = self.append_boolean(value)
1008         elif sig_type == TYPE_SIGNATURE:
1009             retval = self.append_signature(value)
1010         elif sig_type == TYPE_ARRAY:
1011             if len(sig) < 2:
1012                 raise TypeError, "Invalid array signature in append_strict.  Arrays must be followed by a type."
1013
1014             array_type = ord(sig[1])            
1015             if array_type == DICT_ENTRY_BEGIN:
1016                 if ord(sig[-1]) != DICT_ENTRY_END:
1017                     raise TypeError, "Invalid dict entry in append_strict.  No termination in signature %s."%(sig)
1018
1019                 tmp_sig = sig[2:-1]
1020                 retval = self.append_dict(Dictionary(value, signature=tmp_sig))
1021             else:
1022                 tmp_sig = sig[1:]
1023                 retval = self.append_array(Array(value, signature=tmp_sig))
1024         elif sig_type == TYPE_OBJECT_PATH:
1025             retval = self.append_object_path(value)
1026         elif sig_type == TYPE_STRUCT:
1027             tmp_sig = sig[1:-1]
1028             retval = self.append_struct(value, signature = tmp_sig)
1029         elif sig_type == TYPE_VARIANT:
1030             retval = self.append_variant(Variant(value))
1031         elif sig_type == DICT_ENTRY_BEGIN:
1032             raise TypeError, "Signiture is invalid in append_strict. A dict entry must be part of an array." 
1033         else:
1034             raise TypeError, "Argument of unknown type '%s' in append_strict" % (sig)
1035
1036         return retval
1037
1038     def append(self, value):
1039         value_type = type(value)
1040         if value_type == bool:
1041             retval = self.append_boolean(value)
1042         elif value_type == int:
1043             retval = self.append_int32(value)
1044         elif value_type == long:
1045             retval = self.append_int64(value)
1046         elif value_type == str:
1047             retval = self.append_string(value)
1048         elif value_type == float:
1049             retval = self.append_double(value)
1050         elif value_type == dict:
1051             retval = self.append_dict(value)
1052         elif value_type == tuple:
1053             retval = self.append_struct(value)
1054         elif value_type == list:
1055              retval = self.append_array(value)
1056         #elif value_type == None.__class__:
1057         #    retval = self.append_nil()
1058         elif isinstance(value, ObjectPath):
1059             retval = self.append_object_path(value)
1060         elif isinstance(value, ByteArray):
1061             retval = self.append_array(value)
1062         elif isinstance(value, Signature):
1063             retval = self.append_signature(value)
1064         elif isinstance(value, Byte):
1065             retval = self.append_byte(value)
1066         elif isinstance(value, Boolean):
1067             retval = self.append_boolean(value)
1068         elif isinstance(value, Int16):
1069             retval = self.append_int16(value)
1070         elif isinstance(value, UInt16):
1071             retval = self.append_uint16(value)
1072         elif isinstance(value, Int32):
1073             retval = self.append_int32(value)
1074         elif isinstance(value, UInt32):
1075             retval = self.append_uint32(value)
1076         elif isinstance(value, Int64):
1077             retval = self.append_int64(value)
1078         elif isinstance(value, UInt64):
1079             retval = self.append_uint64(value)
1080         elif isinstance(value, Double):
1081             retval = self.append_double(value)
1082         elif isinstance(value, String):
1083             retval = self.append_string(value)
1084         elif isinstance(value, Array):
1085             retval = self.append_array(value)
1086         elif isinstance(value, Struct):
1087             retval = self.append_struct(value)
1088         elif isinstance(value, Dictionary):
1089             retval = self.append_dict(value)
1090         elif isinstance(value, Variant):
1091             retval = self.append_variant(value)
1092         else:
1093             raise TypeError, "Argument of unknown type '%s'" % (value_type)
1094
1095         return retval
1096
1097     def append_boolean(self, value):
1098         cdef dbus_bool_t c_value
1099         c_value = value
1100         return dbus_message_iter_append_basic(self.iter, TYPE_BOOLEAN, <dbus_bool_t *>&c_value)
1101
1102     def append_byte(self, value):
1103         cdef char b
1104         if type(value) == str and len(value) == 1:
1105                 b = ord(value)
1106         elif type(value) == Byte:
1107                 b = value
1108         else:
1109             raise TypeError
1110
1111         return dbus_message_iter_append_basic(self.iter, TYPE_BYTE, <char *>&b)
1112
1113     def append_int16(self, value):
1114         cdef dbus_int32_t c_value
1115         c_value = value
1116         return dbus_message_iter_append_basic(self.iter, TYPE_INT16, <dbus_int32_t *>&c_value)
1117
1118     def append_uint16(self, value):
1119         cdef dbus_uint32_t c_value
1120         c_value = value
1121         return dbus_message_iter_append_basic(self.iter, TYPE_UINT16, <dbus_uint32_t *>&c_value)
1122
1123     def append_int32(self, value):
1124         cdef dbus_int32_t c_value
1125         c_value = value
1126         return dbus_message_iter_append_basic(self.iter, TYPE_INT32, <dbus_int32_t *>&c_value)
1127
1128     def append_uint32(self, value):
1129         cdef dbus_uint32_t c_value
1130         c_value = value
1131         return dbus_message_iter_append_basic(self.iter, TYPE_UINT32, <dbus_uint32_t *>&c_value)
1132
1133     def append_int64(self, value):
1134         cdef dbus_int64_t c_value
1135         c_value = value
1136         return dbus_message_iter_append_basic(self.iter, TYPE_INT64, <dbus_int64_t *>&c_value)
1137
1138     def append_uint64(self, value):
1139         cdef dbus_uint64_t c_value
1140         c_value = value
1141         return dbus_message_iter_append_basic(self.iter, TYPE_UINT64, <dbus_uint64_t *>&c_value)
1142
1143     def append_double(self, value):
1144         cdef double c_value
1145         c_value = value
1146         return dbus_message_iter_append_basic(self.iter, TYPE_DOUBLE, <double *>&c_value)
1147
1148     def append_string(self, value):
1149         cdef char *c_value
1150         c_value = value
1151         return dbus_message_iter_append_basic(self.iter, TYPE_STRING, <char **>&c_value)    
1152
1153     def append_object_path(self, value):
1154         cdef char *c_value
1155         c_value = value
1156         return dbus_message_iter_append_basic(self.iter, TYPE_OBJECT_PATH, <char **>&c_value)
1157
1158     def append_signature(self, value):
1159         cdef char *c_value
1160         c_value = value
1161         return dbus_message_iter_append_basic(self.iter, TYPE_SIGNATURE, <char **>&c_value)
1162
1163
1164     def append_dict(self, python_dict):
1165         cdef DBusMessageIter c_dict_iter, c_dict_entry_iter
1166         cdef MessageIter dict_iter, dict_entry_iter
1167         
1168         level = self.level + 1
1169
1170         key = None
1171         value = None
1172
1173         sig = str(chr(DICT_ENTRY_BEGIN))
1174
1175         if isinstance(python_dict, Dictionary):
1176             key = python_dict.key_type
1177             value = python_dict.value_type
1178             signature = python_dict.signature
1179
1180         dict_list = python_dict.items()
1181
1182         if signature:
1183             sig = sig + signature
1184         else: 
1185             if not (key and value):
1186                 key, value = dict_list[0]
1187
1188             sig = sig + self.python_value_to_dbus_sig(key)
1189             sig = sig + self.python_value_to_dbus_sig(value)
1190
1191         sig = sig + str(chr(DICT_ENTRY_END))
1192
1193         dbus_message_iter_open_container(self.iter, TYPE_ARRAY, sig, <DBusMessageIter *>&c_dict_iter)
1194         dict_iter = MessageIter(level)
1195         dict_iter.__cinit__(&c_dict_iter)
1196
1197         for key, value in dict_list:
1198             dbus_message_iter_open_container(dict_iter.iter, TYPE_DICT_ENTRY, sig, <DBusMessageIter *>&c_dict_entry_iter)
1199             dict_entry_iter = MessageIter(level)
1200             dict_entry_iter.__cinit__(&c_dict_entry_iter)
1201
1202             if signature:
1203                 (tmp_sig, remainder) = self.parse_signature_block(signature)
1204                 if not dict_entry_iter.append_strict(key, tmp_sig):
1205                     dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
1206                     dbus_message_iter_close_container(self.iter, dict_iter.iter)
1207                     return False
1208
1209                 (tmp_sig, remainder) = self.parse_signature_block(remainder)
1210                 if not dict_entry_iter.append_strict(value, tmp_sig):
1211                     dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
1212                     dbus_message_iter_close_container(self.iter, dict_iter.iter)
1213                     return False
1214
1215             else:
1216                 if not dict_entry_iter.append(key):
1217                     dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
1218                     dbus_message_iter_close_container(self.iter, dict_iter.iter)
1219                     return False
1220                 
1221                 if not dict_entry_iter.append(value):
1222                     dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
1223                     dbus_message_iter_close_container(self.iter, dict_iter.iter)
1224                     return False
1225
1226             dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
1227
1228         dbus_message_iter_close_container(self.iter, dict_iter.iter)
1229
1230         return True
1231
1232     def append_struct(self, python_struct, signature = None):
1233         cdef DBusMessageIter c_struct_iter
1234         cdef MessageIter struct_iter
1235
1236         level = self.level + 1
1237         dbus_message_iter_open_container(self.iter, TYPE_STRUCT, NULL, <DBusMessageIter *>&c_struct_iter)
1238         struct_iter = MessageIter(level)
1239         struct_iter.__cinit__(&c_struct_iter)
1240
1241         remainder = signature
1242         for item in python_struct:
1243             if signature:
1244                 (sig, remainder) = self.parse_signature_block(remainder)
1245
1246                 if sig == '':
1247                     dbus_message_iter_close_container(self.iter, struct_iter.iter)
1248                     return False
1249
1250                 if not struct_iter.append_strict(item, sig):
1251                     dbus_message_iter_close_container(self.iter, struct_iter.iter)
1252                     return False
1253             else:
1254                 if not struct_iter.append(item):
1255                     dbus_message_iter_close_container(self.iter, struct_iter.iter)
1256                     return False
1257
1258         dbus_message_iter_close_container(self.iter, struct_iter.iter)
1259
1260         return True
1261
1262     def append_array(self, python_list):
1263         cdef DBusMessageIter c_array_iter
1264         cdef MessageIter array_iter
1265
1266         level = self.level + 1
1267
1268         sig = None
1269         if isinstance(python_list, Array):
1270             if python_list.type:
1271                 sig = self.python_value_to_dbus_sig(python_list.type)
1272             elif python_list.signature:
1273                 sig = python_list.signature
1274             else:
1275                 sig = self.python_value_to_dbus_sig(python_list[0])
1276         else:
1277             sig = self.python_value_to_dbus_sig(python_list[0])
1278
1279         dbus_message_iter_open_container(self.iter, TYPE_ARRAY, sig, <DBusMessageIter *>&c_array_iter)
1280         array_iter = MessageIter(level)
1281         array_iter.__cinit__(&c_array_iter)
1282
1283         length = len(python_list)
1284         for item in python_list:
1285             if not array_iter.append_strict(item, sig):
1286                 dbus_message_iter_close_container(self.iter, array_iter.iter)
1287                 return False
1288
1289         dbus_message_iter_close_container(self.iter, array_iter.iter)
1290
1291         return True
1292
1293     def append_variant(self, value):
1294         cdef DBusMessageIter c_variant_iter
1295         cdef MessageIter variant_iter
1296
1297         level = self.level + 1
1298     
1299         if value.signature:
1300             sig = value.signature
1301         elif value.type:
1302             sig = self.python_value_to_dbus_sig(value.type)
1303         else:
1304             sig = self.python_value_to_dbus_sig(value.value)
1305     
1306         dbus_message_iter_open_container(self.iter, TYPE_VARIANT, sig, <DBusMessageIter *>&c_variant_iter)
1307         
1308         variant_iter = MessageIter(level)
1309         variant_iter.__cinit__(&c_variant_iter)
1310
1311         if not variant_iter.append(value.value):
1312             dbus_message_iter_close_container(self.iter, variant_iter.iter)
1313             return False
1314
1315         dbus_message_iter_close_container(self.iter, variant_iter.iter)
1316         return True
1317
1318     def __str__(self):
1319         cdef DBusMessageIter c_array_iter
1320         cdef MessageIter array_iter
1321
1322         value_at_iter = True
1323         retval = ""
1324         while (value_at_iter):
1325             type = self.get_arg_type()
1326             if type == TYPE_INVALID:
1327                 break
1328             elif type == TYPE_STRING:
1329                 str = iter.get_string()
1330                 arg = 'string:%s\n' % (str)
1331             elif type == TYPE_OBJECT_PATH:
1332                 path = iter.get_object_path()
1333                 arg = 'object_path:%s\n' % (path)
1334             elif type == TYPE_INT32:
1335                 num = iter.get_int32()
1336                 arg = 'int32:%d\n' % (num)
1337             elif type == TYPE_UINT32:
1338                 num = iter.get_uint32()
1339                 arg = 'uint32:%u\n' % (num)
1340             elif type == TYPE_INT64:
1341                 num = iter.get_int64()
1342                 arg = 'int64:%d\n' % (num)
1343             elif type == TYPE_UINT64:
1344                 num = iter.get_uint64()
1345                 arg = 'uint64:%u\n' % (num)
1346             elif type == TYPE_DOUBLE:
1347                 num = iter.get_double()
1348                 arg = 'double:%f\n' % (num)
1349             elif type == TYPE_BYTE:
1350                 num = iter.get_byte()
1351                 arg = 'byte:%x(%s)\n' % (num, str(chr(num)))
1352             elif type == TYPE_BOOLEAN:
1353                 bool = iter.get_boolean()
1354                 if (bool):
1355                     str = "true"
1356                 else:
1357                     str = "false"
1358                 arg = 'boolean:%s\n' % (str)
1359             elif type == TYPE_ARRAY:
1360                 dbus_message_iter_recurse(self.iter, <DBusMessageIter *>&c_array_iter)
1361                 array_iter = MessageIter(self.level + 1)
1362                 array_iter.__cinit__(&c_array_iter)
1363                 if array_iter.has_next():
1364                     arg = 'array [' + str(array_iter) + ']'
1365                 else:
1366                     arg = 'array []'
1367             else:
1368                 arg = '(unknown arg type %d)\n' % type
1369
1370             retval = retval + arg
1371             value_at_iter = self.next()
1372
1373         return retval
1374
1375
1376 (MESSAGE_TYPE_INVALID, MESSAGE_TYPE_METHOD_CALL, MESSAGE_TYPE_METHOD_RETURN, MESSAGE_TYPE_ERROR, MESSAGE_TYPE_SIGNAL) = range(5)
1377 (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('}'))
1378 (HANDLER_RESULT_HANDLED, HANDLER_RESULT_NOT_YET_HANDLED, HANDLER_RESULT_NEED_MEMORY) = range(3)
1379     
1380 cdef class Message:
1381     cdef DBusMessage *msg
1382
1383     def __init__(self, message_type=MESSAGE_TYPE_INVALID,
1384                  service=None, path=None, dbus_interface=None, method=None,
1385                  Message method_call=None,
1386                  name=None,
1387                  Message reply_to=None, error_name=None, error_message=None,
1388                  _create=1):
1389
1390         self.msg = NULL
1391
1392         cdef char *cservice
1393         cdef char *ciface
1394         cdef DBusMessage *cmsg
1395
1396         ciface = NULL
1397         if (dbus_interface != None):
1398             ciface = dbus_interface
1399
1400         cservice = NULL
1401         if (service != None):
1402             cservice = service
1403             
1404         if _create:
1405             if message_type == MESSAGE_TYPE_METHOD_CALL:
1406                 self.msg = dbus_message_new_method_call(cservice, path, ciface, method)
1407             elif message_type == MESSAGE_TYPE_METHOD_RETURN:
1408                 cmsg = method_call._get_msg()
1409                 self.msg = dbus_message_new_method_return(cmsg)
1410             elif message_type == MESSAGE_TYPE_SIGNAL:
1411                 self.msg = dbus_message_new_signal(path, ciface, name)
1412             elif message_type == MESSAGE_TYPE_ERROR:
1413                 cmsg = reply_to._get_msg()
1414                 self.msg = dbus_message_new_error(cmsg, error_name, error_message)
1415  
1416
1417     def __dealloc__(self):
1418         if self.msg != NULL:
1419             dbus_message_unref(self.msg)
1420             
1421     def type_to_name(self, type):
1422         if type == MESSAGE_TYPE_SIGNAL:
1423             return "signal"
1424         elif type == MESSAGE_TYPE_METHOD_CALL:
1425             return "method call"
1426         elif type == MESSAGE_TYPE_METHOD_RETURN:
1427             return "method return"
1428         elif type == MESSAGE_TYPE_ERROR:
1429             return "error"
1430         else:
1431             return "(unknown message type)"
1432
1433     def __str__(self):
1434         message_type = self.get_type()
1435         sender = self.get_sender()
1436
1437         if sender == None:
1438             sender = "(no sender)"
1439
1440         if (message_type == MESSAGE_TYPE_METHOD_CALL) or (message_type == MESSAGE_TYPE_SIGNAL):
1441             retval = '%s interface=%s; member=%s; sender=%s' % (self.type_to_name(message_type),
1442                                                                 self.get_interface(),
1443                                                                 self.get_member(),
1444                                                                 sender)
1445         elif message_type == MESSAGE_TYPE_METHOD_RETURN:
1446             retval = '%s sender=%s' % (self.type_to_name(message_type),
1447                                         sender)
1448         elif message_type == MESSAGE_TYPE_ERROR:
1449             retval = '%s name=%s; sender=%s' % (self.type_to_name(message_type),
1450                                                 self.get_error_name(),
1451                                                 sender)
1452         else:
1453             retval = "Message of unknown type %d" % (message_type)
1454
1455
1456         # FIXME: should really use self.convert_to_tuple() here
1457         
1458         iter = self.get_iter()
1459
1460         retval = retval + "\n" + str(iter) 
1461
1462         return retval
1463     
1464     cdef _set_msg(self, DBusMessage *msg):
1465         self.msg = msg
1466
1467     cdef DBusMessage *_get_msg(self):
1468         return self.msg
1469
1470     def get_iter(self, append=False):
1471         cdef DBusMessageIter iter
1472         cdef MessageIter message_iter
1473         cdef DBusMessage *msg
1474
1475         msg = self._get_msg()
1476
1477         if append:
1478             dbus_message_iter_init_append(msg, &iter)
1479         else:
1480             dbus_message_iter_init(msg, &iter)
1481
1482         message_iter = MessageIter(0)
1483         message_iter.__cinit__(&iter)
1484
1485         return message_iter
1486
1487     def get_args_list(self):
1488         retval = [ ]
1489
1490         iter = self.get_iter()
1491         try:
1492             retval.append(iter.get())
1493         except TypeError, e:
1494             return [ ]
1495             
1496         value_at_iter = iter.next()
1497         while (value_at_iter):
1498             retval.append(iter.get())
1499             value_at_iter = iter.next()        
1500
1501         return retval
1502             
1503     # FIXME: implement dbus_message_copy?
1504
1505     def get_type(self):
1506         return dbus_message_get_type(self.msg)
1507
1508     def set_path(self, object_path):
1509         return dbus_message_set_path(self.msg, object_path)
1510     
1511     def get_path(self):
1512         return dbus_message_get_path(self.msg)
1513     
1514     def set_interface(self, interface):
1515         return dbus_message_set_interface(self.msg, interface)
1516
1517     def get_interface(self):
1518         return dbus_message_get_interface(self.msg)    
1519
1520     def set_member(self, member):
1521         return dbus_message_set_member(self.msg, member)
1522
1523     def get_member(self):
1524         return dbus_message_get_member(self.msg)
1525
1526     def set_error_name(self, name):
1527         return dbus_message_set_error_name(self.msg, name)
1528
1529     def get_error_name(self):
1530         return dbus_message_get_error_name(self.msg)
1531
1532     def set_destination(self, destination):
1533         return dbus_message_set_destination(self.msg, destination)
1534
1535     def get_destination(self):
1536         return dbus_message_get_destination(self.msg)
1537
1538     def set_sender(self, sender):
1539         return dbus_message_set_sender(self.msg, sender)
1540     
1541     def get_sender(self):
1542         cdef char *sender
1543         sender = dbus_message_get_sender(self.msg)
1544         if (sender == NULL):
1545             return None
1546         else:
1547             return sender
1548
1549     def set_no_reply(self, no_reply):
1550         dbus_message_set_no_reply(self.msg, no_reply)
1551
1552     def get_no_reply(self):
1553         return dbus_message_get_no_reply(self.msg)
1554
1555     def is_method_call(self, interface, method):
1556         return dbus_message_is_method_call(self.msg, interface, method)
1557
1558     def is_signal(self, interface, signal_name):
1559         return dbus_message_is_signal(self.msg, interface, signal_name)
1560
1561     def is_error(self, error_name):
1562         return dbus_message_is_error(self.msg, error_name)
1563
1564     def has_destination(self, service):
1565         return dbus_message_has_destination(self.msg, service)
1566
1567     def has_sender(self, service):
1568         return dbus_message_has_sender(self.msg, service)
1569
1570     def get_serial(self):
1571         return dbus_message_get_serial(self.msg)
1572
1573     def set_reply_serial(self, reply_serial):
1574         return dbus_message_set_reply_serial(self.msg, reply_serial)
1575
1576     def get_reply_serial(self):
1577         return dbus_message_get_reply_serial(self.msg)    
1578
1579     #FIXME: dbus_message_get_path_decomposed
1580     
1581     # FIXME: all the different dbus_message_*args* methods
1582
1583 class Signal(Message):
1584     def __init__(self, spath, sinterface, sname):
1585         Message.__init__(self, MESSAGE_TYPE_SIGNAL, path=spath, dbus_interface=sinterface, name=sname)
1586
1587 class EmptyMessage(Message):
1588     def __init__(self):
1589         Message.__init__(self, _create=False)
1590
1591 class MethodCall(Message):
1592     def __init__(self, mpath, minterface, mmethod):
1593         Message.__init__(self, MESSAGE_TYPE_METHOD_CALL, path=mpath, dbus_interface=minterface, method=mmethod)
1594
1595 class MethodReturn(Message):
1596     def __init__(self, method_call):
1597         Message.__init__(self, MESSAGE_TYPE_METHOD_RETURN, method_call=method_call)
1598
1599 class Error(Message):
1600     def __init__(self, reply_to, error_name, error_message):
1601         Message.__init__(self, MESSAGE_TYPE_ERROR, reply_to=reply_to, error_name=error_name, error_message=error_message)
1602         
1603 cdef class Server:
1604     cdef DBusServer *server
1605     def __init__(self, address):
1606         cdef DBusError error
1607         dbus_error_init(&error)
1608         self.server = dbus_server_listen(address,
1609                                          &error)
1610         if dbus_error_is_set(&error):
1611             errormsg = error.message
1612             dbus_error_free (&error)
1613             raise DBusException, errormsg
1614
1615     def disconnect(self):
1616         dbus_server_disconnect(self.server)
1617
1618     def get_is_connected(self):
1619         return dbus_server_get_is_connected(self.server)
1620
1621 #    def set_new_connection_function(self, function, data):
1622 #        dbus_server_set_new_connection_function(self.conn, function,
1623 #                                                data, NULL)
1624         
1625 #    def set_watch_functions(self, add_function, remove_function, data):
1626 #        dbus_server_set_watch_functions(self.server,
1627 #                                        add_function, remove_function,
1628 #                                        data, NULL)
1629         
1630 #    def set_timeout_functions(self, add_function, remove_function, data):
1631 #        dbus_server_set_timeout_functions(self.server,
1632 #                                          add_function, remove_function,
1633 #                                          data, NULL)
1634         
1635 #    def handle_watch(self, watch, condition):
1636 #        dbus_server_handle_watch(self.conn, watch, condition)
1637
1638 BUS_SESSION = DBUS_BUS_SESSION
1639 BUS_SYSTEM = DBUS_BUS_SYSTEM
1640 BUS_STARTER = DBUS_BUS_STARTER
1641
1642 def bus_get (bus_type):
1643     cdef DBusError error
1644     cdef Connection conn
1645     dbus_error_init(&error)
1646     cdef DBusConnection *connection
1647
1648     connection = dbus_bus_get(bus_type,
1649                               &error)
1650
1651     if dbus_error_is_set(&error):
1652         errormsg = error.message
1653         dbus_error_free(&error)
1654         raise DBusException, errormsg 
1655
1656     conn = Connection()
1657     conn.__cinit__(None, connection)
1658     return conn 
1659
1660 def bus_get_unique_name(Connection connection):
1661     cdef DBusConnection *conn
1662     conn = connection._get_conn()
1663     return dbus_bus_get_unique_name(conn)
1664
1665 def bus_get_unix_user(Connection connection, service_name):
1666     cdef DBusError error
1667     dbus_error_init(&error)
1668     cdef int retval
1669     cdef DBusConnection *conn
1670
1671     conn = connection._get_conn()
1672     retval = dbus_bus_get_unix_user(conn, service_name, &error)
1673
1674     if dbus_error_is_set(&error):
1675         errormsg = error.message
1676         dbus_error_free(&error)
1677         raise DBusException, errormsg 
1678
1679     return retval
1680
1681 #These are defines, not enums so they aren't auto generated
1682 DBUS_START_REPLY_SUCCESS = 0 
1683 DBUS_START_REPLY_ALREADY_RUNNING = 1 
1684     
1685 def bus_start_service_by_name(Connection connection, service_name, flags=0):
1686     cdef DBusError error
1687     dbus_error_init(&error)
1688     cdef dbus_bool_t retval
1689     cdef dbus_uint32_t results
1690     cdef DBusConnection *conn
1691
1692     conn = connection._get_conn()
1693
1694     retval = dbus_bus_start_service_by_name(conn, service_name, flags, &results, &error)
1695
1696     if dbus_error_is_set(&error):
1697         errormsg = error.message
1698         dbus_error_free(&error)
1699         raise DBusException, errormsg
1700
1701     return (retval, results) 
1702
1703 def bus_register(Connection connection):
1704     cdef DBusError error
1705     dbus_error_init(&error)
1706     cdef dbus_bool_t retval
1707     cdef DBusConnection *conn
1708
1709     conn = connection._get_conn()
1710     retval = dbus_bus_register(conn,
1711                                &error)
1712     if dbus_error_is_set(&error):
1713         msg = error.message
1714         dbus_error_free(&error)
1715         raise DBusException, errormsg 
1716
1717     return retval
1718
1719 SERVICE_FLAG_PROHIBIT_REPLACEMENT = 0x1
1720 SERVICE_FLAG_REPLACE_EXISTING     = 0x2
1721
1722 def bus_request_name(Connection connection, service_name, flags=0):
1723     cdef DBusError error
1724     dbus_error_init(&error)
1725     cdef int retval
1726     cdef DBusConnection *conn
1727
1728     conn = connection._get_conn()
1729     retval = dbus_bus_request_name(conn,
1730                                    service_name,
1731                                    flags,
1732                                    &error)
1733     if dbus_error_is_set(&error):
1734         errormsg = error.message
1735         dbus_error_free(&error)
1736         raise DBusException, errormsg
1737         
1738     return retval
1739     
1740 def bus_name_has_owner(Connection connection, service_name):
1741     cdef DBusError error
1742     dbus_error_init(&error)
1743     cdef dbus_bool_t retval
1744     cdef DBusConnection *conn
1745
1746     conn = connection._get_conn()
1747     retval = dbus_bus_name_has_owner(conn,
1748                                      service_name,
1749                                      &error)
1750     if dbus_error_is_set(&error):
1751         errormsg = error.message
1752         dbus_error_free(&error)
1753         raise DBusException, errormsg
1754         
1755     return retval
1756
1757 def bus_add_match(Connection connection, rule):
1758     cdef DBusError error
1759     cdef DBusConnection *conn
1760
1761     dbus_error_init(&error)
1762     
1763     conn = connection._get_conn()
1764     dbus_bus_add_match (conn, rule, &error)
1765     
1766     if dbus_error_is_set(&error):
1767         errormsg = error.message
1768         dbus_error_free(&error)
1769         raise DBusException, errormsg
1770
1771 def bus_remove_match(Connection connection, rule):
1772     cdef DBusError error
1773     cdef DBusConnection *conn
1774
1775     dbus_error_init(&error)
1776
1777     conn = connection._get_conn()
1778     dbus_bus_remove_match (conn, rule, &error)
1779     
1780     if dbus_error_is_set(&error):
1781         errormsg = error.message
1782         dbus_error_free(&error)
1783         raise DBusException, errormsg
1784