* python/dbus_bindings.pyx (MessageIter::append_strict): check for
[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         if sig == TYPE_INVALID or sig == None:
983             raise TypeError, 'Invalid arg type sent to append_strict'
984
985         sig_type = ord(sig[0])
986             
987         if sig_type == TYPE_STRING:
988             retval = self.append(value)
989         elif sig_type == TYPE_INT16:
990             retval = self.append_int16(value)
991         elif sig_type == TYPE_UINT16:
992             retval = self.append_uint16(value)
993         elif sig_type == TYPE_INT32:
994             retval = self.append_int32(value)
995         elif sig_type == TYPE_UINT32:
996             retval = self.append_uint32(value)
997         elif sig_type == TYPE_INT64:
998             retval = self.append_int64(value)
999         elif sig_type == TYPE_UINT64:
1000             retval = self.append_uint64(value)
1001         elif sig_type == TYPE_DOUBLE:
1002             retval = self.append_double(value)
1003         elif sig_type == TYPE_BYTE:
1004             retval = self.append_byte(value)
1005         elif sig_type == TYPE_BOOLEAN:
1006             retval = self.append_boolean(value)
1007         elif sig_type == TYPE_SIGNATURE:
1008             retval = self.append_signature(value)
1009         elif sig_type == TYPE_ARRAY:
1010             if len(sig) < 2:
1011                 raise TypeError, "Invalid array signature in append_strict.  Arrays must be followed by a type."
1012
1013             array_type = ord(sig[1])            
1014             if array_type == DICT_ENTRY_BEGIN:
1015                 if ord(sig[-1]) != DICT_ENTRY_END:
1016                     raise TypeError, "Invalid dict entry in append_strict.  No termination in signature %s."%(sig)
1017
1018                 tmp_sig = sig[2:-1]
1019                 retval = self.append_dict(Dictionary(value, signature=tmp_sig))
1020             else:
1021                 tmp_sig = sig[1:]
1022                 retval = self.append_array(Array(value, signature=tmp_sig))
1023         elif sig_type == TYPE_OBJECT_PATH:
1024             retval = self.append_object_path(value)
1025         elif sig_type == STRUCT_BEGIN:
1026             tmp_sig = sig[1:-1]
1027             retval = self.append_struct(value, signature = tmp_sig)
1028         elif sig_type == TYPE_VARIANT:
1029             retval = self.append_variant(Variant(value))
1030         elif sig_type == DICT_ENTRY_BEGIN:
1031             raise TypeError, "Signiture is invalid in append_strict. A dict entry must be part of an array." 
1032         else:
1033             raise TypeError, "Argument of unknown type '%s' in append_strict" % (sig)
1034
1035         return retval
1036
1037     def append(self, value):
1038         value_type = type(value)
1039         if value_type == bool:
1040             retval = self.append_boolean(value)
1041         elif value_type == int:
1042             retval = self.append_int32(value)
1043         elif value_type == long:
1044             retval = self.append_int64(value)
1045         elif value_type == str:
1046             retval = self.append_string(value)
1047         elif value_type == float:
1048             retval = self.append_double(value)
1049         elif value_type == dict:
1050             retval = self.append_dict(value)
1051         elif value_type == tuple:
1052             retval = self.append_struct(value)
1053         elif value_type == list:
1054              retval = self.append_array(value)
1055         #elif value_type == None.__class__:
1056         #    retval = self.append_nil()
1057         elif isinstance(value, ObjectPath):
1058             retval = self.append_object_path(value)
1059         elif isinstance(value, ByteArray):
1060             retval = self.append_array(value)
1061         elif isinstance(value, Signature):
1062             retval = self.append_signature(value)
1063         elif isinstance(value, Byte):
1064             retval = self.append_byte(value)
1065         elif isinstance(value, Boolean):
1066             retval = self.append_boolean(value)
1067         elif isinstance(value, Int16):
1068             retval = self.append_int16(value)
1069         elif isinstance(value, UInt16):
1070             retval = self.append_uint16(value)
1071         elif isinstance(value, Int32):
1072             retval = self.append_int32(value)
1073         elif isinstance(value, UInt32):
1074             retval = self.append_uint32(value)
1075         elif isinstance(value, Int64):
1076             retval = self.append_int64(value)
1077         elif isinstance(value, UInt64):
1078             retval = self.append_uint64(value)
1079         elif isinstance(value, Double):
1080             retval = self.append_double(value)
1081         elif isinstance(value, String):
1082             retval = self.append_string(value)
1083         elif isinstance(value, Array):
1084             retval = self.append_array(value)
1085         elif isinstance(value, Struct):
1086             retval = self.append_struct(value)
1087         elif isinstance(value, Dictionary):
1088             retval = self.append_dict(value)
1089         elif isinstance(value, Variant):
1090             retval = self.append_variant(value)
1091         else:
1092             raise TypeError, "Argument of unknown type '%s'" % (value_type)
1093
1094         return retval
1095
1096     def append_boolean(self, value):
1097         cdef dbus_bool_t c_value
1098         c_value = value
1099         return dbus_message_iter_append_basic(self.iter, TYPE_BOOLEAN, <dbus_bool_t *>&c_value)
1100
1101     def append_byte(self, value):
1102         cdef char b
1103         if type(value) == str and len(value) == 1:
1104                 b = ord(value)
1105         elif type(value) == Byte:
1106                 b = value
1107         else:
1108             raise TypeError
1109
1110         return dbus_message_iter_append_basic(self.iter, TYPE_BYTE, <char *>&b)
1111
1112     def append_int16(self, value):
1113         cdef dbus_int32_t c_value
1114         c_value = value
1115         return dbus_message_iter_append_basic(self.iter, TYPE_INT16, <dbus_int32_t *>&c_value)
1116
1117     def append_uint16(self, value):
1118         cdef dbus_uint32_t c_value
1119         c_value = value
1120         return dbus_message_iter_append_basic(self.iter, TYPE_UINT16, <dbus_uint32_t *>&c_value)
1121
1122     def append_int32(self, value):
1123         cdef dbus_int32_t c_value
1124         c_value = value
1125         return dbus_message_iter_append_basic(self.iter, TYPE_INT32, <dbus_int32_t *>&c_value)
1126
1127     def append_uint32(self, value):
1128         cdef dbus_uint32_t c_value
1129         c_value = value
1130         return dbus_message_iter_append_basic(self.iter, TYPE_UINT32, <dbus_uint32_t *>&c_value)
1131
1132     def append_int64(self, value):
1133         cdef dbus_int64_t c_value
1134         c_value = value
1135         return dbus_message_iter_append_basic(self.iter, TYPE_INT64, <dbus_int64_t *>&c_value)
1136
1137     def append_uint64(self, value):
1138         cdef dbus_uint64_t c_value
1139         c_value = value
1140         return dbus_message_iter_append_basic(self.iter, TYPE_UINT64, <dbus_uint64_t *>&c_value)
1141
1142     def append_double(self, value):
1143         cdef double c_value
1144         c_value = value
1145         return dbus_message_iter_append_basic(self.iter, TYPE_DOUBLE, <double *>&c_value)
1146
1147     def append_string(self, value):
1148         cdef char *c_value
1149         c_value = value
1150         return dbus_message_iter_append_basic(self.iter, TYPE_STRING, <char **>&c_value)    
1151
1152     def append_object_path(self, value):
1153         cdef char *c_value
1154         c_value = value
1155         return dbus_message_iter_append_basic(self.iter, TYPE_OBJECT_PATH, <char **>&c_value)
1156
1157     def append_signature(self, value):
1158         cdef char *c_value
1159         c_value = value
1160         return dbus_message_iter_append_basic(self.iter, TYPE_SIGNATURE, <char **>&c_value)
1161
1162
1163     def append_dict(self, python_dict):
1164         cdef DBusMessageIter c_dict_iter, c_dict_entry_iter
1165         cdef MessageIter dict_iter, dict_entry_iter
1166         
1167         level = self.level + 1
1168
1169         key = None
1170         value = None
1171
1172         sig = str(chr(DICT_ENTRY_BEGIN))
1173
1174         if isinstance(python_dict, Dictionary):
1175             key = python_dict.key_type
1176             value = python_dict.value_type
1177             signature = python_dict.signature
1178
1179         dict_list = python_dict.items()
1180
1181         if signature:
1182             sig = sig + signature
1183         else: 
1184             if not (key and value):
1185                 key, value = dict_list[0]
1186
1187             sig = sig + self.python_value_to_dbus_sig(key)
1188             sig = sig + self.python_value_to_dbus_sig(value)
1189
1190         sig = sig + str(chr(DICT_ENTRY_END))
1191
1192         dbus_message_iter_open_container(self.iter, TYPE_ARRAY, sig, <DBusMessageIter *>&c_dict_iter)
1193         dict_iter = MessageIter(level)
1194         dict_iter.__cinit__(&c_dict_iter)
1195
1196         for key, value in dict_list:
1197             dbus_message_iter_open_container(dict_iter.iter, TYPE_DICT_ENTRY, sig, <DBusMessageIter *>&c_dict_entry_iter)
1198             dict_entry_iter = MessageIter(level)
1199             dict_entry_iter.__cinit__(&c_dict_entry_iter)
1200
1201             if signature:
1202                 (tmp_sig, remainder) = self.parse_signature_block(signature)
1203                 if not dict_entry_iter.append_strict(key, tmp_sig):
1204                     dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
1205                     dbus_message_iter_close_container(self.iter, dict_iter.iter)
1206                     return False
1207
1208                 (tmp_sig, remainder) = self.parse_signature_block(remainder)
1209                 if not dict_entry_iter.append_strict(value, tmp_sig):
1210                     dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
1211                     dbus_message_iter_close_container(self.iter, dict_iter.iter)
1212                     return False
1213
1214             else:
1215                 if not dict_entry_iter.append(key):
1216                     dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
1217                     dbus_message_iter_close_container(self.iter, dict_iter.iter)
1218                     return False
1219                 
1220                 if not dict_entry_iter.append(value):
1221                     dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
1222                     dbus_message_iter_close_container(self.iter, dict_iter.iter)
1223                     return False
1224
1225             dbus_message_iter_close_container(dict_iter.iter, dict_entry_iter.iter)
1226
1227         dbus_message_iter_close_container(self.iter, dict_iter.iter)
1228
1229         return True
1230
1231     def append_struct(self, python_struct, signature = None):
1232         cdef DBusMessageIter c_struct_iter
1233         cdef MessageIter struct_iter
1234
1235         level = self.level + 1
1236         dbus_message_iter_open_container(self.iter, TYPE_STRUCT, NULL, <DBusMessageIter *>&c_struct_iter)
1237         struct_iter = MessageIter(level)
1238         struct_iter.__cinit__(&c_struct_iter)
1239
1240         remainder = signature
1241         for item in python_struct:
1242             if signature:
1243                 (sig, remainder) = self.parse_signature_block(remainder)
1244
1245                 if sig == '':
1246                     dbus_message_iter_close_container(self.iter, struct_iter.iter)
1247                     return False
1248
1249                 if not struct_iter.append_strict(item, sig):
1250                     dbus_message_iter_close_container(self.iter, struct_iter.iter)
1251                     return False
1252             else:
1253                 if not struct_iter.append(item):
1254                     dbus_message_iter_close_container(self.iter, struct_iter.iter)
1255                     return False
1256
1257         dbus_message_iter_close_container(self.iter, struct_iter.iter)
1258
1259         return True
1260
1261     def append_array(self, python_list):
1262         cdef DBusMessageIter c_array_iter
1263         cdef MessageIter array_iter
1264
1265         level = self.level + 1
1266
1267         sig = None
1268         if isinstance(python_list, Array):
1269             if python_list.type:
1270                 sig = self.python_value_to_dbus_sig(python_list.type)
1271             elif python_list.signature:
1272                 sig = python_list.signature
1273             else:
1274                 sig = self.python_value_to_dbus_sig(python_list[0])
1275         else:
1276             sig = self.python_value_to_dbus_sig(python_list[0])
1277
1278         dbus_message_iter_open_container(self.iter, TYPE_ARRAY, sig, <DBusMessageIter *>&c_array_iter)
1279         array_iter = MessageIter(level)
1280         array_iter.__cinit__(&c_array_iter)
1281
1282         length = len(python_list)
1283         for item in python_list:
1284             if not array_iter.append_strict(item, sig):
1285                 dbus_message_iter_close_container(self.iter, array_iter.iter)
1286                 return False
1287
1288         dbus_message_iter_close_container(self.iter, array_iter.iter)
1289
1290         return True
1291
1292     def append_variant(self, value):
1293         cdef DBusMessageIter c_variant_iter
1294         cdef MessageIter variant_iter
1295
1296         level = self.level + 1
1297     
1298         if value.signature:
1299             sig = value.signature
1300         elif value.type:
1301             sig = self.python_value_to_dbus_sig(value.type)
1302         else:
1303             sig = self.python_value_to_dbus_sig(value.value)
1304     
1305         dbus_message_iter_open_container(self.iter, TYPE_VARIANT, sig, <DBusMessageIter *>&c_variant_iter)
1306         
1307         variant_iter = MessageIter(level)
1308         variant_iter.__cinit__(&c_variant_iter)
1309
1310         if not variant_iter.append(value.value):
1311             dbus_message_iter_close_container(self.iter, variant_iter.iter)
1312             return False
1313
1314         dbus_message_iter_close_container(self.iter, variant_iter.iter)
1315         return True
1316
1317     def __str__(self):
1318         cdef DBusMessageIter c_array_iter
1319         cdef MessageIter array_iter
1320
1321         value_at_iter = True
1322         retval = ""
1323         while (value_at_iter):
1324             type = self.get_arg_type()
1325             if type == TYPE_INVALID:
1326                 break
1327             elif type == TYPE_STRING:
1328                 str = iter.get_string()
1329                 arg = 'string:%s\n' % (str)
1330             elif type == TYPE_OBJECT_PATH:
1331                 path = iter.get_object_path()
1332                 arg = 'object_path:%s\n' % (path)
1333             elif type == TYPE_INT32:
1334                 num = iter.get_int32()
1335                 arg = 'int32:%d\n' % (num)
1336             elif type == TYPE_UINT32:
1337                 num = iter.get_uint32()
1338                 arg = 'uint32:%u\n' % (num)
1339             elif type == TYPE_INT64:
1340                 num = iter.get_int64()
1341                 arg = 'int64:%d\n' % (num)
1342             elif type == TYPE_UINT64:
1343                 num = iter.get_uint64()
1344                 arg = 'uint64:%u\n' % (num)
1345             elif type == TYPE_DOUBLE:
1346                 num = iter.get_double()
1347                 arg = 'double:%f\n' % (num)
1348             elif type == TYPE_BYTE:
1349                 num = iter.get_byte()
1350                 arg = 'byte:%x(%s)\n' % (num, str(chr(num)))
1351             elif type == TYPE_BOOLEAN:
1352                 bool = iter.get_boolean()
1353                 if (bool):
1354                     str = "true"
1355                 else:
1356                     str = "false"
1357                 arg = 'boolean:%s\n' % (str)
1358             elif type == TYPE_ARRAY:
1359                 dbus_message_iter_recurse(self.iter, <DBusMessageIter *>&c_array_iter)
1360                 array_iter = MessageIter(self.level + 1)
1361                 array_iter.__cinit__(&c_array_iter)
1362                 if array_iter.has_next():
1363                     arg = 'array [' + str(array_iter) + ']'
1364                 else:
1365                     arg = 'array []'
1366             else:
1367                 arg = '(unknown arg type %d)\n' % type
1368
1369             retval = retval + arg
1370             value_at_iter = self.next()
1371
1372         return retval
1373
1374
1375 (MESSAGE_TYPE_INVALID, MESSAGE_TYPE_METHOD_CALL, MESSAGE_TYPE_METHOD_RETURN, MESSAGE_TYPE_ERROR, MESSAGE_TYPE_SIGNAL) = range(5)
1376 (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('}'))
1377 (HANDLER_RESULT_HANDLED, HANDLER_RESULT_NOT_YET_HANDLED, HANDLER_RESULT_NEED_MEMORY) = range(3)
1378     
1379 cdef class Message:
1380     cdef DBusMessage *msg
1381
1382     def __init__(self, message_type=MESSAGE_TYPE_INVALID,
1383                  service=None, path=None, dbus_interface=None, method=None,
1384                  Message method_call=None,
1385                  name=None,
1386                  Message reply_to=None, error_name=None, error_message=None,
1387                  _create=1):
1388
1389         self.msg = NULL
1390
1391         cdef char *cservice
1392         cdef char *ciface
1393         cdef DBusMessage *cmsg
1394
1395         ciface = NULL
1396         if (dbus_interface != None):
1397             ciface = dbus_interface
1398
1399         cservice = NULL
1400         if (service != None):
1401             cservice = service
1402             
1403         if _create:
1404             if message_type == MESSAGE_TYPE_METHOD_CALL:
1405                 self.msg = dbus_message_new_method_call(cservice, path, ciface, method)
1406             elif message_type == MESSAGE_TYPE_METHOD_RETURN:
1407                 cmsg = method_call._get_msg()
1408                 self.msg = dbus_message_new_method_return(cmsg)
1409             elif message_type == MESSAGE_TYPE_SIGNAL:
1410                 self.msg = dbus_message_new_signal(path, ciface, name)
1411             elif message_type == MESSAGE_TYPE_ERROR:
1412                 cmsg = reply_to._get_msg()
1413                 self.msg = dbus_message_new_error(cmsg, error_name, error_message)
1414  
1415
1416     def __dealloc__(self):
1417         if self.msg != NULL:
1418             dbus_message_unref(self.msg)
1419             
1420     def type_to_name(self, type):
1421         if type == MESSAGE_TYPE_SIGNAL:
1422             return "signal"
1423         elif type == MESSAGE_TYPE_METHOD_CALL:
1424             return "method call"
1425         elif type == MESSAGE_TYPE_METHOD_RETURN:
1426             return "method return"
1427         elif type == MESSAGE_TYPE_ERROR:
1428             return "error"
1429         else:
1430             return "(unknown message type)"
1431
1432     def __str__(self):
1433         message_type = self.get_type()
1434         sender = self.get_sender()
1435
1436         if sender == None:
1437             sender = "(no sender)"
1438
1439         if (message_type == MESSAGE_TYPE_METHOD_CALL) or (message_type == MESSAGE_TYPE_SIGNAL):
1440             retval = '%s interface=%s; member=%s; sender=%s' % (self.type_to_name(message_type),
1441                                                                 self.get_interface(),
1442                                                                 self.get_member(),
1443                                                                 sender)
1444         elif message_type == MESSAGE_TYPE_METHOD_RETURN:
1445             retval = '%s sender=%s' % (self.type_to_name(message_type),
1446                                         sender)
1447         elif message_type == MESSAGE_TYPE_ERROR:
1448             retval = '%s name=%s; sender=%s' % (self.type_to_name(message_type),
1449                                                 self.get_error_name(),
1450                                                 sender)
1451         else:
1452             retval = "Message of unknown type %d" % (message_type)
1453
1454
1455         # FIXME: should really use self.convert_to_tuple() here
1456         
1457         iter = self.get_iter()
1458
1459         retval = retval + "\n" + str(iter) 
1460
1461         return retval
1462     
1463     cdef _set_msg(self, DBusMessage *msg):
1464         self.msg = msg
1465
1466     cdef DBusMessage *_get_msg(self):
1467         return self.msg
1468
1469     def get_iter(self, append=False):
1470         cdef DBusMessageIter iter
1471         cdef MessageIter message_iter
1472         cdef DBusMessage *msg
1473
1474         msg = self._get_msg()
1475
1476         if append:
1477             dbus_message_iter_init_append(msg, &iter)
1478         else:
1479             dbus_message_iter_init(msg, &iter)
1480
1481         message_iter = MessageIter(0)
1482         message_iter.__cinit__(&iter)
1483
1484         return message_iter
1485
1486     def get_args_list(self):
1487         retval = [ ]
1488
1489         iter = self.get_iter()
1490         try:
1491             retval.append(iter.get())
1492         except TypeError, e:
1493             return [ ]
1494             
1495         value_at_iter = iter.next()
1496         while (value_at_iter):
1497             retval.append(iter.get())
1498             value_at_iter = iter.next()        
1499
1500         return retval
1501             
1502     # FIXME: implement dbus_message_copy?
1503
1504     def get_type(self):
1505         return dbus_message_get_type(self.msg)
1506
1507     def set_path(self, object_path):
1508         return dbus_message_set_path(self.msg, object_path)
1509     
1510     def get_path(self):
1511         return dbus_message_get_path(self.msg)
1512     
1513     def set_interface(self, interface):
1514         return dbus_message_set_interface(self.msg, interface)
1515
1516     def get_interface(self):
1517         return dbus_message_get_interface(self.msg)    
1518
1519     def set_member(self, member):
1520         return dbus_message_set_member(self.msg, member)
1521
1522     def get_member(self):
1523         return dbus_message_get_member(self.msg)
1524
1525     def set_error_name(self, name):
1526         return dbus_message_set_error_name(self.msg, name)
1527
1528     def get_error_name(self):
1529         return dbus_message_get_error_name(self.msg)
1530
1531     def set_destination(self, destination):
1532         return dbus_message_set_destination(self.msg, destination)
1533
1534     def get_destination(self):
1535         return dbus_message_get_destination(self.msg)
1536
1537     def set_sender(self, sender):
1538         return dbus_message_set_sender(self.msg, sender)
1539     
1540     def get_sender(self):
1541         cdef char *sender
1542         sender = dbus_message_get_sender(self.msg)
1543         if (sender == NULL):
1544             return None
1545         else:
1546             return sender
1547
1548     def set_no_reply(self, no_reply):
1549         dbus_message_set_no_reply(self.msg, no_reply)
1550
1551     def get_no_reply(self):
1552         return dbus_message_get_no_reply(self.msg)
1553
1554     def is_method_call(self, interface, method):
1555         return dbus_message_is_method_call(self.msg, interface, method)
1556
1557     def is_signal(self, interface, signal_name):
1558         return dbus_message_is_signal(self.msg, interface, signal_name)
1559
1560     def is_error(self, error_name):
1561         return dbus_message_is_error(self.msg, error_name)
1562
1563     def has_destination(self, service):
1564         return dbus_message_has_destination(self.msg, service)
1565
1566     def has_sender(self, service):
1567         return dbus_message_has_sender(self.msg, service)
1568
1569     def get_serial(self):
1570         return dbus_message_get_serial(self.msg)
1571
1572     def set_reply_serial(self, reply_serial):
1573         return dbus_message_set_reply_serial(self.msg, reply_serial)
1574
1575     def get_reply_serial(self):
1576         return dbus_message_get_reply_serial(self.msg)    
1577
1578     #FIXME: dbus_message_get_path_decomposed
1579     
1580     # FIXME: all the different dbus_message_*args* methods
1581
1582 class Signal(Message):
1583     def __init__(self, spath, sinterface, sname):
1584         Message.__init__(self, MESSAGE_TYPE_SIGNAL, path=spath, dbus_interface=sinterface, name=sname)
1585
1586 class EmptyMessage(Message):
1587     def __init__(self):
1588         Message.__init__(self, _create=False)
1589
1590 class MethodCall(Message):
1591     def __init__(self, mpath, minterface, mmethod):
1592         Message.__init__(self, MESSAGE_TYPE_METHOD_CALL, path=mpath, dbus_interface=minterface, method=mmethod)
1593
1594 class MethodReturn(Message):
1595     def __init__(self, method_call):
1596         Message.__init__(self, MESSAGE_TYPE_METHOD_RETURN, method_call=method_call)
1597
1598 class Error(Message):
1599     def __init__(self, reply_to, error_name, error_message):
1600         Message.__init__(self, MESSAGE_TYPE_ERROR, reply_to=reply_to, error_name=error_name, error_message=error_message)
1601         
1602 cdef class Server:
1603     cdef DBusServer *server
1604     def __init__(self, address):
1605         cdef DBusError error
1606         dbus_error_init(&error)
1607         self.server = dbus_server_listen(address,
1608                                          &error)
1609         if dbus_error_is_set(&error):
1610             errormsg = error.message
1611             dbus_error_free (&error)
1612             raise DBusException, errormsg
1613
1614     def disconnect(self):
1615         dbus_server_disconnect(self.server)
1616
1617     def get_is_connected(self):
1618         return dbus_server_get_is_connected(self.server)
1619
1620 #    def set_new_connection_function(self, function, data):
1621 #        dbus_server_set_new_connection_function(self.conn, function,
1622 #                                                data, NULL)
1623         
1624 #    def set_watch_functions(self, add_function, remove_function, data):
1625 #        dbus_server_set_watch_functions(self.server,
1626 #                                        add_function, remove_function,
1627 #                                        data, NULL)
1628         
1629 #    def set_timeout_functions(self, add_function, remove_function, data):
1630 #        dbus_server_set_timeout_functions(self.server,
1631 #                                          add_function, remove_function,
1632 #                                          data, NULL)
1633         
1634 #    def handle_watch(self, watch, condition):
1635 #        dbus_server_handle_watch(self.conn, watch, condition)
1636
1637 BUS_SESSION = DBUS_BUS_SESSION
1638 BUS_SYSTEM = DBUS_BUS_SYSTEM
1639 BUS_STARTER = DBUS_BUS_STARTER
1640
1641 def bus_get (bus_type):
1642     cdef DBusError error
1643     cdef Connection conn
1644     dbus_error_init(&error)
1645     cdef DBusConnection *connection
1646
1647     connection = dbus_bus_get(bus_type,
1648                               &error)
1649
1650     if dbus_error_is_set(&error):
1651         errormsg = error.message
1652         dbus_error_free(&error)
1653         raise DBusException, errormsg 
1654
1655     conn = Connection()
1656     conn.__cinit__(None, connection)
1657     return conn 
1658
1659 def bus_get_unique_name(Connection connection):
1660     cdef DBusConnection *conn
1661     conn = connection._get_conn()
1662     return dbus_bus_get_unique_name(conn)
1663
1664 def bus_get_unix_user(Connection connection, service_name):
1665     cdef DBusError error
1666     dbus_error_init(&error)
1667     cdef int retval
1668     cdef DBusConnection *conn
1669
1670     conn = connection._get_conn()
1671     retval = dbus_bus_get_unix_user(conn, service_name, &error)
1672
1673     if dbus_error_is_set(&error):
1674         errormsg = error.message
1675         dbus_error_free(&error)
1676         raise DBusException, errormsg 
1677
1678     return retval
1679
1680 #These are defines, not enums so they aren't auto generated
1681 DBUS_START_REPLY_SUCCESS = 0 
1682 DBUS_START_REPLY_ALREADY_RUNNING = 1 
1683     
1684 def bus_start_service_by_name(Connection connection, service_name, flags=0):
1685     cdef DBusError error
1686     dbus_error_init(&error)
1687     cdef dbus_bool_t retval
1688     cdef dbus_uint32_t results
1689     cdef DBusConnection *conn
1690
1691     conn = connection._get_conn()
1692
1693     retval = dbus_bus_start_service_by_name(conn, service_name, flags, &results, &error)
1694
1695     if dbus_error_is_set(&error):
1696         errormsg = error.message
1697         dbus_error_free(&error)
1698         raise DBusException, errormsg
1699
1700     return (retval, results) 
1701
1702 def bus_register(Connection connection):
1703     cdef DBusError error
1704     dbus_error_init(&error)
1705     cdef dbus_bool_t retval
1706     cdef DBusConnection *conn
1707
1708     conn = connection._get_conn()
1709     retval = dbus_bus_register(conn,
1710                                &error)
1711     if dbus_error_is_set(&error):
1712         msg = error.message
1713         dbus_error_free(&error)
1714         raise DBusException, errormsg 
1715
1716     return retval
1717
1718 SERVICE_FLAG_PROHIBIT_REPLACEMENT = 0x1
1719 SERVICE_FLAG_REPLACE_EXISTING     = 0x2
1720
1721 def bus_request_name(Connection connection, service_name, flags=0):
1722     cdef DBusError error
1723     dbus_error_init(&error)
1724     cdef int retval
1725     cdef DBusConnection *conn
1726
1727     conn = connection._get_conn()
1728     retval = dbus_bus_request_name(conn,
1729                                    service_name,
1730                                    flags,
1731                                    &error)
1732     if dbus_error_is_set(&error):
1733         errormsg = error.message
1734         dbus_error_free(&error)
1735         raise DBusException, errormsg
1736         
1737     return retval
1738     
1739 def bus_name_has_owner(Connection connection, service_name):
1740     cdef DBusError error
1741     dbus_error_init(&error)
1742     cdef dbus_bool_t retval
1743     cdef DBusConnection *conn
1744
1745     conn = connection._get_conn()
1746     retval = dbus_bus_name_has_owner(conn,
1747                                      service_name,
1748                                      &error)
1749     if dbus_error_is_set(&error):
1750         errormsg = error.message
1751         dbus_error_free(&error)
1752         raise DBusException, errormsg
1753         
1754     return retval
1755
1756 def bus_add_match(Connection connection, rule):
1757     cdef DBusError error
1758     cdef DBusConnection *conn
1759
1760     dbus_error_init(&error)
1761     
1762     conn = connection._get_conn()
1763     dbus_bus_add_match (conn, rule, &error)
1764     
1765     if dbus_error_is_set(&error):
1766         errormsg = error.message
1767         dbus_error_free(&error)
1768         raise DBusException, errormsg
1769
1770 def bus_remove_match(Connection connection, rule):
1771     cdef DBusError error
1772     cdef DBusConnection *conn
1773
1774     dbus_error_init(&error)
1775
1776     conn = connection._get_conn()
1777     dbus_bus_remove_match (conn, rule, &error)
1778     
1779     if dbus_error_is_set(&error):
1780         errormsg = error.message
1781         dbus_error_free(&error)
1782         raise DBusException, errormsg
1783