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