2003-09-26 Seth Nickell <seth@gnome.org>
authorSeth Nickell <seth@gnome.org>
Fri, 26 Sep 2003 10:27:59 +0000 (10:27 +0000)
committerSeth Nickell <seth@gnome.org>
Fri, 26 Sep 2003 10:27:59 +0000 (10:27 +0000)
* python/dbus.py:
* python/examples/example-signals.py:

Start implementing some notions of signals. The API
is really terrible, but they sort of work (with the
exception of being able to filter by service, and to
transmit signals *as* a particular service). Need to
figure out how to make messages come from the service
we registered :-(

* python/dbus_bindings.pyx.in:

Removed duplicate message_handler callbacks.

ChangeLog
python/dbus.py
python/dbus_bindings.pyx.in
python/examples/example-signals.py [new file with mode: 0644]

index 91c7c19..4f68da0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2003-09-26  Seth Nickell  <seth@gnome.org>
+
+       * python/dbus.py:
+       * python/examples/example-signals.py:
+
+       Start implementing some notions of signals. The API
+       is really terrible, but they sort of work (with the
+       exception of being able to filter by service, and to
+       transmit signals *as* a particular service). Need to
+       figure out how to make messages come from the service
+       we registered :-(
+       
+       * python/dbus_bindings.pyx.in:
+
+       Removed duplicate message_handler callbacks.
+       
 2003-09-25  Havoc Pennington  <hp@redhat.com>
 
        * bus/session.conf.in: fix my mess
index d09b3fe..c7ab5dd 100644 (file)
@@ -56,6 +56,8 @@ class Bus:
     def __init__(self, bus_type=TYPE_SESSION, glib_mainloop=True):
         self._connection = dbus_bindings.bus_get(bus_type)
 
+        self._connection.add_filter(self._signal_func)
+        self._match_rule_to_receivers = { }
         if (glib_mainloop):
             self._connection.setup_with_g_main()
 
@@ -65,10 +67,46 @@ class Bus:
         """
         return RemoteService(self._connection, service_name)
 
+    def add_signal_receiver(self, receiver, interface=None, service=None, path=None):
+        match_rule = self._get_match_rule(interface, service, path)
+        
+        if (not self._match_rule_to_receivers.has_key(match_rule)):
+            self._match_rule_to_receivers[match_rule] = [ ]
+        self._match_rule_to_receivers[match_rule].append(receiver)
+        
+        dbus_bindings.bus_add_match(self._connection, match_rule)
+        
     def get_connection(self):
         """Get the dbus_bindings.Connection object associated with this Bus"""
         return self._connection
 
+    def _get_match_rule(self, interface, service, path):
+##        if (interface):
+##            match_rule = match_rule + ",interface='%s'" % (interface)
+##        if (service):
+##            match_rule = match_rule + ",service='%s'" % (service)
+##        if (path):
+##            match_rule = match_rule + ",path='%s'" % (path)
+        # FIXME: use the service here too!!!
+        return "type='signal',interface='%s',path='%s'" % (interface, path)
+    
+    def _signal_func(self, connection, message):
+        if (message.get_type() != dbus_bindings.MESSAGE_TYPE_SIGNAL):
+            return
+        
+        interface = message.get_interface()
+        service   = message.get_sender()
+        path      = message.get_path()
+        member    = message.get_member()
+
+        match_rule = self._get_match_rule(interface, service, path)
+
+        if (self._match_rule_to_receivers.has_key(match_rule)):
+            receivers = self._match_rule_to_receivers[match_rule]
+            args = [interface, member, service, path]
+            for receiver in receivers:
+                receiver(*args)
+        
 
 class RemoteObject:
     """A remote Object.
@@ -144,6 +182,10 @@ class Service:
         """Get the Bus this Service is on"""
         return self._bus
 
+    def get_service_name(self):
+        """Get the name of this service"""
+        return self._service_name
+
 class Object:
     """A base class for exporting your own Objects across the Bus.
 
@@ -161,6 +203,12 @@ class Object:
         
         self._connection.register_object_path(object_path, self._unregister_cb, self._message_cb)
 
+    def broadcast_signal(self, interface, signal_name):
+        message = dbus_bindings.Signal(self._object_path, interface, signal_name)
+        #FIXME: need to set_sender, but it always disconnects when we do this
+        #message.set_sender(self._service.get_service_name())
+        self._connection.send(message)
+
     def _unregister_cb(self, connection):
         print ("Unregister")
         
@@ -173,9 +221,10 @@ class Object:
             retval = target_method(*args)
         except Exception, e:
             if e.__module__ == '__main__':
-                error_name = e.__class__
+                # FIXME: is it right to use .__name__ here?
+                error_name = e.__class__.__name__
             else:
-                error_name = e.__module__ + '.' + str(e.__class__)
+                error_name = e.__module__ + '.' + str(e.__class__.__name__)
             error_contents = str(e)
             reply = dbus_bindings.Error(message, error_name, error_contents)
         else:
@@ -193,7 +242,7 @@ class Object:
                 print ('WARNING: registering DBus Object methods, already have a method named %s' % (method.__name__))
             method_dict[method.__name__] = method
         return method_dict
-        
+
 class RemoteService:
     """A remote service providing objects.
 
index 8feb867..4ae056c 100644 (file)
@@ -65,7 +65,7 @@ cdef void cunregister_function_handler (DBusConnection *connection,
                                         void *user_data):
     tup = <object>user_data
     assert (type(tup) == list)    
-    function = tup[0]
+    function = tup[1]
     args = [Connection(_conn=<object>connection)]
     function(*args)
 
@@ -74,7 +74,7 @@ cdef DBusHandlerResult cmessage_function_handler (DBusConnection *connection,
                                                   void *user_data):
     tup = <object>user_data
     assert (type(tup) == list)
-    function = tup[1]
+    function = tup[0]
     message = Message(_create=0)
     message._set_msg(<object>msg)
     args = [Connection(_conn=<object>connection),
@@ -84,20 +84,6 @@ cdef DBusHandlerResult cmessage_function_handler (DBusConnection *connection,
         retval = DBUS_HANDLER_RESULT_HANDLED
     return retval
 
-cdef DBusHandlerResult chandle_message_function_handler (DBusConnection *connection,
-                                                        DBusMessage *msg,
-                                                        void *user_data):
-    function = <object>user_data
-    assert (type(function) == function)
-    messagein = Message(_create=0)
-    messagein._set_msg(<object>msg)
-    args = [Connection(_conn=<object>connection),
-            messagein]
-    retval = function(*args)
-    if (retval == None):
-        retval = DBUS_HANDLER_RESULT_HANDLED
-    return retval    
-
 cdef class Connection:
     cdef DBusConnection *conn
     
@@ -258,10 +244,14 @@ cdef class Connection:
 
     # FIXME: set_dispatch_status_function, get_unix_user, set_unix_user_function
 
-    def add_filter(self, function):
+    def add_filter(self, filter_function):
+        user_data = [ filter_function ]
+        global _user_data_references
+        _user_data_references.append(user_data)
+        
         return dbus_connection_add_filter(self.conn,
-                                          chandle_message_function_handler,
-                                          <void*>function,
+                                          cmessage_function_handler,
+                                          <void*>user_data,
                                           NULL)
 
 
@@ -298,7 +288,7 @@ cdef class Connection:
         cvtable.unregister_function = cunregister_function_handler 
         cvtable.message_function    = cmessage_function_handler
 
-        user_data = [unregister_cb, message_cb]
+        user_data = [message_cb, unregister_cb]
         global _user_data_references
         _user_data_references.append(user_data)
         
@@ -314,7 +304,7 @@ cdef class Connection:
         cvtable.unregister_function = cunregister_function_handler 
         cvtable.message_function    = cmessage_function_handler
 
-        user_data = [unregister_cb, message_cb]
+        user_data = [message_cb, unregister_cb]
         global _user_data_references
         _user_data_references.append(user_data)        
         
@@ -906,4 +896,22 @@ def bus_service_exists(connection, service_name):
         raise DBusException, error.message
     return retval
 
+def bus_add_match(connection, rule):
+    cdef DBusError error
+    dbus_error_init(&error)
+    
+    conn = connection._get_conn()
+    dbus_bus_add_match (<DBusConnection*>conn, rule, &error)
+    
+    if dbus_error_is_set(&error):
+        raise DBusException, error.message
+
+def bus_remove_match(connection, rule):
+    cdef DBusError error
+    dbus_error_init(&error)
 
+    conn = connection._get_conn()
+    dbus_bus_remove_match (<DBusConnection*>conn, rule, &error)
+    
+    if dbus_error_is_set(&error):
+        raise DBusException, error.message
diff --git a/python/examples/example-signals.py b/python/examples/example-signals.py
new file mode 100644 (file)
index 0000000..8e31956
--- /dev/null
@@ -0,0 +1,27 @@
+import pygtk
+import gtk
+
+import dbus
+
+class SignalFrom(dbus.Object):
+    def __init__(self, service):
+        dbus.Object.__init__(self, "/", [], service)
+
+def signal_to(interface, signal_name, service, path):
+    print ("Received signal '%s.%s' from '%s%s'" % (interface, signal_name, service, path))
+
+bus = dbus.Bus()
+bus.add_signal_receiver(signal_to,
+                        "org.designfu.SignalInterface",
+                        "org.designfu.SignalService",
+                        "/")
+                                  
+
+service = dbus.Service("org.designfu.SignalService", bus)
+signal_from = SignalFrom(service)
+
+signal_from.broadcast_signal("org.designfu.SignalInterface", "HelloWorld")
+
+gtk.main()
+
+