2003-09-21 Seth Nickell <seth@gnome.org>
[platform/upstream/dbus.git] / python / dbus.py
1
2 """Module for high-level communication over the FreeDesktop.org Bus (DBus)
3
4 DBus allows you to share and access remote objects between processes
5 running on the desktop, and also to access system services (such as
6 the print spool).
7
8 To use DBus, first get a Bus object, which provides a connection to one
9 of a few standard dbus-daemon instances that might be running. From the
10 Bus you can get a RemoteService. A service is provided by an application or
11 process connected to the Bus, and represents a set of objects. Once you
12 have a RemoteService you can get a RemoteObject that implements a specific interface
13 (an interface is just a standard group of member functions). Then you can call
14 those member functions directly.
15
16 You can think of a complete method call as looking something like:
17
18 Bus:SESSION -> Service:org.gnome.Evolution -> Object:/org/gnome/Evolution/Inbox -> Interface: org.gnome.Evolution.MailFolder -> Method: Forward('message1', 'seth@gnome.org')
19
20 This communicates over the SESSION Bus to the org.gnome.Evolution process to call the
21 Forward method of the /org/gnome/Evolution/Inbox object (which provides the
22 org.gnome.Evolution.MailFolder interface) with two string arguments.
23
24 For example, the dbus-daemon itself provides a service and some objects:
25
26 # Get a connection to the desktop-wide SESSION bus
27 bus = dbus.Bus(dbus.Bus.TYPE_SESSION)
28
29 # Get the service provided by the dbus-daemon named org.freedesktop.DBus
30 dbus_service = bus.get_service('org.freedesktop.DBus')
31
32 # Get a reference to the desktop bus' standard object, denoted
33 # by the path /org/freedesktop/DBus. The object /org/freedesktop/DBus
34 # implements the 'org.freedesktop.DBus' interface
35 dbus_object = dbus_service.get_object('/org/freedesktop/DBus',
36                                        'org.freedesktop.DBus')
37
38 # One of the member functions in the org.freedesktop.DBus interface
39 # is ListServices(), which provides a list of all the other services
40 # registered on this bus. Call it, and print the list.
41 print(dbus_object.ListServices())
42 """
43
44 import dbus_bindings
45
46 class Bus:
47     """A connection to a DBus daemon.
48
49     One of three possible standard buses, the SESSION, SYSTEM,
50     or ACTIVATION bus
51     """
52     TYPE_SESSION    = dbus_bindings.BUS_SESSION
53     TYPE_SYSTEM     = dbus_bindings.BUS_SYSTEM
54     TYPE_ACTIVATION = dbus_bindings.BUS_ACTIVATION
55
56     def __init__(self, bus_type=TYPE_SESSION, glib_mainloop=True):
57         self._connection = dbus_bindings.bus_get(bus_type)
58
59         if (glib_mainloop):
60             self._connection.setup_with_g_main()
61
62     def get_service(self, service_name="org.freedesktop.Broadcast"):
63         """Get one of the RemoteServices connected to this Bus. service_name
64         is just a string of the form 'com.widgetcorp.MyService'
65         """
66         return RemoteService(self._connection, service_name)
67
68     def get_connection(self):
69         """Get the dbus_bindings.Connection object associated with this Bus"""
70         return self._connection
71
72
73 class RemoteObject:
74     """A remote Object.
75
76     A RemoteObject is provided by a RemoteService on a particular Bus. RemoteObjects
77     have member functions, and can be called like normal Python objects.
78     """
79     def __init__(self, connection, service_name, object_path, interface):
80         self._connection   = connection
81         self._service_name = service_name
82         self._object_path  = object_path
83         self._interface    = interface
84
85     def __getattr__(self, member):
86         if member == '__call__':
87             return object.__call__
88         else:
89             return RemoteMethod(self._connection, self._service_name,
90                                 self._object_path, self._interface, member)
91
92
93 class RemoteMethod:
94     """A remote Method.
95
96     Typically a member of a RemoteObject. Calls to the
97     method produce messages that travel over the Bus and are routed
98     to a specific Service.
99     """
100     def __init__(self, connection, service_name, object_path, interface, method_name):
101         self._connection   = connection
102         self._service_name = service_name
103         self._object_path  = object_path
104         self._interface    = interface
105         self._method_name  = method_name
106
107     def __call__(self, *args):
108         print ("Going to call object(%s).interface(%s).method(%s)"
109                % (self._object_path, self._interface, self._method_name))
110
111         message = dbus_bindings.MethodCall(self._object_path, self._interface, self._method_name)
112         message.set_destination(self._service_name)
113         
114         # Add the arguments to the function
115         iter = message.get_iter()
116         for arg in args:
117             print ("Adding arg %s" % (arg))
118             print ("Append success is %d" % (iter.append(arg)))
119             print ("Args now %s" % (message.get_args_list()))            
120
121         reply_message = self._connection.send_with_reply_and_block(message, 5000)
122
123         args_tuple = reply_message.get_args_list()
124         if (len(args_tuple) == 0):
125             return
126         elif (len(args_tuple) == 1):
127             return args_tuple[0]
128         else:
129             return args_tuple
130
131 class Service:
132     """A base class for exporting your own Services across the Bus
133
134     Just inherit from Service, providing the name of your service
135     (e.g. org.designfu.SampleService).
136     """
137     def __init__(self, service_name, bus=None):
138         self._service_name = service_name
139                              
140         if bus == None:
141             # Get the default bus
142             self._bus = Bus()
143         else:
144             self._bus = bus
145
146         dbus_bindings.bus_acquire_service(self._bus.get_connection(), service_name)
147
148     def get_bus(self):
149         """Get the Bus this Service is on"""
150         return self._bus
151
152 class Object:
153     """A base class for exporting your own Objects across the Bus.
154
155     Just inherit from Object and provide a list of methods to share
156     across the Bus. These will appear as member functions of your
157     ServiceObject.
158     """
159     def __init__(self, object_path, methods_to_share, service):
160         self._object_path = object_path
161         self._service = service
162         self._object_methods = methods_to_share
163         self._bus = service.get_bus()
164         self._connection = self._bus.get_connection()
165         
166         self._connection.register_object_path(object_path, self._unregister_cb, self._message_cb)
167
168     def _unregister_cb(self, connection):
169         print ("Unregister")
170         
171     def message_cb(self, connection, message):
172         print ("Message %s received" % (message))
173         print ("MethodCall %s" % (message.get_member()))
174         
175 class RemoteService:
176     """A remote service providing objects.
177
178     A service is typically a process or application that provides
179     remote objects, but can also be the broadcast service that
180     receives signals from all applications on the Bus.
181     """
182     
183     def __init__(self, connection, service_name):
184         self._connection     = connection
185         self._service_name   = service_name
186
187     def get_object(self, object_path, interface):
188         """Get an object provided by this Service that implements a
189         particular interface. object_path is a string of the form
190         '/com/widgetcorp/MyService/MyObject1'. interface looks a lot
191         like a service_name (they're often the same) and is of the form,
192         'com.widgetcorp.MyInterface', and mostly just defines the
193         set of member functions that will be present in the object.
194         """
195         return RemoteObject(self._connection, self._service_name, object_path, interface)
196