From c5cf3857b114d0008a6d8191abf389064b5a66fc Mon Sep 17 00:00:00 2001 From: Seth Nickell Date: Fri, 26 Sep 2003 10:27:59 +0000 Subject: 2003-09-26 Seth Nickell * 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 | 16 +++++++++++ python/dbus.py | 55 +++++++++++++++++++++++++++++++++++--- python/dbus_bindings.pyx.in | 50 +++++++++++++++++++--------------- python/examples/example-signals.py | 27 +++++++++++++++++++ 4 files changed, 124 insertions(+), 24 deletions(-) create mode 100644 python/examples/example-signals.py diff --git a/ChangeLog b/ChangeLog index 91c7c195..4f68da09 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2003-09-26 Seth Nickell + + * 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 * bus/session.conf.in: fix my mess diff --git a/python/dbus.py b/python/dbus.py index d09b3fec..c7ab5dd3 100644 --- a/python/dbus.py +++ b/python/dbus.py @@ -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. diff --git a/python/dbus_bindings.pyx.in b/python/dbus_bindings.pyx.in index 8feb8678..4ae056c5 100644 --- a/python/dbus_bindings.pyx.in +++ b/python/dbus_bindings.pyx.in @@ -65,7 +65,7 @@ cdef void cunregister_function_handler (DBusConnection *connection, void *user_data): tup = user_data assert (type(tup) == list) - function = tup[0] + function = tup[1] args = [Connection(_conn=connection)] function(*args) @@ -74,7 +74,7 @@ cdef DBusHandlerResult cmessage_function_handler (DBusConnection *connection, void *user_data): tup = user_data assert (type(tup) == list) - function = tup[1] + function = tup[0] message = Message(_create=0) message._set_msg(msg) args = [Connection(_conn=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 = user_data - assert (type(function) == function) - messagein = Message(_create=0) - messagein._set_msg(msg) - args = [Connection(_conn=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, - function, + cmessage_function_handler, + 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 (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 (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 index 00000000..8e319569 --- /dev/null +++ b/python/examples/example-signals.py @@ -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() + + -- cgit v1.2.3