[glibmm] DBusConnection: Add signal_subscribe() and add_filter().



commit 62dc94ca3c604a9e70e32498ccd392291a657960
Author: José Alburquerque <jaalburqu svn gnome org>
Date:   Sun Dec 5 20:46:06 2010 -0500

    	DBusConnection: Add signal_subscribe() and add_filter().
    
    	* gio/src/dbusconnection.{ccg,hg}: Add signal_subscribe(),
    	signal_unsubscribe(), add_filter() and remove_filter() methods.
    	Wrapped GDBusSignalFlags (reordered enums in alphabetical order).
    	([get|set]_exit_on_close):
    	(get_capabilities): Reordered declarations (by moving the _WRAP_METHOD
    	macros) according to where they are declared in the C API.

 ChangeLog                  |   11 ++++
 gio/src/dbusconnection.ccg |   85 +++++++++++++++++++++++++++++++++
 gio/src/dbusconnection.hg  |  113 ++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 204 insertions(+), 5 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 45ab535..0d5add9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2010-12-05  José Alburquerque  <jaalburqu svn gnome org>
+
+	DBusConnection: Add signal_subscribe() and add_filter().
+
+	* gio/src/dbusconnection.{ccg,hg}: Add signal_subscribe(),
+	signal_unsubscribe(), add_filter() and remove_filter() methods.
+	Wrapped GDBusSignalFlags (reordered enums in alphabetical order).
+	([get|set]_exit_on_close):
+	(get_capabilities): Reordered declarations (by moving the _WRAP_METHOD
+	macros) according to where they are declared in the C API.
+
 2.27.4:
 
 2010-11-30  José Alburquerque  <jaalburqu svn gnome org>
diff --git a/gio/src/dbusconnection.ccg b/gio/src/dbusconnection.ccg
index 28fb2a0..7687d41 100644
--- a/gio/src/dbusconnection.ccg
+++ b/gio/src/dbusconnection.ccg
@@ -21,6 +21,63 @@
 #include <giomm/dbusauthobserver.h>
 #include "slot_async.h"
 
+namespace
+{
+
+extern "C"
+{
+
+static void DBusConnection_Signal_giomm_callback(GDBusConnection* connection, const gchar* sender_name, const gchar* object_path, const gchar* interface_name, const gchar* signal_name, GVariant* parameters, gpointer user_data)
+{
+  Gio::DBusConnection::SlotSignal* the_slot =
+    static_cast<Gio::DBusConnection::SlotSignal*>(user_data);
+
+  try
+  {
+    (*the_slot)(Glib::wrap(connection, true), Glib::ustring(sender_name),
+      Glib::ustring(object_path), Glib::ustring(interface_name),
+      Glib::ustring(signal_name), Glib::VariantBase(parameters, true));
+  }
+  catch(...)
+  {
+    Glib::exception_handlers_invoke();
+  }
+}
+
+static void DBusConnection_Signal_giomm_callback_destroy(void* data)
+{
+  delete static_cast<Gio::DBusConnection::SlotSignal*>(data);
+}
+
+static GDBusMessage* DBusConnection_Message_Filter_giomm_callback(GDBusConnection* connection, GDBusMessage* message, gboolean incoming, gpointer user_data)
+{
+  Gio::DBusConnection::SlotMessageFilter* the_slot =
+    static_cast<Gio::DBusConnection::SlotMessageFilter*>(user_data);
+
+  try
+  {
+    Glib::RefPtr<Gio::DBusMessage> result = (*the_slot)(
+      Glib::wrap(connection, true), Glib::wrap(message, true),
+      static_cast<bool>(incoming));
+    return (result) ? result->gobj_copy() : 0;
+  }
+  catch(...)
+  {
+    Glib::exception_handlers_invoke();
+  }
+
+  return message;
+}
+
+static void DBusConnection_Message_Filter_giomm_callback_destroy(void* data)
+{
+  delete static_cast<Gio::DBusConnection::SlotMessageFilter*>(data);
+}
+
+} // extern "C"
+
+}
+
 namespace Gio
 {
 
@@ -479,4 +536,32 @@ void DBusConnection::emit_singal(
     ::Glib::Error::throw_exception(gerror);
 }
 
+guint DBusConnection::signal_subscribe(
+  const SlotSignal& slot,
+  const Glib::ustring& sender,
+  const Glib::ustring& interface_name,
+  const Glib::ustring& member,
+  const Glib::ustring& object_path,
+  const Glib::ustring& arg0,
+  DBusSignalFlags flags
+)
+{
+  SlotSignal* slot_copy = new SlotSignal(slot);
+
+  return g_dbus_connection_signal_subscribe(gobj(), sender.c_str(),
+    interface_name.c_str(), member.c_str(), object_path.c_str(), arg0.c_str(),
+    static_cast<GDBusSignalFlags>(flags), 
+    &DBusConnection_Signal_giomm_callback, slot_copy,
+    &DBusConnection_Signal_giomm_callback_destroy);
+}
+
+guint DBusConnection::add_filter(const SlotMessageFilter& slot)
+{
+  SlotMessageFilter* slot_copy = new SlotMessageFilter(slot);
+
+  return g_dbus_connection_add_filter(gobj(),
+    &DBusConnection_Message_Filter_giomm_callback, slot_copy,
+    DBusConnection_Message_Filter_giomm_callback_destroy);
+}
+
 } // namespace Gio
diff --git a/gio/src/dbusconnection.hg b/gio/src/dbusconnection.hg
index 321de49..22ba833 100644
--- a/gio/src/dbusconnection.hg
+++ b/gio/src/dbusconnection.hg
@@ -33,9 +33,10 @@ namespace Gio
 {
 
 _WRAP_ENUM(BusType, GBusType)
+_WRAP_ENUM(DBusCallFlags, GDBusCallFlags, NO_GTYPE)
 _WRAP_ENUM(DBusConnectionFlags, GDBusConnectionFlags, NO_GTYPE)
 _WRAP_ENUM(DBusSendMessageFlags, GDBusSendMessageFlags, NO_GTYPE)
-_WRAP_ENUM(DBusCallFlags, GDBusCallFlags, NO_GTYPE)
+_WRAP_ENUM(DBusSignalFlags, GDBusSignalFlags, NO_GTYPE)
 
 class DBusAuthObserver;
 
@@ -108,6 +109,37 @@ protected:
 
 public:
 
+  /** Signature for slot used in signal_subscribe().
+   *  For example,
+   * @code
+   * void on_signal(const Glib::RefPtr<DBusConnection>&, const
+   * Glib::ustring& sender_name, const Glib::ustring& object_path, const
+   * Glib::ustring& object_path, const Glib::ustring& interface_name, const
+   * Glib::ustring& signal_name, const Glib::VariantBase& parameters);.
+   * @endcode
+   */
+  typedef sigc::slot<void, const Glib::RefPtr<DBusConnection>&,
+    const Glib::ustring&, const Glib::ustring&, const Glib::ustring&,
+    const Glib::ustring&, const Glib::VariantBase&>  SlotSignal;
+
+  /** Signature for slot used in add_filter().
+   *  For example,
+   * @code
+   * Glib::RefPtr<DBusMessage> on_message_filter(const
+   * Glib::RefPtr<DBusConnection>, const Glib::RefPtr<DBusMessage>& bool
+   * incoming);.
+   * @endcode
+   *
+   * A filter function is passed a DBusMessage and expected to return a
+   * DBusMessage too. Passive filter functions that don't modify the message
+   * can simply return the message object.  Filter functions that wants to
+   * drop a message can simply return <tt>0</tt>.  And filter function may
+   * modify a message by copying it and return the copy.
+   */
+  typedef sigc::slot<Glib::RefPtr<DBusMessage>,
+    const Glib::RefPtr<DBusConnection>&,
+    const Glib::RefPtr<DBusMessage>&, bool> SlotMessageFilter;
+
   /** Asynchronously connects to the message bus specified by @a bus_type.
    *
    * When the operation is finished, @a slot will be invoked. You can then
@@ -363,6 +395,9 @@ public:
 
   _WRAP_METHOD(void flush_sync(const Glib::RefPtr<Cancellable>& cancellable), g_dbus_connection_flush_sync, errthrow)
 
+  _WRAP_METHOD(bool get_exit_on_close() const, g_dbus_connection_get_exit_on_close)
+  _WRAP_METHOD(void set_exit_on_close(bool exit_on_close = true), g_dbus_connection_set_exit_on_close)
+
   //TODO: In the C API, out_serial is volatile, but gmmproc can't parse that.
   #m4 _CONVERSION(`guint32*',`volatile guint32*',`($3)')
   _WRAP_METHOD(bool send_message(const Glib::RefPtr<DBusMessage>& message, DBusSendMessageFlags flags, guint32* out_serial), g_dbus_connection_send_message, errthrow)
@@ -421,6 +456,8 @@ public:
   _WRAP_METHOD(Glib::ustring get_guid() const, g_dbus_connection_get_guid)
   _WRAP_METHOD(Glib::ustring get_unique_name() const, g_dbus_connection_get_unique_name)
 
+  _WRAP_METHOD(DBusCapabilityFlags get_capabilities() const, g_dbus_connection_get_capabilities)
+
   _WRAP_METHOD(Glib::RefPtr<Credentials> get_peer_credentials(), g_dbus_connection_get_peer_credentials, refreturn)
   _WRAP_METHOD(Glib::RefPtr<const Credentials> get_peer_credentials() const, g_dbus_connection_get_peer_credentials, refreturn, constversion)
 
@@ -584,10 +621,76 @@ public:
     const Glib::VariantBase&            parameters = Glib::VariantBase()
   );
 
-  _WRAP_METHOD(bool get_exit_on_close() const, g_dbus_connection_get_exit_on_close)
-  _WRAP_METHOD(void set_exit_on_close(bool exit_on_close = true), g_dbus_connection_set_exit_on_close)
-  _WRAP_METHOD(DBusCapabilityFlags get_capabilities() const, g_dbus_connection_get_capabilities)
-};
+  /** Subscribes to signals on the connection and invokes @a slot with a
+   * whenever the signal is received. Note that @a slot will be invoked in the
+   * thread-default main loop of the thread you are calling this method from.
+   *
+   * If the connection is not a message bus connection, @a sender must be
+   * <tt>0</tt>.
+   *
+   * If @a sender is a well-known name note that @a slot is invoked with the
+   * unique name for the owner of @a sender, not the well-known name as one
+   * would expect. This is because the message bus rewrites the name. As such,
+   * to avoid certain race conditions, users should be tracking the name owner
+   * of the well-known name and use that when processing the received signal.
+   *
+   * @param slot Slot to invoke when there is a signal matching the requested
+   * data.
+   * @param sender Sender name to match on (unique or well-known name) or
+   * <tt>0</tt> to listen from all senders.
+   * @param interface_name D-Bus interface name to match on or <tt>0</tt> to
+   * match on all interfaces.
+   * @param member D-Bus signal name to match on or <tt>0</tt> to match on all
+   * signals.  
+   * @param object_path Object path to match on or <tt>0</tt> to match on all
+   * object paths.  
+   * @param arg0 Contents of first string argument to match on or <tt>0</tt>
+   * to match on all kinds of arguments.  
+   * @param flags Flags describing how to subscribe to the signal (currently
+   * unused).  
+   * @return A subscription identifier that can be used with
+   * signal_unsubscribe().
+   * @newin{2,28}
+   */
+  guint signal_subscribe(
+    const SlotSignal& slot,
+    const Glib::ustring& sender = Glib::ustring(),
+    const Glib::ustring& interface_name = Glib::ustring(),
+    const Glib::ustring& member = Glib::ustring(),
+    const Glib::ustring& object_path = Glib::ustring(),
+    const Glib::ustring& arg0 = Glib::ustring(),
+    DBusSignalFlags flags = Gio::DBUS_SIGNAL_FLAGS_NONE
+  );
+  _IGNORE(g_dbus_connection_signal_subscribe)
+
+  _WRAP_METHOD(void signal_unsubscribe(guint subscription_id), g_dbus_connection_signal_unsubscribe)
+
+  /** Adds a message filter. Filters are handlers that are run on all incoming
+   * and outgoing messages, prior to standard dispatch. Filters are run in the
+   * order that they were added. The same handler can be added as a filter
+   * more than once, in which case it will be run more than once. Filters
+   * added during a filter slot won't be run on the message being processed.
+   * Filter slots are allowed to modify and even drop messages.
+   *
+   * Note that filters are run in a dedicated message handling thread so they
+   * can't block and, generally, can't do anything but signal a worker thread.
+   * Also note that filters are rarely needed - use API such as
+   * send_message_with_reply(), signal_subscribe() or call() instead.
+   *
+   * If a filter consumes an incoming message the message is not dispatched
+   * anywhere else - not even the standard dispatch machinery (that API such
+   * as signal_subscribe() and send_message_with_reply() relies on) will see
+   * the message. Similary, if a filter consumes an outgoing message, the
+   * message will not be sent to the other peer.
+   *
+   * @param slot A filter slot.  
+   * @return A filter identifier that can be used with remove_filter().
+   * @newin{2,28}
+   */
+  guint add_filter(const SlotMessageFilter& slot);
+  _IGNORE(g_dbus_connection_add_filter)
 
+  _WRAP_METHOD(void remove_filter(guint filter_id), g_dbus_connection_remove_filter)
+};
 
 } // namespace Gio



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]