2004-09-16 David Zeuthen <david@fubar.dk>
[platform/upstream/dbus.git] / python / dbus_bindings.pyx.in
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 #include "dbus_h_wrapper.h"
9
10 cdef extern from "stdlib.h":
11     cdef void *malloc(size_t size)
12     cdef void free(void *ptr)
13     cdef void *calloc(size_t nmemb, size_t size)
14
15 cdef extern from "dbus-glib.h":
16     ctypedef struct GMainContext
17     cdef void dbus_connection_setup_with_g_main (DBusConnection *connection,
18                                                  GMainContext   *context)
19     cdef void dbus_server_setup_with_g_main     (DBusServer     *server,
20                                                  GMainContext   *context)
21     cdef void dbus_g_thread_init ()
22
23 cdef extern from "Python.h":
24     void Py_XINCREF (object)
25     void Py_XDECREF (object)
26     object PyString_FromStringAndSize(char *, int)
27
28 ctypedef struct DBusError:
29     char *name
30     char *message
31     unsigned int dummy1 
32     unsigned int dummy2
33     unsigned int dummy3
34     unsigned int dummy4
35     unsigned int dummy5
36     void *padding1
37     
38 ctypedef struct DBusMessageIter:
39     void *dummy1
40     void *dummy2
41     dbus_uint32_t dummy3
42     int dummy4
43     int dummy5
44     int dummy6
45     int dummy7
46     int dummy8
47     int dummy9
48     int dummy10
49     int dummy11
50     int pad1
51     int pad2
52     void *pad3
53
54 ctypedef struct DBusObjectPathVTable:
55   DBusObjectPathUnregisterFunction   unregister_function
56   DBusObjectPathMessageFunction      message_function
57   void (* dbus_internal_pad1) (void *)
58   void (* dbus_internal_pad2) (void *)
59   void (* dbus_internal_pad3) (void *)
60   void (* dbus_internal_pad4) (void *)
61
62
63 _user_data_references = [ ]
64
65 class DBusException(Exception):
66     pass
67
68 class ConnectionError(Exception):
69     pass
70
71 class ObjectPath(str):
72     def __init__(self, value):
73         str.__init__(value)
74
75 class ByteArray(str):
76     def __init__(self, value):
77         str.__init__(value)
78
79
80 #forward delcerations
81 cdef class Connection
82 cdef class Message
83 cdef class PendingCall
84 cdef class Watch
85 cdef class MessageIter
86
87 cdef void cunregister_function_handler (DBusConnection *connection,
88                                         void *user_data):
89     cdef Connection conn
90     tup = <object>user_data
91     assert (type(tup) == list)    
92     function = tup[1]
93     conn = Connection()
94     conn.__cinit__(None, connection)
95
96     args = [conn]
97     function(*args)
98
99 cdef DBusHandlerResult cmessage_function_handler (DBusConnection *connection,
100                                                   DBusMessage *msg,
101                                                   void *user_data):
102     cdef Connection conn
103     cdef Message message
104
105     tup = <object>user_data
106     assert (type(tup) == list)
107     function = tup[0]
108     message = Message(_create=0)
109     message._set_msg(msg)
110   
111     conn = Connection()
112     conn.__cinit__(None, connection)  
113  
114     args = [conn,
115             message]
116     retval = function(*args)
117     if (retval == None):
118         retval = DBUS_HANDLER_RESULT_HANDLED
119
120     return retval
121
122 cdef class Connection:
123     cdef DBusConnection *conn
124     
125     def __init__(self, address=None, Connection _conn=None):
126         cdef DBusConnection *c_conn
127         cdef char *c_address
128         c_conn=NULL
129         if (_conn != None):
130             c_conn = _conn.conn
131
132         if (address != None or _conn != None):
133             self.__cinit__(c_address, c_conn)
134
135     # hack to be able to pass in a c pointer to the constructor
136     # while still alowing python programs to create a Connection object
137     cdef __cinit__(self, address, DBusConnection *_conn):
138         cdef DBusError error
139         dbus_error_init(&error)
140         if _conn != NULL:
141             self.conn = _conn
142             dbus_connection_ref(self.conn)
143         else:
144             self.conn = dbus_connection_open(address,
145                                          &error)
146             if dbus_error_is_set(&error):
147                 raise DBusException, error.message
148
149
150     cdef _set_conn(self, DBusConnection *conn):
151         self.conn = conn
152     
153     cdef DBusConnection *_get_conn(self):
154         return self.conn
155     
156     def get_base_service(self):
157         return bus_get_base_service(self)
158
159     def setup_with_g_main(self):
160         dbus_connection_setup_with_g_main(self.conn, NULL)
161
162     def disconnect(self):
163         dbus_connection_disconnect(self.conn)
164
165     def get_is_connected(self):
166         return dbus_connection_get_is_connected(self.conn)
167     
168     def get_is_authenticated(self):
169         return dbus_connection_get_is_authenticated(self.conn)
170
171     def flush(self):
172         dbus_connection_flush(self.conn)
173
174     def borrow_message(self):
175         cdef Message m
176         m = Message(_create=0)
177         m._set_msg(dbus_connection_borrow_message(self.conn))
178         return m
179     
180     def return_message(self, Message message):
181         cdef DBusMessage *msg
182         msg = message._get_msg()
183         dbus_connection_return_message(self.conn, msg)
184
185     def steal_borrowed_message(self, Message message):
186         cdef DBusMessage *msg
187         msg = message._get_msg()
188         dbus_connection_steal_borrowed_message(self.conn,
189                                                msg)
190     
191     def pop_message(self):
192         cdef DBusMessage *msg
193         cdef Message m
194  
195         msg = dbus_connection_pop_message(self.conn)
196         if msg != NULL:
197             m = Message(_create=0)
198             m._set_msg(msg)
199         else:
200             m = None
201         return m        
202
203     def get_dispatch_status(self):
204         return dbus_connection_get_dispatch_status(self.conn)
205     
206     def dispatch(self):
207         return dbus_connection_dispatch(self.conn)
208
209     def send(self, Message message):
210         #cdef dbus_uint32_t client_serial
211         #if type(message) != Message:
212         #    raise TypeError
213         cdef DBusMessage *msg
214         msg = message._get_msg()
215         retval = dbus_connection_send(self.conn,
216                                       msg,
217                                       NULL)
218         return retval
219
220     def send_with_reply(self, Message message, timeout_milliseconds):
221         cdef dbus_bool_t retval
222         cdef DBusPendingCall *cpending_call
223         cdef DBusError error
224         cdef DBusMessage *msg
225         cdef PendingCall pending_call
226
227         dbus_error_init(&error)
228
229         cpending_call = NULL
230         
231         msg = message._get_msg()
232
233         retval = dbus_connection_send_with_reply(self.conn,
234                                                  msg,
235                                                  &cpending_call,
236                                                  timeout_milliseconds)
237
238         if dbus_error_is_set(&error):
239             raise DBusException, error.message
240
241         if (cpending_call != NULL):
242             pending_call = PendingCall()
243             pending_call.__cinit__(cpending_call)
244         else:
245             pending_call = None
246
247         return (retval, pending_call)
248                                 
249     def send_with_reply_and_block(self, Message message,
250                                   timeout_milliseconds=0):
251         cdef DBusMessage * retval
252         cdef DBusError error
253         cdef DBusMessage *msg
254         cdef Message m
255
256         dbus_error_init(&error)
257
258         msg = message._get_msg()
259
260         retval = dbus_connection_send_with_reply_and_block(
261             self.conn,
262             msg,
263             timeout_milliseconds,
264             &error)
265
266         if dbus_error_is_set(&error):
267             raise DBusException, error.message
268
269         if retval == NULL:
270             raise AssertionError
271         
272         m = Message(_create=0)
273         m._set_msg(retval)
274         return m
275
276     def set_watch_functions(self, add_function, remove_function, data):
277         pass
278
279     def set_timeout_functions(self, add_function, remove_function, data):
280         pass
281
282     def set_wakeup_main_function(self, wakeup_main_function, data):
283         pass
284
285     # FIXME: set_dispatch_status_function, get_unix_user, set_unix_user_function
286
287     def add_filter(self, filter_function):
288         user_data = [ filter_function ]
289         global _user_data_references
290         _user_data_references.append(user_data)
291         
292         return dbus_connection_add_filter(self.conn,
293                                           cmessage_function_handler,
294                                           <void*>user_data,
295                                           NULL)
296
297
298     #FIXME: remove_filter
299     #       this is pretty tricky, we want to only remove the filter
300     #       if we truly have no more calls to our message_function_handler...ugh
301
302     def set_data(self, slot, data):
303         pass
304
305     def get_data(self, slot):
306         pass
307
308     def set_max_message_size(self, size):
309         dbus_connection_set_max_message_size(self.conn, size)
310
311     def get_max_message_size(self):
312         return dbus_connection_get_max_message_size(self.conn)
313
314     def set_max_received_size(self, size):
315         dbus_connection_set_max_received_size(self.conn, size)
316
317     def get_max_received_size(self):
318         return dbus_connection_get_max_received_size(self.conn)
319
320     def get_outgoing_size(self):
321         return dbus_connection_get_outgoing_size(self.conn)    
322
323     # preallocate_send, free_preallocated_send, send_preallocated
324
325     def register_object_path(self, path, unregister_cb, message_cb):
326         cdef DBusObjectPathVTable cvtable
327         
328         cvtable.unregister_function = cunregister_function_handler 
329         cvtable.message_function    = cmessage_function_handler
330
331         user_data = [message_cb, unregister_cb]
332         global _user_data_references
333         _user_data_references.append(user_data)
334         
335         return dbus_connection_register_object_path(self.conn, path, &cvtable,
336                                                     <void*>user_data) 
337
338     def register_fallback(self, path, unregister_cb, message_cb):
339         cdef DBusObjectPathVTable cvtable
340
341         cvtable.unregister_function = cunregister_function_handler 
342         cvtable.message_function    = cmessage_function_handler
343
344         user_data = [message_cb, unregister_cb]
345         global _user_data_references
346         _user_data_references.append(user_data)        
347         
348         return dbus_connection_register_fallback(self.conn, path, &cvtable,
349                                                  <void*>user_data) 
350
351     #FIXME: unregister_object_path , see problems with remove_filter
352
353     def list_registered (self, parent_path):
354         cdef char **cchild_entries
355         cdef dbus_bool_t retval
356         
357         retval = dbus_connection_list_registered(self.conn, parent_path, &cchild_entries)
358
359         if (not retval):
360             #FIXME: raise out of memory exception?
361             return None
362
363         i = 0
364         child_entries = []
365
366         while (cchild_entries[i] != NULL):
367             child_entries.append(cchild_entries[i])
368             i = i + 1
369
370         dbus_free_string_array(cchild_entries)
371
372         return child_entries
373
374     
375 cdef class PendingCall:
376     cdef DBusPendingCall *pending_call
377
378     def __init__(self, PendingCall _pending_call=None):
379         if (_pending_call != None):
380             self.__cinit__(_pending_call.pending_call)
381
382     cdef void __cinit__(self, DBusPendingCall *_pending_call):
383         self.pending_call = _pending_call
384         dbus_pending_call_ref(self.pending_call)
385
386     cdef DBusPendingCall *_get_pending_call(self):
387         return self.pending_call
388
389     def cancel(self):
390         dbus_pending_call_cancel(self.pending_call)
391
392     def get_completed(self):
393         return dbus_pending_call_get_completed(self.pending_call)
394
395     def get_reply(self):
396         cdef Message message
397         message = Message(_create=0)
398         message._set_msg(dbus_pending_call_get_reply(self.pending_call))
399         return message
400
401     def block(self):
402         dbus_pending_call_block(self.pending_call)
403
404 cdef class Watch:
405     cdef DBusWatch* watch
406
407     def __init__(self):
408         pass
409
410     cdef __cinit__(self, DBusWatch *cwatch):
411         self.watch = cwatch
412
413     def get_fd(self):
414         return dbus_watch_get_fd(self.watch)
415
416     # FIXME: not picked up correctly by extract.py
417     #def get_flags(self):
418     #    return dbus_watch_get_flags(self.watch)
419
420     def handle(self, flags):
421         return dbus_watch_handle(self.watch, flags)
422
423     def get_enabled(self):
424         return dbus_watch_get_enabled(self.watch)
425     
426 cdef class MessageIter:
427     cdef DBusMessageIter *iter
428     cdef DBusMessageIter real_iter
429
430     def __init__(self):
431         self.iter = &self.real_iter
432         
433     cdef __cinit__(self, DBusMessageIter *iter):
434         self.real_iter = iter[0]
435     
436     cdef DBusMessageIter *_get_iter(self):
437         return self.iter
438
439     def has_next(self):
440         return dbus_message_iter_has_next(self.iter)
441     
442     def next(self):
443         return dbus_message_iter_next(self.iter)
444
445     def get(self):
446         arg_type = self.get_arg_type()
447
448         if arg_type == TYPE_INVALID:
449             raise TypeError, 'Invalid arg type in MessageIter'
450         elif arg_type == TYPE_NIL:
451             retval = None
452         elif arg_type == TYPE_STRING:
453             retval = self.get_string()
454         elif arg_type == TYPE_INT32:
455             retval = self.get_int32()
456         elif arg_type == TYPE_UINT32:
457             retval = self.get_uint32()
458         elif arg_type == TYPE_INT64:
459             retval = self.get_int64()
460         elif arg_type == TYPE_UINT64:
461             retval = self.get_uint64()
462         elif arg_type == TYPE_DOUBLE:
463             retval = self.get_double()
464         elif arg_type == TYPE_BYTE:
465             retval = self.get_byte()
466         elif arg_type == TYPE_BOOLEAN:
467             retval = self.get_boolean()
468         elif arg_type == TYPE_ARRAY:
469             array_type = self.get_array_type()
470
471             if array_type == TYPE_STRING:
472                 retval = self.get_string_array()
473             elif array_type == TYPE_OBJECT_PATH:
474                 retval = self.get_object_path_array()
475             elif array_type == TYPE_BYTE:
476                 retval = self.get_byte_array()
477             elif array_type == TYPE_INT32:
478                 retval = self.get_int32_array()
479             elif array_type == TYPE_UINT32:
480                 retval = self.get_uint32_array()
481             elif array_type == TYPE_INT64:
482                 retval = self.get_int64_array()
483             elif array_type == TYPE_UINT64:
484                 retval = self.get_uint64_array()
485             elif array_type == TYPE_DOUBLE:
486                 retval = self.get_double_array()
487             else:
488                 raise TypeError, "Unknown array type %d in MessageIter" % (array_type)
489         elif arg_type == TYPE_DICT:
490             retval = self.get_dict()
491         elif arg_type == TYPE_OBJECT_PATH:
492             retval = self.get_object_path()
493         else:
494             raise TypeError, 'Unknown arg type %d in MessageIter' % (arg_type)
495
496         return retval
497
498     def get_dict(self):
499         cdef DBusMessageIter c_dict_iter
500         cdef MessageIter dict_iter
501         
502         dbus_message_iter_init_dict_iterator(self.iter, &c_dict_iter)
503
504         dict_iter = MessageIter()
505         dict_iter.__cinit__(&c_dict_iter)
506
507         dict = {}
508
509         end_of_dict = False
510
511         while True:
512             key = dict_iter.get_dict_key()
513             value = dict_iter.get()
514             dict[key] = value
515             if not dict_iter.has_next():
516                 break
517             dict_iter.next()
518
519         return dict
520
521     def get_arg_type(self):
522         return dbus_message_iter_get_arg_type(self.iter)
523
524     def get_array_type(self):
525         return dbus_message_iter_get_array_type(self.iter)
526
527     # FIXME: implement get_byte
528     #def get_byte(self):
529     #    return dbus_message_iter_get_byte(self.iter)
530
531     def get_boolean(self):
532         return dbus_message_iter_get_boolean(self.iter)
533     
534     def get_int32(self):
535         return dbus_message_iter_get_int32(self.iter)
536
537     def get_uint32(self):
538         return dbus_message_iter_get_uint32(self.iter)
539
540     def get_int64(self):
541         return dbus_message_iter_get_int64(self.iter)
542
543     def get_uint64(self):
544         return dbus_message_iter_get_uint64(self.iter)
545
546     def get_double(self):
547         return dbus_message_iter_get_double(self.iter)
548
549     def get_string(self):
550         return dbus_message_iter_get_string(self.iter)
551
552     def get_object_path(self):
553         object_path_string = dbus_message_iter_get_object_path(self.iter)
554         return ObjectPath(object_path_string)
555     
556     def get_dict_key(self):
557         return dbus_message_iter_get_dict_key(self.iter)
558
559     # FIXME: implement dbus_message_iter_init_array_iterator
560     
561     def get_byte_array(self):
562         cdef int len
563         cdef unsigned char *bytearray
564         cdef int i
565         dbus_message_iter_get_byte_array(self.iter, &bytearray, <int*>&len)
566         python_string = PyString_FromStringAndSize(<char *>bytearray, len)        
567         return python_string
568
569     # FIXME: implement dbus_message_iter_get_boolean_array
570
571     def get_int32_array(self):
572         cdef int len
573         cdef dbus_int32_t *retval
574         cdef int i
575         dbus_message_iter_get_int32_array(self.iter, &retval, <int*>&len)
576         python_list = []
577         for i from 0 <= i < len:
578             python_list.append(retval[i])
579         return python_list
580
581     def get_uint32_array(self):
582         cdef int len
583         cdef dbus_uint32_t *retval
584         cdef int i
585         dbus_message_iter_get_uint32_array(self.iter, &retval, <int*>&len)
586         python_list = []
587         for i from 0 <= i < len:
588             python_list.append(retval[i])
589         return python_list
590
591     def get_int64_array(self):
592         cdef int len
593         cdef dbus_int64_t *retval
594         cdef int i
595         dbus_message_iter_get_int64_array(self.iter, &retval, <int*>&len)
596         python_list = []
597         for i from 0 <= i < len:
598             python_list.append(retval[i])
599         return python_list
600
601     def get_uint64_array(self):
602         cdef int len
603         cdef dbus_uint64_t *retval
604         cdef int i
605         dbus_message_iter_get_uint64_array(self.iter, &retval, <int*>&len)
606         python_list = []
607         for i from 0 <= i < len:
608             python_list.append(retval[i])
609         return python_list
610
611     def get_double_array(self):
612         cdef int len
613         cdef double *retval
614         cdef int i
615         dbus_message_iter_get_double_array(self.iter, &retval, <int*>&len)
616         python_list = []
617         for i from 0 <= i < len:
618             python_list.append(retval[i])
619         return python_list
620
621
622     def get_string_array(self):
623         cdef int len
624         cdef char **retval
625         cdef int i
626         dbus_message_iter_get_string_array(self.iter, &retval, <int*>&len)
627         list = []
628         for i from 0 <= i < len:
629             list.append(retval[i])
630         return list
631
632     def get_object_path_array(self):
633         cdef int len
634         cdef char **retval
635         cdef int i
636         dbus_message_iter_get_object_path_array(self.iter, &retval, <int*>&len)
637         list = []
638         for i from 0 <= i < len:
639             list.append(ObjectPath(retval[i]))
640         return list    
641
642     # dbus_message_append_iter_init included in class Message
643
644     #FIXME: handle all the different types?
645     def append(self, value):
646         value_type = type(value)
647
648         if value_type == bool:
649             retval = self.append_boolean(value)
650         elif value_type == int:
651             retval = self.append_int32(value)
652         elif value_type == long:
653             retval = self.append_int64(value)
654         elif value_type == str:
655             retval = self.append_string(value)
656         elif value_type == float:
657             retval = self.append_double(value)
658         elif value_type == dict:
659             retval = self.append_dict(value)
660         elif value_type == list:
661             if len(value) == 0:
662                 # Empty lists are currently not supported, returning None instead
663                 retval = self.append(None)
664             else:
665                 list_type = type(value[0])
666                 if list_type == str:
667                     self.append_string_array(value)
668                 elif list_type == int:
669                     self.append_int32_array(value)
670                 elif list_type == long:
671                     self.append_int64_array(value)
672                 elif list_type == float:
673                     self.append_double_array(value)
674                 elif isinstance(value[0], ObjectPath):
675                     self.append_object_path_array(value)
676                 else:
677                     raise TypeError, "List of unknown type '%s'" % (list_type)
678         elif value_type == None.__class__:
679             retval = self.append_nil()
680         elif isinstance(value, ObjectPath):
681             retval = self.append_object_path(value)
682         elif isinstance(value, ByteArray):
683             retval = self.append_byte_array(value)
684         else:
685             raise TypeError, "Argument of unknown type '%s'" % (value_type)
686
687         return retval
688
689     def append_nil(self):
690         return dbus_message_iter_append_nil(self.iter)
691     
692     def append_boolean(self, value):
693         return dbus_message_iter_append_boolean(self.iter, value)
694
695     def append_byte(self, value):
696         if type(value) != str or len(value) != 1:
697             raise TypeError
698         return dbus_message_iter_append_byte(self.iter, ord(value))
699     
700     def append_int32(self, value):
701         return dbus_message_iter_append_int32(self.iter, value)
702
703     def append_uint32(self, value):
704         return dbus_message_iter_append_uint32(self.iter, value)
705
706     def append_int64(self, value):
707         return dbus_message_iter_append_int64(self.iter, value)
708
709     def append_uint64(self, value):
710         return dbus_message_iter_append_uint64(self.iter, value)
711
712     def append_double(self, value):
713         return dbus_message_iter_append_double(self.iter, value)
714
715     def append_string(self, value):
716         return dbus_message_iter_append_string(self.iter, value)    
717
718     def append_dict_key(self, value):
719         return dbus_message_iter_append_dict_key(self.iter, value)
720
721     def append_object_path(self, value):
722         return dbus_message_iter_append_object_path(self.iter, value)
723
724     # FIXME: append_array, append_boolean_array, append_uint32_array, 
725     # append_uint64_array
726
727     def append_dict(self, python_dict):
728         cdef DBusMessageIter c_dict_iter
729         cdef MessageIter dict_iter
730         
731         dbus_message_iter_append_dict(self.iter, &c_dict_iter)
732         
733         dict_iter = MessageIter()
734         dict_iter.__cinit__(&c_dict_iter)
735
736         for key, value in python_dict.iteritems():
737             if type(key) != str:
738                 raise TypeError, "DBus dict keys must be strings"
739             dict_iter.append_dict_key(key)
740             dict_iter.append(value)
741
742     def append_byte_array(self, python_list):
743         cdef unsigned char * value
744         cdef int length
745         cdef int i
746         length = len(python_list)
747         value = <unsigned char*>malloc(length * sizeof(unsigned char))
748         for i from 0 <= i < length:
749             item = python_list[i]
750             if type(item) != str or len(item) != 1:
751                 raise TypeError
752             value[i] = ord(item)
753         return dbus_message_iter_append_byte_array(self.iter, value, length)
754
755     def append_int32_array(self, python_list):
756         cdef dbus_int32_t *value
757         cdef int length
758         cdef int i
759         length = len(python_list)
760         value = <dbus_int32_t*>malloc(length * sizeof(dbus_int32_t))
761         for i from 0 <= i < length:
762             item = python_list[i]
763             if type(item) != int:
764                 raise TypeError
765             value[i] = item
766         return dbus_message_iter_append_int32_array(self.iter, value, length)
767
768     def append_int64_array(self, python_list):
769         cdef dbus_int64_t *value
770         cdef int length
771         cdef int i
772         length = len(python_list)
773         value = <dbus_int64_t*>malloc(length * sizeof(dbus_int64_t))
774         for i from 0 <= i < length:
775             item = python_list[i]
776             if type(item) != int:
777                 raise TypeError
778             value[i] = item
779         return dbus_message_iter_append_int64_array(self.iter, value, length)
780
781     def append_double_array(self, python_list):
782         cdef double *value
783         cdef int length
784         cdef int i
785         length = len(python_list)
786         value = <double*>malloc(length * sizeof(double))
787         for i from 0 <= i < length:
788             item = python_list[i]
789             if type(item) != float:
790                 raise TypeError
791             value[i] = item
792         return dbus_message_iter_append_double_array(self.iter, value, length)
793     
794     def append_object_path_array(self, list):
795         cdef char **value
796         cdef int length
797         cdef int i
798         length = len(list)
799         value = <char**>malloc(length * sizeof(char *))
800         for i from 0 <= i < length:
801             item = list[i]
802             if not isinstance(item, ObjectPath):
803                 raise TypeError
804             value[i] = item
805
806         return dbus_message_iter_append_object_path_array(self.iter, value, length)
807     
808     def append_string_array(self, python_list):
809         cdef char **value
810         cdef int length
811         cdef dbus_bool_t return_code
812         cdef int i
813         length = len(python_list)
814         value = <char**>malloc(length * sizeof(char *))
815         for i from 0 <= i < length:
816             item = python_list[i]
817             if type(item) != str:
818                 raise TypeError
819             value[i] = item
820         return dbus_message_iter_append_string_array(self.iter, value, length)
821
822 (MESSAGE_TYPE_INVALID, MESSAGE_TYPE_METHOD_CALL, MESSAGE_TYPE_METHOD_RETURN, MESSAGE_TYPE_ERROR, MESSAGE_TYPE_SIGNAL) = range(5)
823 (TYPE_INVALID, TYPE_NIL, TYPE_BYTE, TYPE_BOOLEAN, TYPE_INT32, TYPE_UINT32, TYPE_INT64, TYPE_UINT64, TYPE_DOUBLE, TYPE_STRING, TYPE_CUSTOM, TYPE_ARRAY, TYPE_DICT, TYPE_OBJECT_PATH) = (0, ord('v'), ord('y'), ord('b'), ord('i'), ord('u'), ord('x'), ord('t'), ord('d'), ord('s'), ord('c'), ord('a'), ord('m'), ord('o'))
824 (HANDLER_RESULT_HANDLED, HANDLER_RESULT_NOT_YET_HANDLED, HANDLER_RESULT_NEED_MEMORY) = range(3)
825     
826 cdef class Message:
827     cdef DBusMessage *msg
828
829     def __init__(self, message_type=MESSAGE_TYPE_INVALID,
830                  service=None, path=None, interface=None, method=None,
831                  Message method_call=None,
832                  name=None,
833                  Message reply_to=None, error_name=None, error_message=None,
834                  _create=1):
835         cdef char *cservice
836         cdef DBusMessage *cmsg
837
838         if (service == None):
839             cservice = NULL
840         else:
841             cservice = service
842             
843         if not _create:
844             return
845
846         if message_type == MESSAGE_TYPE_METHOD_CALL:
847             self.msg = dbus_message_new_method_call(cservice, path, interface, method)
848         elif message_type == MESSAGE_TYPE_METHOD_RETURN:
849             cmsg = method_call._get_msg()
850             self.msg = dbus_message_new_method_return(cmsg)
851         elif message_type == MESSAGE_TYPE_SIGNAL:
852             self.msg = dbus_message_new_signal(path, interface, name)
853         elif message_type == MESSAGE_TYPE_ERROR:
854             cmsg = reply_to._get_msg()
855             self.msg = dbus_message_new_error(cmsg, error_name, error_message)
856             
857     def type_to_name(self, type):
858         if type == MESSAGE_TYPE_SIGNAL:
859             return "signal"
860         elif type == MESSAGE_TYPE_METHOD_CALL:
861             return "method call"
862         elif type == MESSAGE_TYPE_METHOD_RETURN:
863             return "method return"
864         elif type == MESSAGE_TYPE_ERROR:
865             return "error"
866         else:
867             return "(unknown message type)"
868         
869     def __str__(self):
870         message_type = self.get_type()
871         sender = self.get_sender()
872
873         if sender == None:
874             sender = "(no sender)"
875
876         if (message_type == MESSAGE_TYPE_METHOD_CALL) or (message_type == MESSAGE_TYPE_SIGNAL):
877             retval = '%s interface=%s; member=%s; sender=%s' % (self.type_to_name(message_type),
878                                                                 self.get_interface(),
879                                                                 self.get_member(),
880                                                                 sender)
881         elif message_type == MESSAGE_TYPE_METHOD_RETURN:
882             retval = '%s sender=%s' % (self.type_to_name(message_type),
883                                         sender)
884         elif message_type == MESSAGE_TYPE_ERROR:
885             retval = '%s name=%s; sender=%s' % (self.type_to_name(message_type),
886                                                 self.get_error_name(),
887                                                 sender)
888         else:
889             retval = "Message of unknown type %d" % (message_type)
890
891
892         # FIXME: should really use self.convert_to_tuple() here
893         
894         iter = self.get_iter()
895         value_at_iter = True
896         
897         while (value_at_iter):
898             type = iter.get_arg_type()
899
900             if type == TYPE_INVALID:
901                 break
902             elif type == TYPE_NIL:
903                 arg = 'nil:None\n'
904             elif type == TYPE_STRING:
905                 str = iter.get_string()
906                 arg = 'string:%s\n' % (str)
907             elif type == TYPE_OBJECT_PATH:
908                 path = iter.get_object_path()
909                 arg = 'object_path:%s\n' % (path)
910             elif type == TYPE_INT32:
911                 num = iter.get_int32()
912                 arg = 'int32:%d\n' % (num)
913             elif type == TYPE_UINT32:
914                 num = iter.get_uint32()
915                 arg = 'uint32:%u\n' % (num)
916             elif type == TYPE_INT64:
917                 num = iter.get_int64()
918                 arg = 'int64:%d\n' % (num)
919             elif type == TYPE_UINT64:
920                 num = iter.get_uint64()
921                 arg = 'uint64:%u\n' % (num)
922             elif type == TYPE_DOUBLE:
923                 num = iter.get_double()
924                 arg = 'double:%f\n' % (num)
925             elif type == TYPE_BYTE:
926                 num = iter.get_byte()
927                 arg = 'byte:%d\n' % (num)
928             elif type == TYPE_BOOLEAN:
929                 bool = iter.get_boolean()
930                 if (bool):
931                     str = "true"
932                 else:
933                     str = "false"
934                 arg = 'boolean:%s\n' % (str)
935             else:
936                 arg = '(unknown arg type %d)\n' % type
937
938             retval = retval + arg
939             value_at_iter = iter.next()
940
941         return retval
942     
943     cdef _set_msg(self, DBusMessage *msg):
944         self.msg = msg
945
946     cdef DBusMessage *_get_msg(self):
947         return self.msg
948
949     def get_iter(self):
950         cdef DBusMessageIter iter
951         cdef MessageIter message_iter
952         cdef DBusMessage *msg
953
954         msg = self._get_msg()
955         dbus_message_iter_init(msg, &iter)
956
957         message_iter =  MessageIter()
958         message_iter.__cinit__(&iter)
959
960         return message_iter
961
962     def get_args_list(self):
963         retval = [ ]
964
965         iter = self.get_iter()
966         try:
967             retval.append(iter.get())
968         except TypeError, e:
969             return [ ]
970             
971         value_at_iter = iter.next()
972         while (value_at_iter):
973             retval.append(iter.get())
974             value_at_iter = iter.next()        
975
976         return retval
977             
978     # FIXME: implement dbus_message_copy?
979
980     def get_type(self):
981         return dbus_message_get_type(self.msg)
982
983     def set_path(self, object_path):
984         return dbus_message_set_path(self.msg, object_path)
985     
986     def get_path(self):
987         return dbus_message_get_path(self.msg)
988     
989     def set_interface(self, interface):
990         return dbus_message_set_interface(self.msg, interface)
991
992     def get_interface(self):
993         return dbus_message_get_interface(self.msg)    
994
995     def set_member(self, member):
996         return dbus_message_set_member(self.msg, member)
997
998     def get_member(self):
999         return dbus_message_get_member(self.msg)
1000
1001     def set_error_name(self, name):
1002         return dbus_message_set_error_name(self.msg, name)
1003
1004     def get_error_name(self):
1005         return dbus_message_get_error_name(self.msg)
1006
1007     def set_destination(self, destination):
1008         return dbus_message_set_destination(self.msg, destination)
1009
1010     def get_destination(self):
1011         return dbus_message_get_destination(self.msg)
1012
1013     def set_sender(self, sender):
1014         return dbus_message_set_sender(self.msg, sender)
1015     
1016     def get_sender(self):
1017         cdef char *sender
1018         sender = dbus_message_get_sender(self.msg)
1019         if (sender == NULL):
1020             return None
1021         else:
1022             return sender
1023
1024     def set_no_reply(self, no_reply):
1025         dbus_message_set_no_reply(self.msg, no_reply)
1026
1027     def get_no_reply(self):
1028         return dbus_message_get_no_reply(self.msg)
1029
1030     def is_method_call(self, interface, method):
1031         return dbus_message_is_method_call(self.msg, interface, method)
1032
1033     def is_signal(self, interface, signal_name):
1034         return dbus_message_is_signal(self.msg, interface, signal_name)
1035
1036     def is_error(self, error_name):
1037         return dbus_message_is_error(self.msg, error_name)
1038
1039     def has_destination(self, service):
1040         return dbus_message_has_destination(self.msg, service)
1041
1042     def has_sender(self, service):
1043         return dbus_message_has_sender(self.msg, service)
1044
1045     def get_serial(self):
1046         return dbus_message_get_serial(self.msg)
1047
1048     def set_reply_serial(self, reply_serial):
1049         return dbus_message_set_reply_serial(self.msg, reply_serial)
1050
1051     def get_reply_serial(self):
1052         return dbus_message_get_reply_serial(self.msg)    
1053
1054     #FIXME: dbus_message_get_path_decomposed
1055     
1056     # FIXME: all the different dbus_message_*args* methods
1057
1058 class Signal(Message):
1059     def __init__(self, spath, sinterface, sname):
1060         Message.__init__(self, MESSAGE_TYPE_SIGNAL, path=spath, interface=sinterface, name=sname)
1061
1062 class MethodCall(Message):
1063     def __init__(self, mpath, minterface, mmethod):
1064         Message.__init__(self, MESSAGE_TYPE_METHOD_CALL, path=mpath, interface=minterface, method=mmethod)
1065
1066 class MethodReturn(Message):
1067     def __init__(self, method_call):
1068         Message.__init__(self, MESSAGE_TYPE_METHOD_RETURN, method_call=method_call)
1069
1070 class Error(Message):
1071     def __init__(self, reply_to, error_name, error_message):
1072         Message.__init__(self, MESSAGE_TYPE_ERROR, reply_to=reply_to, error_name=error_name, error_message=error_message)
1073         
1074 cdef class Server:
1075     cdef DBusServer *server
1076     def __init__(self, address):
1077         cdef DBusError error
1078         dbus_error_init(&error)
1079         self.server = dbus_server_listen(address,
1080                                          &error)
1081         if dbus_error_is_set(&error):
1082             raise DBusException, error.message
1083
1084     def setup_with_g_main (self):
1085         dbus_server_setup_with_g_main(self.server, NULL)
1086
1087     def disconnect(self):
1088         dbus_server_disconnect(self.server)
1089
1090     def get_is_connected(self):
1091         return dbus_server_get_is_connected(self.server)
1092
1093 #    def set_new_connection_function(self, function, data):
1094 #        dbus_server_set_new_connection_function(self.conn, function,
1095 #                                                data, NULL)
1096         
1097 #    def set_watch_functions(self, add_function, remove_function, data):
1098 #        dbus_server_set_watch_functions(self.server,
1099 #                                        add_function, remove_function,
1100 #                                        data, NULL)
1101         
1102 #    def set_timeout_functions(self, add_function, remove_function, data):
1103 #        dbus_server_set_timeout_functions(self.server,
1104 #                                          add_function, remove_function,
1105 #                                          data, NULL)
1106         
1107 #    def handle_watch(self, watch, condition):
1108 #        dbus_server_handle_watch(self.conn, watch, condition)
1109
1110 BUS_SESSION = DBUS_BUS_SESSION
1111 BUS_SYSTEM = DBUS_BUS_SYSTEM
1112 BUS_ACTIVATION = DBUS_BUS_ACTIVATION
1113
1114 def bus_get (bus_type):
1115     cdef DBusError error
1116     cdef Connection conn
1117     dbus_error_init(&error)
1118     cdef DBusConnection *connection
1119
1120     connection = dbus_bus_get(bus_type,
1121                               &error)
1122
1123     if dbus_error_is_set(&error):
1124         raise DBusException, error.message
1125
1126     conn = Connection()
1127     conn.__cinit__(None, connection)
1128     return conn 
1129
1130 def bus_get_base_service(Connection connection):
1131     cdef DBusConnection *conn
1132     conn = connection._get_conn()
1133     return dbus_bus_get_base_service(conn)
1134
1135 def bus_register(Connection connection):
1136     cdef DBusError error
1137     dbus_error_init(&error)
1138     cdef dbus_bool_t retval
1139     cdef DBusConnection *conn
1140
1141     conn = connection._get_conn()
1142     retval = dbus_bus_register(conn,
1143                                &error)
1144     if dbus_error_is_set(&error):
1145         raise DBusException, error.message
1146
1147     return retval
1148
1149 SERVICE_FLAG_PROHIBIT_REPLACEMENT = 0x1
1150 SERVICE_FLAG_REPLACE_EXISTING     = 0x2
1151
1152 def bus_acquire_service(Connection connection, service_name, flags=0):
1153     cdef DBusError error
1154     dbus_error_init(&error)
1155     cdef int retval
1156     cdef DBusConnection *conn
1157
1158     conn = connection._get_conn()
1159     retval = dbus_bus_acquire_service(conn,
1160                                       service_name,
1161                                       flags,
1162                                       &error)
1163     if dbus_error_is_set(&error):
1164         raise DBusException, error.message
1165     return retval
1166     
1167 def bus_service_exists(Connection connection, service_name):
1168     cdef DBusError error
1169     dbus_error_init(&error)
1170     cdef dbus_bool_t retval
1171     cdef DBusConnection *conn
1172
1173     conn = connection._get_conn()
1174     retval = dbus_bus_service_exists(conn,
1175                                      service_name,
1176                                      &error)
1177     if dbus_error_is_set(&error):
1178         raise DBusException, error.message
1179     return retval
1180
1181 def bus_add_match(Connection connection, rule):
1182     cdef DBusError error
1183     cdef DBusConnection *conn
1184
1185     dbus_error_init(&error)
1186     
1187     conn = connection._get_conn()
1188     dbus_bus_add_match (conn, rule, &error)
1189     
1190     if dbus_error_is_set(&error):
1191         raise DBusException, error.message
1192
1193 def bus_remove_match(Connection connection, rule):
1194     cdef DBusError error
1195     cdef DBusConnection *conn
1196
1197     dbus_error_init(&error)
1198
1199     conn = connection._get_conn()
1200     dbus_bus_remove_match (conn, rule, &error)
1201     
1202     if dbus_error_is_set(&error):
1203         raise DBusException, error.message
1204
1205 def init_gthreads ():
1206         dbus_g_thread_init ()