aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk>2011-04-29 23:25:35 +0800
committerEmilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk>2011-04-29 23:25:35 +0800
commitb028f1e3930ab201994eccd4ff7d1bc18c50e6f3 (patch)
tree4b83e90fe17af81dd8edffaf8084688a9d022bc7
parentcf401b3897d7d4eba4e8dbe5fec9e85079e17446 (diff)
parent1c68eae8b655e8904bbb0a90001f01eb6d3b342a (diff)
downloadgsoc2013-empathy-b028f1e3930ab201994eccd4ff7d1bc18c50e6f3.tar
gsoc2013-empathy-b028f1e3930ab201994eccd4ff7d1bc18c50e6f3.tar.gz
gsoc2013-empathy-b028f1e3930ab201994eccd4ff7d1bc18c50e6f3.tar.bz2
gsoc2013-empathy-b028f1e3930ab201994eccd4ff7d1bc18c50e6f3.tar.lz
gsoc2013-empathy-b028f1e3930ab201994eccd4ff7d1bc18c50e6f3.tar.xz
gsoc2013-empathy-b028f1e3930ab201994eccd4ff7d1bc18c50e6f3.tar.zst
gsoc2013-empathy-b028f1e3930ab201994eccd4ff7d1bc18c50e6f3.zip
Merge branch 'empathy-skype' into debian
-rw-r--r--configure.ac17
-rw-r--r--data/.gitignore1
-rw-r--r--libempathy-gtk/empathy-account-widget-skype.c86
-rw-r--r--libempathy-gtk/empathy-account-widget.c15
-rw-r--r--libempathy-gtk/empathy-chat.c96
-rw-r--r--libempathy-gtk/empathy-chat.h2
-rw-r--r--libempathy/empathy-tp-chat.c94
-rw-r--r--libempathy/empathy-tp-chat.h6
-rw-r--r--src/Makefile.am2
-rw-r--r--src/empathy-account-assistant.c5
-rw-r--r--src/empathy-call-handler.c13
-rw-r--r--src/empathy-call-window.c113
-rw-r--r--src/empathy-chat-window.c34
13 files changed, 413 insertions, 71 deletions
diff --git a/configure.ac b/configure.ac
index 86d6b805f..c151b3a3f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -42,7 +42,7 @@ LIBCANBERRA_GTK_REQUIRED=0.4
LIBNOTIFY_REQUIRED=0.7.0
TELEPATHY_FARSIGHT_REQUIRED=0.0.14
TELEPATHY_GLIB_REQUIRED=0.14.1
-TELEPATHY_LOGGER=0.2.0
+TELEPATHY_LOGGER=0.2.8
UNIQUE_REQUIRED=1.1.2
# Optionnal deps
@@ -200,6 +200,21 @@ if test "x$with_call" = "xyes" -a "x$have_farstream" != "xyes"; then
fi
AM_CONDITIONAL(HAVE_CALL, test "x$have_farstream" = "xyes")
+
+# -----------------------------------------------------------
+# Call support in tp-logger
+# -----------------------------------------------------------
+SAVE_CFLAGS=$CFLAGS
+SAVE_CPPFLAGS=$CPPFLAGS
+CFLAGS="$CFLAGS $EMPATHY_CFLAGS"
+CPPFLAGS="$CPPFLAGS $EMPATHY_CFLAGS"
+
+AC_CHECK_HEADER(telepathy-logger/call-event.h,,
+ AC_MSG_ERROR([tp-logger must be compiled with --enable-call]))
+
+CFLAGS=$SAVE_CFLAGS
+CPPFLAGS=$SAVE_CPPFLAGS
+
# -----------------------------------------------------------
# evolution-data-server (about-me)
# -----------------------------------------------------------
diff --git a/data/.gitignore b/data/.gitignore
index 7ec3d4d81..902e80747 100644
--- a/data/.gitignore
+++ b/data/.gitignore
@@ -7,3 +7,4 @@ org.freedesktop.Telepathy.Client.Empathy.AudioVideo.service
empathy-accounts.desktop
empathy-accounts.desktop.in
org.freedesktop.Telepathy.Client.Empathy.Auth.service
+org.freedesktop.Telepathy.Client.Empathy.Call.service
diff --git a/libempathy-gtk/empathy-account-widget-skype.c b/libempathy-gtk/empathy-account-widget-skype.c
index 9b8e6270f..288fc039a 100644
--- a/libempathy-gtk/empathy-account-widget-skype.c
+++ b/libempathy-gtk/empathy-account-widget-skype.c
@@ -149,7 +149,6 @@ auth_observer_observe_channels (TpSimpleObserver *auth_observer,
TpChannel *channel;
GHashTable *props;
GStrv available_mechanisms;
- GtkWidget *password_entry = user_data;
const char *password = NULL;
gboolean remember;
@@ -157,11 +156,11 @@ auth_observer_observe_channels (TpSimpleObserver *auth_observer,
if (tp_strdiff (
tp_connection_get_connection_manager_name (connection),
"psyke"))
- goto except;
+ goto finally;
/* can only deal with one channel */
if (g_list_length (channels) != 1)
- goto except;
+ goto finally;
channel = channels->data;
props = tp_channel_borrow_immutable_properties (channel);
@@ -172,18 +171,14 @@ auth_observer_observe_channels (TpSimpleObserver *auth_observer,
/* must support X-TELEPATHY-PASSWORD */
if (!tp_strv_contains ((const char * const *) available_mechanisms,
"X-TELEPATHY-PASSWORD"))
- goto except;
+ goto finally;
- /* do we have a password */
- if (g_object_get_data (G_OBJECT (password_entry), "fake-password") == NULL)
- password = gtk_entry_get_text (GTK_ENTRY (password_entry));
+ password = g_object_get_data (G_OBJECT (auth_observer), "password");
+ remember = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (auth_observer),
+ "remember-password"));
if (tp_str_empty (password))
- goto except;
-
- /* do we want to remember it */
- remember = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
- g_object_get_data (G_OBJECT (password_entry), "remember-password")));
+ goto finally;
DEBUG ("claiming auth channel");
@@ -191,12 +186,12 @@ auth_observer_observe_channels (TpSimpleObserver *auth_observer,
auth_observer_claim_cb,
observe_channels_data_new (account, channel, password, remember));
-except:
+finally:
tp_observe_channels_context_accept (context);
}
static TpBaseClient *
-auth_observer_new (GtkWidget *password_entry)
+auth_observer_new (void)
{
TpDBusDaemon *dbus;
TpBaseClient *auth_observer;
@@ -212,7 +207,7 @@ auth_observer_new (GtkWidget *password_entry)
}
auth_observer = tp_simple_observer_new (dbus, FALSE, "Empathy.PsykePreAuth",
- FALSE, auth_observer_observe_channels, password_entry, NULL);
+ FALSE, auth_observer_observe_channels, NULL, NULL);
tp_base_client_set_observer_delay_approvers (auth_observer, TRUE);
tp_base_client_take_observer_filter (auth_observer, tp_asv_new (
@@ -365,7 +360,7 @@ account_widget_build_skype_get_password_saved_cb (TpProxy *account,
gpointer user_data,
GObject *password_entry)
{
- GtkWidget *remember_password;
+ GtkWidget *remember_password = user_data;
gboolean password_saved;
if (in_error != NULL)
@@ -385,9 +380,6 @@ account_widget_build_skype_get_password_saved_cb (TpProxy *account,
!tp_str_empty (gtk_entry_get_text (GTK_ENTRY (password_entry))))
return;
- remember_password =
- GTK_WIDGET (g_object_get_data (password_entry, "remember-password"));
-
gtk_entry_set_text (GTK_ENTRY (password_entry),
password_saved ? "xxxxxxxxxxxx": "");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (remember_password),
@@ -417,7 +409,7 @@ account_widget_build_skype_account_properties_changed_cb (TpProxy *account,
return;
account_widget_build_skype_get_password_saved_cb (account, value, NULL,
- NULL, password_entry);
+ user_data, password_entry);
}
static void
@@ -453,6 +445,26 @@ account_widget_skype_additional_apply_async (EmpathyAccountWidget *self,
TpAccount *account = empathy_account_settings_get_account (priv->settings);
GSimpleAsyncResult *simple = g_simple_async_result_new (G_OBJECT (self),
callback, user_data, NULL);
+ GtkWidget *password_entry, *remember_password;
+ GObject *auth_observer;
+ const char *password = NULL;
+ gboolean remember;
+
+ /* sync the password with the observer */
+ auth_observer = g_object_get_data (G_OBJECT (self), "auth-observer");
+ password_entry = g_object_get_data (G_OBJECT (self), "password-entry");
+ remember_password = g_object_get_data (G_OBJECT (self), "remember-password");
+
+ if (g_object_get_data (G_OBJECT (password_entry), "fake-password") == NULL)
+ password = gtk_entry_get_text (GTK_ENTRY (password_entry));
+
+ remember = gtk_toggle_button_get_active (
+ GTK_TOGGLE_BUTTON (remember_password));
+
+ g_object_set_data_full (auth_observer, "password",
+ g_strdup (password), g_free);
+ g_object_set_data (auth_observer, "remember-password",
+ GUINT_TO_POINTER (remember));
/* we have to forget the password, else psyke won't query for the new one */
emp_cli_account_interface_external_password_storage_call_forget_password (
@@ -782,6 +794,7 @@ void
empathy_account_widget_build_skype (EmpathyAccountWidget *self,
const char *filename)
{
+ static TpBaseClient *auth_observer = NULL;
EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
TpAccount *account = empathy_account_settings_get_account (priv->settings);
GtkWidget *password_entry, *remember_password;
@@ -854,12 +867,17 @@ empathy_account_widget_build_skype (EmpathyAccountWidget *self,
self->ui_details->default_focus = g_strdup ("entry_id");
}
- /* create the Psyke pre-authentication observer --
- * tie the lifetime of the observer to the lifetime of the widget */
- g_object_set_data_full (G_OBJECT (self->ui_details->widget), "auth-observer",
- auth_observer_new (password_entry), g_object_unref);
- g_object_set_data (G_OBJECT (password_entry), "remember-password",
- remember_password);
+ /* create the Psyke pre-authentication observer */
+ if (auth_observer == NULL)
+ {
+ /* the auth observer lives for the lifetime of the process */
+ DEBUG ("Creating Psyke authentication observer");
+ auth_observer = auth_observer_new ();
+ }
+
+ g_object_set_data (G_OBJECT (self), "auth-observer", auth_observer);
+ g_object_set_data (G_OBJECT (self), "password-entry", password_entry);
+ g_object_set_data (G_OBJECT (self), "remember-password", remember_password);
g_object_bind_property (remember_password, "active",
password_entry, "sensitive", G_BINDING_SYNC_CREATE);
@@ -872,10 +890,10 @@ empathy_account_widget_build_skype (EmpathyAccountWidget *self,
EMP_IFACE_ACCOUNT_INTERFACE_EXTERNAL_PASSWORD_STORAGE,
"PasswordSaved",
account_widget_build_skype_get_password_saved_cb,
- NULL, NULL, G_OBJECT (password_entry));
+ remember_password, NULL, G_OBJECT (password_entry));
tp_cli_dbus_properties_connect_to_properties_changed (account,
account_widget_build_skype_account_properties_changed_cb,
- NULL, NULL, G_OBJECT (password_entry), NULL);
+ remember_password, NULL, G_OBJECT (password_entry), NULL);
}
/* if the user changes the password, it's probably no longer a fake
@@ -962,12 +980,16 @@ static gboolean
is_other_psyke_account (TpAccount *ours,
TpAccount *other)
{
- if (ours == NULL)
- return TRUE;
+ gboolean paths_diff;
- return (tp_strdiff (
+ if (ours == NULL)
+ paths_diff = TRUE;
+ else
+ paths_diff = tp_strdiff (
tp_proxy_get_object_path (ours),
- tp_proxy_get_object_path (other)) &&
+ tp_proxy_get_object_path (other));
+
+ return (paths_diff &&
tp_account_is_enabled (other) &&
!tp_strdiff (tp_account_get_connection_manager (other), "psyke"));
}
diff --git a/libempathy-gtk/empathy-account-widget.c b/libempathy-gtk/empathy-account-widget.c
index c78bcb7b8..edc2f98eb 100644
--- a/libempathy-gtk/empathy-account-widget.c
+++ b/libempathy-gtk/empathy-account-widget.c
@@ -866,7 +866,20 @@ static void
account_widget_apply_clicked_cb (GtkWidget *button,
EmpathyAccountWidget *self)
{
- empathy_accounts_dialog_skype_disable_other_accounts (NULL, NULL);
+ EmpathyAccountWidgetPriv *priv = GET_PRIV (self);
+ GtkWidget *parent;
+
+ parent = gtk_widget_get_toplevel (button);
+ if (!GTK_IS_WINDOW (parent) || !gtk_widget_is_toplevel (parent))
+ parent = NULL;
+
+ if (priv->creating_account)
+ {
+ if (!empathy_accounts_dialog_skype_disable_other_accounts (NULL,
+ GTK_WINDOW (parent)))
+ /* the user chose not to proceed */
+ return;
+ }
account_widget_apply_and_log_in (self);
}
diff --git a/libempathy-gtk/empathy-chat.c b/libempathy-gtk/empathy-chat.c
index ee18be657..fd43473dd 100644
--- a/libempathy-gtk/empathy-chat.c
+++ b/libempathy-gtk/empathy-chat.c
@@ -170,6 +170,7 @@ enum {
PROP_REMOTE_CONTACT,
PROP_SHOW_CONTACTS,
PROP_SMS_CHANNEL,
+ PROP_N_MESSAGES_SENDING,
};
static guint signals[LAST_SIGNAL] = { 0 };
@@ -210,6 +211,10 @@ chat_get_property (GObject *object,
case PROP_SMS_CHANNEL:
g_value_set_boolean (value, priv->sms_channel);
break;
+ case PROP_N_MESSAGES_SENDING:
+ g_value_set_uint (value,
+ empathy_chat_get_n_messages_sending (chat));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
@@ -1198,31 +1203,41 @@ static void
chat_send_error_cb (EmpathyTpChat *tp_chat,
const gchar *message_body,
TpChannelTextSendError error_code,
+ const gchar *dbus_error,
EmpathyChat *chat)
{
- const gchar *error;
+ const gchar *error = NULL;
gchar *str;
- switch (error_code) {
- case TP_CHANNEL_TEXT_SEND_ERROR_OFFLINE:
- error = _("offline");
- break;
- case TP_CHANNEL_TEXT_SEND_ERROR_INVALID_CONTACT:
- error = _("invalid contact");
- break;
- case TP_CHANNEL_TEXT_SEND_ERROR_PERMISSION_DENIED:
- error = _("permission denied");
- break;
- case TP_CHANNEL_TEXT_SEND_ERROR_TOO_LONG:
- error = _("too long message");
- break;
- case TP_CHANNEL_TEXT_SEND_ERROR_NOT_IMPLEMENTED:
- error = _("not implemented");
- break;
- case TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN:
- default:
- error = _("unknown");
- break;
+ if (!tp_strdiff (dbus_error, TP_ERROR_STR_INSUFFICIENT_BALANCE)) {
+ error = _("insufficient balance to send message");
+ } else if (!tp_strdiff (dbus_error, TP_ERROR_STR_NOT_CAPABLE)) {
+ error = _("not capable");
+ }
+
+ if (error == NULL) {
+ /* if we didn't find a dbus-error, try the old error */
+ switch (error_code) {
+ case TP_CHANNEL_TEXT_SEND_ERROR_OFFLINE:
+ error = _("offline");
+ break;
+ case TP_CHANNEL_TEXT_SEND_ERROR_INVALID_CONTACT:
+ error = _("invalid contact");
+ break;
+ case TP_CHANNEL_TEXT_SEND_ERROR_PERMISSION_DENIED:
+ error = _("permission denied");
+ break;
+ case TP_CHANNEL_TEXT_SEND_ERROR_TOO_LONG:
+ error = _("too long message");
+ break;
+ case TP_CHANNEL_TEXT_SEND_ERROR_NOT_IMPLEMENTED:
+ error = _("not implemented");
+ break;
+ case TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN:
+ default:
+ error = _("unknown");
+ break;
+ }
}
if (message_body != NULL) {
@@ -2813,6 +2828,14 @@ empathy_chat_class_init (EmpathyChatClass *klass)
FALSE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class,
+ PROP_N_MESSAGES_SENDING,
+ g_param_spec_uint ("n-messages-sending",
+ "Num Messages Sending",
+ "The number of messages being sent",
+ 0, G_MAXUINT, 0,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
signals[COMPOSING] =
g_signal_new ("composing",
G_OBJECT_CLASS_TYPE (object_class),
@@ -3089,6 +3112,12 @@ chat_sms_channel_changed_cb (EmpathyChat *self)
g_object_notify (G_OBJECT (self), "sms-channel");
}
+static void
+chat_n_messages_sending_changed_cb (EmpathyChat *self)
+{
+ g_object_notify (G_OBJECT (self), "n-messages-sending");
+}
+
void
empathy_chat_set_tp_chat (EmpathyChat *chat,
EmpathyTpChat *tp_chat)
@@ -3143,6 +3172,9 @@ empathy_chat_set_tp_chat (EmpathyChat *chat,
g_signal_connect_swapped (tp_chat, "notify::sms-channel",
G_CALLBACK (chat_sms_channel_changed_cb),
chat);
+ g_signal_connect_swapped (tp_chat, "notify::n-messages-sending",
+ G_CALLBACK (chat_n_messages_sending_changed_cb),
+ chat);
/* Get initial value of properties */
properties = empathy_tp_chat_get_properties (priv->tp_chat);
@@ -3439,3 +3471,25 @@ empathy_chat_is_sms_channel (EmpathyChat *self)
return priv->sms_channel;
}
+
+guint
+empathy_chat_get_n_messages_sending (EmpathyChat *self)
+{
+ EmpathyChatPriv *priv;
+
+ g_return_val_if_fail (EMPATHY_IS_CHAT (self), 0);
+
+ priv = GET_PRIV (self);
+
+ if (priv->tp_chat == NULL) {
+ return 0;
+ } else {
+ guint n_messages;
+
+ g_object_get (priv->tp_chat,
+ "n-messages-sending", &n_messages,
+ NULL);
+
+ return n_messages;
+ }
+}
diff --git a/libempathy-gtk/empathy-chat.h b/libempathy-gtk/empathy-chat.h
index 08472400e..0fd779cc6 100644
--- a/libempathy-gtk/empathy-chat.h
+++ b/libempathy-gtk/empathy-chat.h
@@ -90,6 +90,8 @@ guint empathy_chat_get_nb_unread_messages (EmpathyChat *chat);
void empathy_chat_messages_read (EmpathyChat *self);
gboolean empathy_chat_is_sms_channel (EmpathyChat *self);
+guint empathy_chat_get_n_messages_sending (EmpathyChat *self);
+
G_END_DECLS
#endif /* __EMPATHY_CHAT_H__ */
diff --git a/libempathy/empathy-tp-chat.c b/libempathy/empathy-tp-chat.c
index e829d6e6b..29f886416 100644
--- a/libempathy/empathy-tp-chat.c
+++ b/libempathy/empathy-tp-chat.c
@@ -31,6 +31,7 @@
#include "empathy-tp-contact-factory.h"
#include "empathy-contact-list.h"
#include "empathy-dispatcher.h"
+#include "empathy-enum-types.h"
#include "empathy-marshal.h"
#include "empathy-time.h"
#include "empathy-utils.h"
@@ -61,6 +62,8 @@ typedef struct {
gboolean can_upgrade_to_muc;
gboolean got_sms_channel;
gboolean sms_channel;
+
+ GHashTable *messages_being_sent;
} EmpathyTpChatPriv;
static void tp_chat_iface_init (EmpathyContactListIface *iface);
@@ -73,6 +76,7 @@ enum {
PROP_PASSWORD_NEEDED,
PROP_READY,
PROP_SMS_CHANNEL,
+ PROP_N_MESSAGES_SENDING,
};
enum {
@@ -93,6 +97,39 @@ G_DEFINE_TYPE_WITH_CODE (EmpathyTpChat, empathy_tp_chat, G_TYPE_OBJECT,
static void acknowledge_messages (EmpathyTpChat *chat, GArray *ids);
static void
+tp_chat_set_delivery_status (EmpathyTpChat *self,
+ const gchar *token,
+ EmpathyDeliveryStatus delivery_status)
+{
+ EmpathyTpChatPriv *priv = GET_PRIV (self);
+
+ /* channel must support receiving failures and successes */
+ if (!tp_str_empty (token) &&
+ tp_text_channel_get_delivery_reporting_support (
+ TP_TEXT_CHANNEL (priv->channel)) &
+ (TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_FAILURES |
+ TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_SUCCESSES)) {
+
+ DEBUG ("Delivery status (%s) = %u", token, delivery_status);
+
+ switch (delivery_status) {
+ case EMPATHY_DELIVERY_STATUS_NONE:
+ g_hash_table_remove (priv->messages_being_sent,
+ token);
+ break;
+
+ default:
+ g_hash_table_insert (priv->messages_being_sent,
+ g_strdup (token),
+ GUINT_TO_POINTER (delivery_status));
+ break;
+ }
+
+ g_object_notify (G_OBJECT (self), "n-messages-sending");
+ }
+}
+
+static void
tp_chat_invalidated_cb (TpProxy *proxy,
guint domain,
gint code,
@@ -322,19 +359,38 @@ handle_delivery_report (EmpathyTpChat *self,
gboolean valid;
GPtrArray *echo;
const gchar *message_body = NULL;
+ const gchar *delivery_dbus_error;
+ const gchar *delivery_token = NULL;
header = tp_message_peek (message, 0);
if (header == NULL)
goto out;
+ delivery_token = tp_asv_get_string (header, "delivery-token");
delivery_status = tp_asv_get_uint32 (header, "delivery-status", &valid);
- if (!valid || delivery_status != TP_DELIVERY_STATUS_PERMANENTLY_FAILED)
+
+ if (!valid) {
+ goto out;
+ } else if (delivery_status == TP_DELIVERY_STATUS_ACCEPTED) {
+ DEBUG ("Accepted %s", delivery_token);
+ tp_chat_set_delivery_status (self, delivery_token,
+ EMPATHY_DELIVERY_STATUS_ACCEPTED);
+ goto out;
+ } else if (delivery_status == TP_DELIVERY_STATUS_DELIVERED) {
+ DEBUG ("Delivered %s", delivery_token);
+ tp_chat_set_delivery_status (self, delivery_token,
+ EMPATHY_DELIVERY_STATUS_NONE);
+ goto out;
+ } else if (delivery_status != TP_DELIVERY_STATUS_PERMANENTLY_FAILED) {
goto out;
+ }
delivery_error = tp_asv_get_uint32 (header, "delivery-error", &valid);
if (!valid)
delivery_error = TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN;
+ delivery_dbus_error = tp_asv_get_string (header, "delivery-dbus-error");
+
/* TODO: ideally we should use tp-glib API giving us the echoed message as a
* TpMessage. (fdo #35884) */
echo = tp_asv_get_boxed (header, "delivery-echo",
@@ -347,7 +403,10 @@ handle_delivery_report (EmpathyTpChat *self,
message_body = tp_asv_get_string (echo_body, "content");
}
- g_signal_emit (self, signals[SEND_ERROR], 0, message_body, delivery_error);
+ tp_chat_set_delivery_status (self, delivery_token,
+ EMPATHY_DELIVERY_STATUS_NONE);
+ g_signal_emit (self, signals[SEND_ERROR], 0, message_body,
+ delivery_error, delivery_dbus_error);
out:
tp_text_channel_ack_message_async (TP_TEXT_CHANNEL (priv->channel),
@@ -439,9 +498,10 @@ message_send_cb (GObject *source,
{
EmpathyTpChat *chat = user_data;
TpTextChannel *channel = (TpTextChannel *) source;
+ gchar *token = NULL;
GError *error = NULL;
- if (!tp_text_channel_send_message_finish (channel, result, NULL, &error)) {
+ if (!tp_text_channel_send_message_finish (channel, result, &token, &error)) {
DEBUG ("Error: %s", error->message);
/* FIXME: we should use the body of the message as first argument of the
@@ -449,10 +509,14 @@ message_send_cb (GObject *source,
* we'll have rebased EmpathyTpChat on top of TpTextChannel we'll be able
* to use the user_data pointer to pass the message and fix this. */
g_signal_emit (chat, signals[SEND_ERROR], 0,
- NULL, error_to_text_send_error (error));
+ NULL, error_to_text_send_error (error), NULL);
g_error_free (error);
}
+
+ tp_chat_set_delivery_status (chat, token,
+ EMPATHY_DELIVERY_STATUS_SENDING);
+ g_free (token);
}
typedef struct {
@@ -812,6 +876,7 @@ tp_chat_finalize (GObject *object)
g_queue_free (priv->messages_queue);
g_queue_free (priv->pending_messages_queue);
+ g_hash_table_destroy (priv->messages_being_sent);
G_OBJECT_CLASS (empathy_tp_chat_parent_class)->finalize (object);
}
@@ -1414,6 +1479,10 @@ tp_chat_get_property (GObject *object,
case PROP_SMS_CHANNEL:
g_value_set_boolean (value, priv->sms_channel);
break;
+ case PROP_N_MESSAGES_SENDING:
+ g_value_set_uint (value,
+ g_hash_table_size (priv->messages_being_sent));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
@@ -1503,6 +1572,14 @@ empathy_tp_chat_class_init (EmpathyTpChatClass *klass)
FALSE,
G_PARAM_READABLE));
+ g_object_class_install_property (object_class,
+ PROP_N_MESSAGES_SENDING,
+ g_param_spec_uint ("n-messages-sending",
+ "Num Messages Sending",
+ "The number of messages being sent",
+ 0, G_MAXUINT, 0,
+ G_PARAM_READABLE));
+
/* Signals */
signals[MESSAGE_RECEIVED] =
g_signal_new ("message-received",
@@ -1520,9 +1597,9 @@ empathy_tp_chat_class_init (EmpathyTpChatClass *klass)
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
- _empathy_marshal_VOID__STRING_UINT,
+ _empathy_marshal_VOID__STRING_UINT_STRING,
G_TYPE_NONE,
- 2, G_TYPE_STRING, G_TYPE_UINT);
+ 3, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING);
signals[CHAT_STATE_CHANGED] =
g_signal_new ("chat-state-changed",
@@ -1566,6 +1643,8 @@ empathy_tp_chat_init (EmpathyTpChat *chat)
chat->priv = priv;
priv->messages_queue = g_queue_new ();
priv->pending_messages_queue = g_queue_new ();
+ priv->messages_being_sent = g_hash_table_new_full (
+ g_str_hash, g_str_equal, g_free, NULL);
}
static void
@@ -1684,7 +1763,8 @@ empathy_tp_chat_send (EmpathyTpChat *chat,
DEBUG ("Sending message: %s", message_body);
tp_text_channel_send_message_async (TP_TEXT_CHANNEL (priv->channel),
- message, 0, message_send_cb, chat);
+ message, TP_MESSAGE_SENDING_FLAG_REPORT_DELIVERY,
+ message_send_cb, chat);
g_free (message_body);
}
diff --git a/libempathy/empathy-tp-chat.h b/libempathy/empathy-tp-chat.h
index d72c30e06..34651d13c 100644
--- a/libempathy/empathy-tp-chat.h
+++ b/libempathy/empathy-tp-chat.h
@@ -59,6 +59,12 @@ typedef struct {
GValue *value;
} EmpathyTpChatProperty;
+typedef enum {
+ EMPATHY_DELIVERY_STATUS_NONE,
+ EMPATHY_DELIVERY_STATUS_SENDING,
+ EMPATHY_DELIVERY_STATUS_ACCEPTED
+} EmpathyDeliveryStatus;
+
GType empathy_tp_chat_get_type (void) G_GNUC_CONST;
EmpathyTpChat *empathy_tp_chat_new (TpAccount *account,
TpChannel *channel);
diff --git a/src/Makefile.am b/src/Makefile.am
index 246296172..3915f0404 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -259,7 +259,7 @@ dist_man_MANS = \
src-marshal.list: $(empathy_SOURCES) Makefile.am
$(AM_V_GEN)( cd $(srcdir) && \
sed -n -e 's/.*src_marshal_\([[:upper:][:digit:]]*__[[:upper:][:digit:]_]*\).*/\1/p' \
- $(empathy_SOURCES) $(empathy_av_SOURCES) ) \
+ $(empathy_SOURCES) $(empathy_av_SOURCES) $(empathy_call_SOURCES) ) \
| sed -e 's/__/:/' -e 'y/_/,/' | sort -u > $@.tmp
@if cmp -s $@.tmp $@; then \
rm $@.tmp; \
diff --git a/src/empathy-account-assistant.c b/src/empathy-account-assistant.c
index f7753bdb3..e3fffc2ed 100644
--- a/src/empathy-account-assistant.c
+++ b/src/empathy-account-assistant.c
@@ -565,6 +565,11 @@ account_assistant_finish_enter_or_create_page (EmpathyAccountAssistant *self,
_("Enter the details for the new account"));
}
+ /* if someone clicked 'Back' this signal handler can be connected twice:
+ * disconnect any existing handlers */
+ g_signal_handlers_disconnect_by_func (priv->chooser,
+ account_assistant_protocol_changed_cb, self);
+
g_signal_connect (priv->chooser, "changed",
G_CALLBACK (account_assistant_protocol_changed_cb), self);
diff --git a/src/empathy-call-handler.c b/src/empathy-call-handler.c
index aff96bd6e..56d109838 100644
--- a/src/empathy-call-handler.c
+++ b/src/empathy-call-handler.c
@@ -189,13 +189,18 @@ static void
on_call_state_changed_cb (TpyCallChannel *call,
TpyCallState state,
TpyCallFlags flags,
- const GValueArray *call_state_reason,
+ const GValueArray *call_state_reason,
GHashTable *call_state_details,
EmpathyCallHandler *handler)
{
EmpathyCallHandlerPriv *priv = handler->priv;
+ gchar *dbus_reason;
+ guint actor, reason;
- g_signal_emit (handler, signals[STATE_CHANGED], 0, state);
+ tp_value_array_unpack ((GValueArray *) call_state_reason, 3,
+ &actor, &reason, &dbus_reason);
+
+ g_signal_emit (handler, signals[STATE_CHANGED], 0, state, dbus_reason);
if (state == TPY_CALL_STATE_ENDED)
{
@@ -503,8 +508,8 @@ empathy_call_handler_class_init (EmpathyCallHandlerClass *klass)
signals[STATE_CHANGED] =
g_signal_new ("state-changed", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
- g_cclosure_marshal_VOID__UINT,
- G_TYPE_NONE, 1, G_TYPE_UINT);
+ _src_marshal_VOID__UINT_STRING,
+ G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_STRING);
}
EmpathyCallHandler *
diff --git a/src/empathy-call-window.c b/src/empathy-call-window.c
index fdb753245..3f260327a 100644
--- a/src/empathy-call-window.c
+++ b/src/empathy-call-window.c
@@ -2110,14 +2110,37 @@ empathy_call_window_update_timer (gpointer user_data)
return TRUE;
}
-#if 0
+enum
+{
+ EMP_RESPONSE_BALANCE
+};
+
+static void
+on_error_infobar_response_cb (GtkInfoBar *info_bar,
+ gint response_id,
+ gpointer user_data)
+{
+ switch (response_id)
+ {
+ case GTK_RESPONSE_CLOSE:
+ gtk_widget_destroy (GTK_WIDGET (info_bar));
+ break;
+ case EMP_RESPONSE_BALANCE:
+ empathy_url_show (GTK_WIDGET (info_bar),
+ g_object_get_data (G_OBJECT (info_bar), "uri"));
+ break;
+ }
+}
+
static void
display_error (EmpathyCallWindow *self,
- TpyCallChannel *call,
const gchar *img,
const gchar *title,
const gchar *desc,
- const gchar *details)
+ const gchar *details,
+ const gchar *button_text,
+ const gchar *uri,
+ gint button_response)
{
EmpathyCallWindowPriv *priv = GET_PRIV (self);
GtkWidget *info_bar;
@@ -2132,6 +2155,14 @@ display_error (EmpathyCallWindow *self,
info_bar = gtk_info_bar_new_with_buttons (GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
NULL);
+ if (button_text != NULL)
+ {
+ gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
+ button_text, button_response);
+ g_object_set_data_full (G_OBJECT (info_bar),
+ "uri", g_strdup (uri), g_free);
+ }
+
gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), GTK_MESSAGE_WARNING);
content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (info_bar));
@@ -2179,13 +2210,14 @@ display_error (EmpathyCallWindow *self,
}
g_signal_connect (info_bar, "response",
- G_CALLBACK (gtk_widget_destroy), NULL);
+ G_CALLBACK (on_error_infobar_response_cb), NULL);
gtk_box_pack_start (GTK_BOX (priv->errors_vbox), info_bar,
FALSE, FALSE, CONTENT_HBOX_CHILDREN_PACKING_PADDING);
gtk_widget_show_all (info_bar);
}
+#if 0
static gchar *
media_stream_error_to_txt (EmpathyCallWindow *self,
TpyCallChannel *call,
@@ -2305,14 +2337,87 @@ empathy_call_window_video_stream_error (TpyCallChannel *call,
#endif
static void
+got_balance_props (TpProxy *proxy,
+ GHashTable *props,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ EmpathyCallWindow *self = EMPATHY_CALL_WINDOW (weak_object);
+ GValueArray *balance;
+ gchar *balance_str, *currency, *tmp;
+ const gchar *uri;
+ gint amount, scale;
+
+ if (error != NULL)
+ {
+ DEBUG ("Failed to get Balance: %s", error->message);
+ return;
+ }
+
+ balance = tp_asv_get_boxed (props, "AccountBalance",
+ TP_STRUCT_TYPE_CURRENCY_AMOUNT);
+ uri = tp_asv_get_string (props, "ManageCreditURI");
+ tp_value_array_unpack (balance, 3,
+ &amount,
+ &scale,
+ &currency);
+
+ if (amount == 0 &&
+ scale == G_MAXINT32 &&
+ tp_str_empty (currency))
+ {
+ /* unknown balance */
+ balance_str = g_strdup ("(--)");
+ }
+ else
+ {
+ char *money = empathy_format_currency (amount, scale, currency);
+
+ balance_str = g_strdup_printf ("%s %s",
+ currency, money);
+ g_free (money);
+ }
+
+ /* FIXME: don't hardcode Skype here */
+ display_error (self,
+ NULL,
+ _("Sorry, you don’t have enough Skype Credit for that call."),
+ tmp = g_strdup_printf (_("Your current balance is %s."),
+ balance_str),
+ NULL,
+ _("Buy Skype credit..."),
+ uri,
+ EMP_RESPONSE_BALANCE);
+ g_free (tmp);
+}
+
+static void
empathy_call_window_state_changed_cb (EmpathyCallHandler *handler,
TpyCallState state,
+ gchar *reason,
EmpathyCallWindow *self)
{
EmpathyCallWindowPriv *priv = GET_PRIV (self);
TpyCallChannel *call;
gboolean can_send_video;
+ if (state == TPY_CALL_STATE_ENDED &&
+ !tp_strdiff (reason, TP_ERROR_STR_INSUFFICIENT_BALANCE))
+ {
+ g_object_get (handler, "call-channel", &call, NULL);
+
+ tp_cli_dbus_properties_call_get_all (
+ tp_channel_borrow_connection (TP_CHANNEL (call)),
+ -1,
+ TP_IFACE_CONNECTION_INTERFACE_BALANCE,
+ got_balance_props,
+ NULL, NULL, G_OBJECT (self));
+
+ g_object_unref (call);
+ return;
+ }
+
if (state != TPY_CALL_STATE_ACCEPTED)
return;
diff --git a/src/empathy-chat-window.c b/src/empathy-chat-window.c
index aa7a1a152..4bbf1a789 100644
--- a/src/empathy-chat-window.c
+++ b/src/empathy-chat-window.c
@@ -294,6 +294,16 @@ chat_window_create_label (EmpathyChatWindow *window,
gtk_box_pack_start (GTK_BOX (hbox), event_box, TRUE, TRUE, 0);
if (is_tab_label) {
+ GtkWidget *sending_spinner;
+
+ sending_spinner = gtk_spinner_new ();
+
+ gtk_box_pack_start (GTK_BOX (hbox), sending_spinner,
+ FALSE, FALSE, 0);
+ g_object_set_data (G_OBJECT (chat),
+ "chat-window-tab-sending-spinner",
+ sending_spinner);
+
close_button = gtk_button_new ();
gtk_button_set_relief (GTK_BUTTON (close_button), GTK_RELIEF_NONE);
g_object_set_data (G_OBJECT (chat), "chat-window-tab-close-button", close_button);
@@ -647,6 +657,8 @@ chat_window_update_chat_tab_full (EmpathyChat *chat,
const gchar *icon_name;
GtkWidget *tab_image;
GtkWidget *menu_image;
+ GtkWidget *sending_spinner;
+ guint nb_sending;
window = chat_window_find_chat (chat);
if (!window) {
@@ -695,6 +707,16 @@ chat_window_update_chat_tab_full (EmpathyChat *chat,
gtk_widget_hide (menu_image);
}
+ /* Update the sending spinner */
+ nb_sending = empathy_chat_get_n_messages_sending (chat);
+ sending_spinner = g_object_get_data (G_OBJECT (chat),
+ "chat-window-tab-sending-spinner");
+
+ g_object_set (sending_spinner,
+ "active", nb_sending > 0,
+ "visible", nb_sending > 0,
+ NULL);
+
/* Update tab tooltip */
tooltip = g_string_new (NULL);
@@ -714,6 +736,15 @@ chat_window_update_chat_tab_full (EmpathyChat *chat,
id,
tp_account_get_display_name (account));
+ if (nb_sending > 0) {
+ append_markup_printf (tooltip, "\n");
+ append_markup_printf (tooltip,
+ ngettext ("Sending %d message",
+ "Sending %d messages",
+ nb_sending),
+ nb_sending);
+ }
+
if (!EMP_STR_EMPTY (status)) {
append_markup_printf (tooltip, "\n<i>%s</i>", status);
}
@@ -2239,6 +2270,9 @@ empathy_chat_window_add_chat (EmpathyChatWindow *window,
g_signal_connect (chat, "notify::sms-channel",
G_CALLBACK (chat_window_chat_notify_cb),
NULL);
+ g_signal_connect (chat, "notify::n-messages-sending",
+ G_CALLBACK (chat_window_chat_notify_cb),
+ NULL);
chat_window_chat_notify_cb (chat);
gtk_notebook_append_page_menu (GTK_NOTEBOOK (priv->notebook), child, label, popup_label);