aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy/empathy-tp-file.c
diff options
context:
space:
mode:
Diffstat (limited to 'libempathy/empathy-tp-file.c')
-rw-r--r--libempathy/empathy-tp-file.c73
1 files changed, 68 insertions, 5 deletions
diff --git a/libempathy/empathy-tp-file.c b/libempathy/empathy-tp-file.c
index c885e0f20..420182f5f 100644
--- a/libempathy/empathy-tp-file.c
+++ b/libempathy/empathy-tp-file.c
@@ -297,6 +297,7 @@ struct _EmpathyTpFilePriv {
time_t start_time;
gchar *unix_socket_path;
GCancellable *cancellable;
+ gboolean keep_alive;
};
enum {
@@ -326,6 +327,18 @@ empathy_tp_file_init (EmpathyTpFile *tp_file)
}
static void
+tp_file_check_keep_alive (EmpathyTpFile *tp_file)
+{
+ if (tp_file->priv->keep_alive &&
+ (tp_file->priv->state == EMP_FILE_TRANSFER_STATE_COMPLETED ||
+ tp_file->priv->state == EMP_FILE_TRANSFER_STATE_CANCELLED))
+ {
+ tp_file->priv->keep_alive = FALSE;
+ g_object_unref (tp_file);
+ }
+}
+
+static void
tp_file_invalidated_cb (TpProxy *proxy,
guint domain,
gint code,
@@ -343,14 +356,14 @@ tp_file_invalidated_cb (TpProxy *proxy,
EMP_FILE_TRANSFER_STATE_CHANGE_REASON_LOCAL_ERROR;
g_object_notify (G_OBJECT (tp_file), "state");
}
+
+ tp_file_check_keep_alive (tp_file);
}
static void
tp_file_finalize (GObject *object)
{
- EmpathyTpFile *tp_file;
-
- tp_file = EMPATHY_TP_FILE (object);
+ EmpathyTpFile *tp_file = EMPATHY_TP_FILE (object);
if (tp_file->priv->channel)
{
@@ -475,6 +488,7 @@ tp_file_state_changed_cb (TpProxy *proxy,
tp_file->priv->state_change_reason = reason;
g_object_notify (G_OBJECT (tp_file), "state");
+ tp_file_check_keep_alive (tp_file);
}
static void
@@ -674,22 +688,50 @@ tp_file_set_property (GObject *object,
};
}
+static GHashTable *ft_table = NULL;
+
+static void
+tp_file_weak_notify_cb (gpointer channel,
+ GObject *tp_file)
+{
+ g_hash_table_remove (ft_table, channel);
+}
+
/**
* empathy_tp_file_new:
* @channel: a Telepathy channel
*
- * Creates a new #EmpathyTpFile wrapping @channel.
+ * Creates a new #EmpathyTpFile wrapping @channel, or return a new ref to an
+ * existing #EmpathyTpFile for that channel.
*
* Returns: a new #EmpathyTpFile
*/
EmpathyTpFile *
empathy_tp_file_new (TpChannel *channel)
{
+ EmpathyTpFile *tp_file;
+
g_return_val_if_fail (TP_IS_CHANNEL (channel), NULL);
- return g_object_new (EMPATHY_TYPE_TP_FILE,
+ if (ft_table != NULL)
+ {
+ tp_file = g_hash_table_lookup (ft_table, channel);
+ if (tp_file != NULL) {
+ return g_object_ref (tp_file);
+ }
+ }
+ else
+ ft_table = g_hash_table_new_full (empathy_proxy_hash,
+ empathy_proxy_equal, (GDestroyNotify) g_object_unref, NULL);
+
+ tp_file = g_object_new (EMPATHY_TYPE_TP_FILE,
"channel", channel,
NULL);
+
+ g_hash_table_insert (ft_table, g_object_ref (channel), tp_file);
+ g_object_weak_ref (G_OBJECT (tp_file), tp_file_weak_notify_cb, channel);
+
+ return tp_file;
}
/**
@@ -798,6 +840,27 @@ empathy_tp_file_offer (EmpathyTpFile *tp_file, GFile *gfile, GError **error)
&nothing, tp_file_method_cb, NULL, NULL, G_OBJECT (tp_file));
}
+/**
+ * empathy_tp_file_keep_alive:
+ * @tp_file: an #EmpathyTpFile
+ *
+ * Keep @tp_file alive until the file transfer is COMPLETED or CANCELLED, by
+ * adding a temporary reference.
+ */
+void
+empathy_tp_file_keep_alive (EmpathyTpFile *tp_file)
+{
+ g_return_if_fail (EMPATHY_IS_TP_FILE (tp_file));
+
+ if (tp_file->priv->keep_alive)
+ return;
+
+ tp_file->priv->keep_alive = TRUE;
+ if (tp_file->priv->state != EMP_FILE_TRANSFER_STATE_COMPLETED &&
+ tp_file->priv->state != EMP_FILE_TRANSFER_STATE_CANCELLED)
+ g_object_ref (tp_file);
+}
+
EmpathyContact *
empathy_tp_file_get_contact (EmpathyTpFile *tp_file)
{