2 * empathy-ft-factory.c - Source for EmpathyFTFactory
3 * Copyright (C) 2009 Collabora Ltd.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * Author: Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
22 /* empathy-ft-factory.c */
26 #include <telepathy-glib/telepathy-glib.h>
28 #include "empathy-ft-factory.h"
29 #include "empathy-ft-handler.h"
30 #include "empathy-marshal.h"
31 #include "empathy-utils.h"
34 * SECTION:empathy-ft-factory
35 * @title:EmpathyFTFactory
36 * @short_description: creates #EmpathyFTHandler objects
37 * @include: libempathy/empathy-ft-factory.h
39 * #EmpathyFTFactory takes care of the creation of the #EmpathyFTHandler
40 * objects used for file transfer. As the creation of the handlers is
41 * async, a client will have to connect to the ::new-ft-handler signal
42 * to receive the handler.
43 * In case of an incoming file transfer, the handler will need the destination
44 * file before being useful; as this is usually decided by the user (e.g. with
45 * a file selector), a ::new-incoming-transfer is emitted by the factory when
46 * a destination file is needed, which can be set later with
47 * empathy_ft_factory_set_destination_for_incoming_handler().
50 G_DEFINE_TYPE (EmpathyFTFactory, empathy_ft_factory, G_TYPE_OBJECT);
54 NEW_INCOMING_TRANSFER,
58 static EmpathyFTFactory *factory_singleton = NULL;
59 static guint signals[LAST_SIGNAL] = { 0 };
61 /* private structure */
63 TpBaseClient *handler;
64 } EmpathyFTFactoryPriv;
66 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyFTFactory)
69 do_constructor (GType type,
71 GObjectConstructParam *props)
75 if (factory_singleton != NULL) {
76 retval = g_object_ref (factory_singleton);
78 retval = G_OBJECT_CLASS (empathy_ft_factory_parent_class)->constructor
79 (type, n_props, props);
81 factory_singleton = EMPATHY_FT_FACTORY (retval);
82 g_object_add_weak_pointer (retval, (gpointer *) &factory_singleton);
89 empathy_ft_factory_class_init (EmpathyFTFactoryClass *klass)
91 GObjectClass *object_class = G_OBJECT_CLASS (klass);
93 g_type_class_add_private (klass, sizeof (EmpathyFTFactoryPriv));
95 object_class->constructor = do_constructor;
98 * EmpathyFTFactory::new-ft-handler
99 * @factory: the object which received the signal
100 * @handler: the handler made available by the factory
101 * @error: a #GError or %NULL
103 * The signal is emitted when a new #EmpathyFTHandler is available.
104 * Note that @handler is never %NULL even if @error is set, as you might want
105 * to display the error in an UI; in that case, the handler won't support
108 signals[NEW_FT_HANDLER] =
109 g_signal_new ("new-ft-handler",
110 G_TYPE_FROM_CLASS (klass),
111 G_SIGNAL_RUN_LAST, 0,
113 _empathy_marshal_VOID__OBJECT_POINTER,
114 G_TYPE_NONE, 2, EMPATHY_TYPE_FT_HANDLER, G_TYPE_POINTER);
117 * EmpathyFTFactory::new-incoming-transfer
118 * @factory: the object which received the signal
119 * @handler: the incoming handler being constructed
120 * @error: a #GError or %NULL
122 * The signal is emitted when a new incoming #EmpathyFTHandler is being
123 * constructed, and needs a destination #GFile to be useful.
124 * Clients that connect to this signal will have to call
125 * empathy_ft_factory_set_destination_for_incoming_handler() when they
127 * Note that @handler is never %NULL even if @error is set, as you might want
128 * to display the error in an UI; in that case, the handler won't support
131 signals[NEW_INCOMING_TRANSFER] =
132 g_signal_new ("new-incoming-transfer",
133 G_TYPE_FROM_CLASS (klass),
134 G_SIGNAL_RUN_LAST, 0,
136 _empathy_marshal_VOID__OBJECT_POINTER,
137 G_TYPE_NONE, 2, EMPATHY_TYPE_FT_HANDLER, G_TYPE_POINTER);
141 ft_handler_incoming_ready_cb (EmpathyFTHandler *handler,
145 EmpathyFTFactory *factory = user_data;
147 g_signal_emit (factory, signals[NEW_INCOMING_TRANSFER], 0, handler, error);
151 handle_channels_cb (TpSimpleHandler *handler,
153 TpConnection *connection,
155 GList *requests_satisfied,
156 gint64 user_action_time,
157 TpHandleChannelsContext *context,
160 EmpathyFTFactory *self = user_data;
163 for (l = channels; l != NULL; l = g_list_next (l))
165 TpChannel *channel = l->data;
166 EmpathyTpFile *tp_file;
168 if (tp_proxy_get_invalidated (channel) != NULL)
171 if (tp_channel_get_channel_type_id (channel) !=
172 TP_IFACE_QUARK_CHANNEL_TYPE_FILE_TRANSFER)
175 tp_file = empathy_tp_file_new (channel);
177 /* We handle only incoming FT */
178 empathy_ft_handler_new_incoming (tp_file, ft_handler_incoming_ready_cb,
181 g_object_unref (tp_file);
185 tp_handle_channels_context_accept (context);
189 empathy_ft_factory_init (EmpathyFTFactory *self)
191 EmpathyFTFactoryPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
192 EMPATHY_TYPE_FT_FACTORY, EmpathyFTFactoryPriv);
194 GError *error = NULL;
198 dbus = tp_dbus_daemon_dup (&error);
201 g_warning ("Failed to get TpDBusDaemon: %s", error->message);
202 g_error_free (error);
206 priv->handler = tp_simple_handler_new (dbus, FALSE, FALSE,
207 "Empathy.FileTransfer", FALSE, handle_channels_cb, self, NULL);
209 tp_base_client_take_handler_filter (priv->handler, tp_asv_new (
210 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
211 TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER,
212 TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
213 /* Only handle *incoming* channels as outgoing FT channels has to be
214 * handled by the requester. */
215 TP_PROP_CHANNEL_REQUESTED, G_TYPE_BOOLEAN, FALSE,
218 g_object_unref (dbus);
222 ft_handler_outgoing_ready_cb (EmpathyFTHandler *handler,
226 EmpathyFTFactory *factory = user_data;
228 g_signal_emit (factory, signals[NEW_FT_HANDLER], 0, handler, error);
234 * empathy_ft_factory_dup_singleton:
236 * Gives the caller a reference to the #EmpathyFTFactory singleton,
237 * (creating it if necessary).
239 * Return value: an #EmpathyFTFactory object
242 empathy_ft_factory_dup_singleton (void)
244 return g_object_new (EMPATHY_TYPE_FT_FACTORY, NULL);
248 * empathy_ft_factory_new_transfer_outgoing:
249 * @factory: an #EmpathyFTFactory
250 * @contact: the #EmpathyContact destination of the transfer
251 * @source: the #GFile to be transferred to @contact
253 * Trigger the creation of an #EmpathyFTHandler object to send @source to
254 * the specified @contact.
257 empathy_ft_factory_new_transfer_outgoing (EmpathyFTFactory *factory,
258 EmpathyContact *contact,
261 g_return_if_fail (EMPATHY_IS_FT_FACTORY (factory));
262 g_return_if_fail (EMPATHY_IS_CONTACT (contact));
263 g_return_if_fail (G_IS_FILE (source));
265 empathy_ft_handler_new_outgoing (contact, source,
266 ft_handler_outgoing_ready_cb, factory);
270 * empathy_ft_factory_set_destination_for_incoming_handler:
271 * @factory: an #EmpathyFTFactory
272 * @handler: the #EmpathyFTHandler to set the destination of
273 * @destination: the #GFile destination of the transfer
275 * Sets @destination as destination file for the transfer. After the call of
276 * this method, the ::new-ft-handler will be emitted for the incoming handler.
279 empathy_ft_factory_set_destination_for_incoming_handler (
280 EmpathyFTFactory *factory,
281 EmpathyFTHandler *handler,
284 g_return_if_fail (EMPATHY_IS_FT_FACTORY (factory));
285 g_return_if_fail (EMPATHY_IS_FT_HANDLER (handler));
286 g_return_if_fail (G_IS_FILE (destination));
288 empathy_ft_handler_incoming_set_destination (handler, destination);
290 g_signal_emit (factory, signals[NEW_FT_HANDLER], 0, handler, NULL);
294 empathy_ft_factory_register (EmpathyFTFactory *self,
297 EmpathyFTFactoryPriv *priv = GET_PRIV (self);
299 return tp_base_client_register (priv->handler, error);