From ed0e0cf4f678d9e3b13570d217d7960b5ffebdac Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 11 Apr 2008 13:11:38 +0000 Subject: [PATCH] We can't use *_run_* API from dbus signal cb or method implementation. To avoid problems move the code to a g_idle cb. svn path=/trunk/; revision=922 --- libempathy-gtk/empathy-account-chooser.c | 6 +- libempathy-gtk/empathy-accounts-dialog.c | 6 +- libempathy-gtk/empathy-chat.c | 6 +- libempathy/empathy-chandler.c | 66 ++++++++++++---- libempathy/empathy-contact-manager.c | 7 +- libempathy/empathy-filter.c | 77 ++++++++++++++----- libempathy/empathy-tp-contact-factory.c | 7 +- libempathy/empathy-utils.c | 96 ++++++++++++++++++++++++ libempathy/empathy-utils.h | 4 + src/empathy-main-window.c | 6 +- 10 files changed, 230 insertions(+), 51 deletions(-) diff --git a/libempathy-gtk/empathy-account-chooser.c b/libempathy-gtk/empathy-account-chooser.c index 5b1867e6..6b731ff7 100644 --- a/libempathy-gtk/empathy-account-chooser.c +++ b/libempathy-gtk/empathy-account-chooser.c @@ -223,9 +223,9 @@ empathy_account_chooser_new (void) g_signal_connect (priv->monitor, "account-deleted", G_CALLBACK (account_chooser_account_deleted_cb), chooser); - dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc), "AccountStatusChanged", - G_CALLBACK (account_chooser_status_changed_cb), - chooser, NULL); + empathy_connect_to_account_status_changed (priv->mc, + G_CALLBACK (account_chooser_status_changed_cb), + chooser, NULL); account_chooser_setup (EMPATHY_ACCOUNT_CHOOSER (chooser)); diff --git a/libempathy-gtk/empathy-accounts-dialog.c b/libempathy-gtk/empathy-accounts-dialog.c index 958d709a..6f4421b8 100644 --- a/libempathy-gtk/empathy-accounts-dialog.c +++ b/libempathy-gtk/empathy-accounts-dialog.c @@ -1074,9 +1074,9 @@ empathy_accounts_dialog_show (GtkWindow *parent) g_signal_connect (dialog->monitor, "account-disabled", G_CALLBACK (accounts_dialog_account_enabled_cb), dialog); - dbus_g_proxy_connect_signal (DBUS_G_PROXY (dialog->mc), "AccountStatusChanged", - G_CALLBACK (accounts_dialog_status_changed_cb), - dialog, NULL); + empathy_connect_to_account_status_changed (dialog->mc, + G_CALLBACK (accounts_dialog_status_changed_cb), + dialog, NULL); accounts_dialog_model_setup (dialog); accounts_dialog_setup (dialog); diff --git a/libempathy-gtk/empathy-chat.c b/libempathy-gtk/empathy-chat.c index 3be3302f..0328c4ee 100644 --- a/libempathy-gtk/empathy-chat.c +++ b/libempathy-gtk/empathy-chat.c @@ -1537,9 +1537,9 @@ empathy_chat_init (EmpathyChat *chat) priv->sent_messages_index = -1; priv->mc = empathy_mission_control_new (); - dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc), "AccountStatusChanged", - G_CALLBACK (chat_status_changed_cb), - chat, NULL); + empathy_connect_to_account_status_changed (priv->mc, + G_CALLBACK (chat_status_changed_cb), + chat, NULL); /* Block events for some time to avoid having "has come online" or * "joined" messages. */ diff --git a/libempathy/empathy-chandler.c b/libempathy/empathy-chandler.c index a294febf..2fdb3729 100644 --- a/libempathy/empathy-chandler.c +++ b/libempathy/empathy-chandler.c @@ -44,17 +44,20 @@ G_DEFINE_TYPE_WITH_CODE (EmpathyChandler, empathy_chandler, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (EMP_TYPE_SVC_CHANDLER, chandler_iface_init)); -static void -my_handle_channel (EmpSvcChandler *self, - const gchar *bus_name, - const gchar *connection, - const gchar *channel_type, - const gchar *channel, - guint handle_type, - guint handle, - DBusGMethodInvocation *context) +typedef struct { + EmpathyChandler *chandler; + gchar *bus_name; + gchar *connection; + gchar *channel_type; + gchar *channel; + guint handle_type; + guint handle; +} IdleData; + +static gboolean +handle_channel_idle_cb (gpointer data) { - EmpathyChandler *chandler = EMPATHY_CHANDLER (self); + IdleData *idle_data = data; TpChannel *chan; TpConnection *conn; static TpDBusDaemon *daemon = NULL; @@ -63,17 +66,52 @@ my_handle_channel (EmpSvcChandler *self, daemon = tp_dbus_daemon_new (tp_get_bus ()); } - conn = tp_connection_new (daemon, bus_name, connection, NULL); - chan = tp_channel_new (conn, channel, channel_type, handle_type, handle, NULL); + conn = tp_connection_new (daemon, idle_data->bus_name, + idle_data->connection, NULL); + chan = tp_channel_new (conn, idle_data->channel, idle_data->channel_type, + idle_data->handle_type, idle_data->handle, NULL); tp_channel_run_until_ready (chan, NULL, NULL); empathy_debug (DEBUG_DOMAIN, "New channel to be handled: " "type=%s handle=%d", - channel_type, handle); - g_signal_emit (chandler, signals[NEW_CHANNEL], 0, chan); + idle_data->channel_type, idle_data->handle); + g_signal_emit (idle_data->chandler, signals[NEW_CHANNEL], 0, chan); g_object_unref (chan); g_object_unref (conn); + g_free (idle_data->bus_name); + g_free (idle_data->connection); + g_free (idle_data->channel_type); + g_free (idle_data->channel); + g_slice_free (IdleData, idle_data); + + return FALSE; +} + +static void +my_handle_channel (EmpSvcChandler *self, + const gchar *bus_name, + const gchar *connection, + const gchar *channel_type, + const gchar *channel, + guint handle_type, + guint handle, + DBusGMethodInvocation *context) +{ + EmpathyChandler *chandler = EMPATHY_CHANDLER (self); + IdleData *data; + + data = g_slice_new (IdleData); + data->chandler = chandler; + data->bus_name = g_strdup (bus_name); + data->connection = g_strdup (connection); + data->channel_type = g_strdup (channel_type); + data->channel = g_strdup (channel); + data->handle_type = handle_type; + data->handle = handle; + g_idle_add_full (G_PRIORITY_HIGH, + handle_channel_idle_cb, + data, NULL); emp_svc_chandler_return_from_handle_channel (context); } diff --git a/libempathy/empathy-contact-manager.c b/libempathy/empathy-contact-manager.c index 1ef3b683..a151dbd2 100644 --- a/libempathy/empathy-contact-manager.c +++ b/libempathy/empathy-contact-manager.c @@ -225,10 +225,9 @@ empathy_contact_manager_init (EmpathyContactManager *manager) priv->mc = empathy_mission_control_new (); - dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc), - "AccountStatusChanged", - G_CALLBACK (contact_manager_status_changed_cb), - manager, NULL); + empathy_connect_to_account_status_changed (priv->mc, + G_CALLBACK (contact_manager_status_changed_cb), + manager, NULL); /* Get ContactList for existing connections */ accounts = mission_control_get_online_connections (priv->mc, NULL); diff --git a/libempathy/empathy-filter.c b/libempathy/empathy-filter.c index a5d0757d..08f9ee6c 100644 --- a/libempathy/empathy-filter.c +++ b/libempathy/empathy-filter.c @@ -53,19 +53,22 @@ G_DEFINE_TYPE_WITH_CODE (EmpathyFilter, empathy_filter, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (EMP_TYPE_SVC_FILTER, filter_iface_init)); -static void -my_filter_channel (EmpSvcFilter *self, - const gchar *bus_name, - const gchar *connection, - const gchar *channel_type, - const gchar *channel, - guint handle_type, - guint handle, - guint id, - DBusGMethodInvocation *context) +typedef struct { + EmpathyFilter *filter; + gchar *bus_name; + gchar *connection; + gchar *channel_type; + gchar *channel; + guint handle_type; + guint handle; + guint id; +} IdleData; + +static gboolean +filter_channel_idle_cb (gpointer data) { - EmpathyFilter *filter = EMPATHY_FILTER (self); - EmpathyFilterPriv *priv = GET_PRIV (filter); + IdleData *idle_data = data; + EmpathyFilterPriv *priv = GET_PRIV (idle_data->filter); TpChannel *chan; TpConnection *conn; static TpDBusDaemon *daemon = NULL; @@ -74,19 +77,58 @@ my_filter_channel (EmpSvcFilter *self, daemon = tp_dbus_daemon_new (tp_get_bus ()); } - conn = tp_connection_new (daemon, bus_name, connection, NULL); - chan = tp_channel_new (conn, channel, channel_type, handle_type, handle, NULL); + conn = tp_connection_new (daemon, idle_data->bus_name, + idle_data->connection, NULL); + tp_connection_run_until_ready (conn, FALSE, NULL, NULL); + chan = tp_channel_new (conn, idle_data->channel, idle_data->channel_type, + idle_data->handle_type, idle_data->handle, NULL); tp_channel_run_until_ready (chan, NULL, NULL); - g_hash_table_insert (priv->table, chan, GUINT_TO_POINTER (id)); + g_hash_table_insert (priv->table, chan, GUINT_TO_POINTER (idle_data->id)); empathy_debug (DEBUG_DOMAIN, "New channel to be filtred: " "type=%s handle=%d id=%d", - channel_type, handle, id); + idle_data->channel_type, idle_data->handle, + idle_data->id); - g_signal_emit (filter, signals[NEW_CHANNEL], 0, chan); + g_signal_emit (idle_data->filter, signals[NEW_CHANNEL], 0, chan); g_object_unref (conn); + g_free (idle_data->bus_name); + g_free (idle_data->connection); + g_free (idle_data->channel_type); + g_free (idle_data->channel); + g_slice_free (IdleData, idle_data); + + return FALSE; +} + +static void +my_filter_channel (EmpSvcFilter *self, + const gchar *bus_name, + const gchar *connection, + const gchar *channel_type, + const gchar *channel, + guint handle_type, + guint handle, + guint id, + DBusGMethodInvocation *context) +{ + EmpathyFilter *filter = EMPATHY_FILTER (self); + IdleData *data; + + data = g_slice_new (IdleData); + data->filter = filter; + data->bus_name = g_strdup (bus_name); + data->connection = g_strdup (connection); + data->channel_type = g_strdup (channel_type); + data->channel = g_strdup (channel); + data->handle_type = handle_type; + data->handle = handle; + data->id = id; + g_idle_add_full (G_PRIORITY_HIGH, + filter_channel_idle_cb, + data, NULL); emp_svc_filter_return_from_filter_channel (context); } @@ -181,6 +223,7 @@ empathy_filter_new (const gchar *bus_name, G_OBJECT (filter)); mc = empathy_mission_control_new (); + mission_control_register_filter (mc, bus_name, object_path, diff --git a/libempathy/empathy-tp-contact-factory.c b/libempathy/empathy-tp-contact-factory.c index 91a4a83a..678e53b3 100644 --- a/libempathy/empathy-tp-contact-factory.c +++ b/libempathy/empathy-tp-contact-factory.c @@ -1277,10 +1277,9 @@ empathy_tp_contact_factory_init (EmpathyTpContactFactory *tp_factory) EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory); priv->mc = empathy_mission_control_new (); - dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc), - "AccountStatusChanged", - G_CALLBACK (tp_contact_factory_status_changed_cb), - tp_factory, NULL); + empathy_connect_to_account_status_changed (priv->mc, + G_CALLBACK (tp_contact_factory_status_changed_cb), + tp_factory, NULL); } EmpathyTpContactFactory * diff --git a/libempathy/empathy-utils.c b/libempathy/empathy-utils.c index b4058cd3..46fb9702 100644 --- a/libempathy/empathy-utils.c +++ b/libempathy/empathy-utils.c @@ -633,3 +633,99 @@ empathy_channel_get_account (TpChannel *channel) return account; } + +typedef void (*AccountStatusChangedFunc) (MissionControl *mc, + TpConnectionStatus status, + McPresence presence, + TpConnectionStatusReason reason, + const gchar *unique_name, + gpointer *user_data); + +typedef struct { + AccountStatusChangedFunc handler; + gpointer user_data; + GClosureNotify free_func; +} AccountStatusChangedData; + +typedef struct { + MissionControl *mc; + TpConnectionStatus status; + McPresence presence; + TpConnectionStatusReason reason; + gchar *unique_name; + AccountStatusChangedData *data; +} InvocationData; + +static void +account_status_changed_data_free (gpointer ptr, + GClosure *closure) +{ + AccountStatusChangedData *data = ptr; + + if (data->free_func) { + data->free_func (data->user_data, closure); + } + g_slice_free (AccountStatusChangedData, data); +} + +static gboolean +account_status_changed_invoke_callback (gpointer data) +{ + InvocationData *invocation_data = data; + + invocation_data->data->handler (invocation_data->mc, + invocation_data->status, + invocation_data->presence, + invocation_data->reason, + invocation_data->unique_name, + invocation_data->data->user_data); + + g_free (invocation_data->unique_name); + g_slice_free (InvocationData, invocation_data); + + return FALSE; +} + +static void +account_status_changed_cb (MissionControl *mc, + TpConnectionStatus status, + McPresence presence, + TpConnectionStatusReason reason, + const gchar *unique_name, + AccountStatusChangedData *data) +{ + InvocationData *invocation_data; + + invocation_data = g_slice_new (InvocationData); + invocation_data->mc = mc; + invocation_data->status = status; + invocation_data->presence = presence; + invocation_data->reason = reason; + invocation_data->unique_name = g_strdup (unique_name); + invocation_data->data = data; + g_idle_add_full (G_PRIORITY_HIGH, + account_status_changed_invoke_callback, + invocation_data, NULL); +} + +void +empathy_connect_to_account_status_changed (MissionControl *mc, + GCallback handler, + gpointer user_data, + GClosureNotify free_func) +{ + AccountStatusChangedData *data; + + g_return_if_fail (IS_MISSIONCONTROL (mc)); + g_return_if_fail (handler != NULL); + + data = g_slice_new (AccountStatusChangedData); + + data->handler = (AccountStatusChangedFunc) handler; + data->user_data = user_data; + data->free_func = free_func; + dbus_g_proxy_connect_signal (DBUS_G_PROXY (mc), "AccountStatusChanged", + G_CALLBACK (account_status_changed_cb), + data, account_status_changed_data_free); +} + diff --git a/libempathy/empathy-utils.h b/libempathy/empathy-utils.h index f717b845..2b14374f 100644 --- a/libempathy/empathy-utils.h +++ b/libempathy/empathy-utils.h @@ -102,6 +102,10 @@ void empathy_run_until_ready_full (gpointer object, gpointer user_data, GMainLoop **loop); McAccount * empathy_channel_get_account (TpChannel *channel); +void empathy_connect_to_account_status_changed (MissionControl *mc, + GCallback handler, + gpointer user_data, + GClosureNotify free_func); G_END_DECLS diff --git a/src/empathy-main-window.c b/src/empathy-main-window.c index 79fb1d39..5c46d7f7 100644 --- a/src/empathy-main-window.c +++ b/src/empathy-main-window.c @@ -239,9 +239,9 @@ empathy_main_window_show (void) g_object_unref (glade); window->mc = empathy_mission_control_new (); - dbus_g_proxy_connect_signal (DBUS_G_PROXY (window->mc), "AccountStatusChanged", - G_CALLBACK (main_window_status_changed_cb), - window, NULL); + empathy_connect_to_account_status_changed (window->mc, + G_CALLBACK (main_window_status_changed_cb), + window, NULL); window->errors = g_hash_table_new_full (empathy_account_hash, empathy_account_equal, -- 2.39.2