summaryrefslogtreecommitdiff
path: root/python/dbus.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/dbus.py')
-rw-r--r--python/dbus.py196
1 files changed, 196 insertions, 0 deletions
diff --git a/python/dbus.py b/python/dbus.py
new file mode 100644
index 00000000..a7cca56a
--- /dev/null
+++ b/python/dbus.py
@@ -0,0 +1,196 @@
+
+"""Module for high-level communication over the FreeDesktop.org Bus (DBus)
+
+DBus allows you to share and access remote objects between processes
+running on the desktop, and also to access system services (such as
+the print spool).
+
+To use DBus, first get a Bus object, which provides a connection to one
+of a few standard dbus-daemon instances that might be running. From the
+Bus you can get a RemoteService. A service is provided by an application or
+process connected to the Bus, and represents a set of objects. Once you
+have a RemoteService you can get a RemoteObject that implements a specific interface
+(an interface is just a standard group of member functions). Then you can call
+those member functions directly.
+
+You can think of a complete method call as looking something like:
+
+Bus:SESSION -> Service:org.gnome.Evolution -> Object:/org/gnome/Evolution/Inbox -> Interface: org.gnome.Evolution.MailFolder -> Method: Forward('message1', 'seth@gnome.org')
+
+This communicates over the SESSION Bus to the org.gnome.Evolution process to call the
+Forward method of the /org/gnome/Evolution/Inbox object (which provides the
+org.gnome.Evolution.MailFolder interface) with two string arguments.
+
+For example, the dbus-daemon itself provides a service and some objects:
+
+# Get a connection to the desktop-wide SESSION bus
+bus = dbus.Bus(dbus.Bus.TYPE_SESSION)
+
+# Get the service provided by the dbus-daemon named org.freedesktop.DBus
+dbus_service = bus.get_service('org.freedesktop.DBus')
+
+# Get a reference to the desktop bus' standard object, denoted
+# by the path /org/freedesktop/DBus. The object /org/freedesktop/DBus
+# implements the 'org.freedesktop.DBus' interface
+dbus_object = dbus_service.get_object('/org/freedesktop/DBus',
+ 'org.freedesktop.DBus')
+
+# One of the member functions in the org.freedesktop.DBus interface
+# is ListServices(), which provides a list of all the other services
+# registered on this bus. Call it, and print the list.
+print(dbus_object.ListServices())
+"""
+
+import dbus_bindings
+
+class Bus:
+ """A connection to a DBus daemon.
+
+ One of three possible standard buses, the SESSION, SYSTEM,
+ or ACTIVATION bus
+ """
+ TYPE_SESSION = dbus_bindings.BUS_SESSION
+ TYPE_SYSTEM = dbus_bindings.BUS_SYSTEM
+ TYPE_ACTIVATION = dbus_bindings.BUS_ACTIVATION
+
+ def __init__(self, bus_type=TYPE_SESSION, glib_mainloop=True):
+ self._connection = dbus_bindings.bus_get(bus_type)
+
+ if (glib_mainloop):
+ self._connection.setup_with_g_main()
+
+ def get_service(self, service_name="org.freedesktop.Broadcast"):
+ """Get one of the RemoteServices connected to this Bus. service_name
+ is just a string of the form 'com.widgetcorp.MyService'
+ """
+ return RemoteService(self._connection, service_name)
+
+ def get_connection(self):
+ """Get the dbus_bindings.Connection object associated with this Bus"""
+ return self._connection
+
+
+class RemoteObject:
+ """A remote Object.
+
+ A RemoteObject is provided by a RemoteService on a particular Bus. RemoteObjects
+ have member functions, and can be called like normal Python objects.
+ """
+ def __init__(self, connection, service_name, object_path, interface):
+ self._connection = connection
+ self._service_name = service_name
+ self._object_path = object_path
+ self._interface = interface
+
+ def __getattr__(self, member):
+ if member == '__call__':
+ return object.__call__
+ else:
+ return RemoteMethod(self._connection, self._service_name,
+ self._object_path, self._interface, member)
+
+
+class RemoteMethod:
+ """A remote Method.
+
+ Typically a member of a RemoteObject. Calls to the
+ method produce messages that travel over the Bus and are routed
+ to a specific Service.
+ """
+ def __init__(self, connection, service_name, object_path, interface, method_name):
+ self._connection = connection
+ self._service_name = service_name
+ self._object_path = object_path
+ self._interface = interface
+ self._method_name = method_name
+
+ def __call__(self, *args):
+ print ("Going to call object(%s).interface(%s).method(%s)"
+ % (self._object_path, self._interface, self._method_name))
+
+ message = dbus_bindings.MethodCall(self._object_path, self._interface, self._method_name)
+ message.set_destination(self._service_name)
+
+ # Add the arguments to the function
+ iter = message.get_iter()
+ for arg in args:
+ print ("Adding arg %s" % (arg))
+ print ("Append success is %d" % (iter.append(arg)))
+ print ("Args now %s" % (message.get_args_list()))
+
+ reply_message = self._connection.send_with_reply_and_block(message, 5000)
+
+ args_tuple = reply_message.get_args_list()
+ if (len(args_tuple) == 0):
+ return
+ elif (len(args_tuple) == 1):
+ return args_tuple[0]
+ else:
+ return args_tuple
+
+class Service:
+ """A base class for exporting your own Services across the Bus
+
+ Just inherit from Service, providing the name of your service
+ (e.g. org.designfu.SampleService).
+ """
+ def __init__(self, service_name, bus=None):
+ self._service_name = service_name
+
+ if bus == None:
+ # Get the default bus
+ self._bus = Bus()
+ else:
+ self._bus = bus
+
+ dbus_bindings.bus_acquire_service(self._bus.get_connection(), service_name)
+
+ def get_bus(self):
+ """Get the Bus this Service is on"""
+ return self._bus
+
+class Object:
+ """A base class for exporting your own Objects across the Bus.
+
+ Just inherit from Object and provide a list of methods to share
+ across the Bus. These will appear as member functions of your
+ ServiceObject.
+ """
+ def __init__(self, object_path, methods_to_share, service):
+ self._object_path = object_path
+ self._service = service
+ self._object_methods = methods_to_share
+ self._bus = service.get_bus()
+ self._connection = self._bus.get_connection()
+
+ self._connection.register_object_path(object_path, self._unregister_cb, self._message_cb)
+
+ def _unregister_cb(self, connection):
+ print ("Unregister")
+
+ def message_cb(self, connection, message):
+ print ("Message %s received" % (message))
+ print ("MethodCall %s" % (message.get_member()))
+
+class RemoteService:
+ """A remote service providing objects.
+
+ A service is typically a process or application that provides
+ remote objects, but can also be the broadcast service that
+ receives signals from all applications on the Bus.
+ """
+
+ def __init__(self, connection, service_name):
+ self._connection = connection
+ self._service_name = service_name
+
+ def get_object(self, object_path, interface):
+ """Get an object provided by this Service that implements a
+ particular interface. object_path is a string of the form
+ '/com/widgetcorp/MyService/MyObject1'. interface looks a lot
+ like a service_name (they're often the same) and is of the form,
+ 'com.widgetcorp.MyInterface', and mostly just defines the
+ set of member functions that will be present in the object.
+ """
+ return RemoteObject(self._connection, self._service_name, object_path, interface)
+