]> git.0d.be Git - empathy.git/blob - libempathy/empathy-ft-factory.c
Updated Persian translation
[empathy.git] / libempathy / empathy-ft-factory.c
1 /*
2  * empathy-ft-factory.c - Source for EmpathyFTFactory
3  * Copyright (C) 2009 Collabora Ltd.
4  *
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.
9  *
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.
14  *
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
18  *
19  * Author: Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
20  */
21
22 /* empathy-ft-factory.c */
23
24 #include <glib.h>
25
26 #include <telepathy-glib/telepathy-glib.h>
27
28 #include "empathy-ft-factory.h"
29 #include "empathy-ft-handler.h"
30 #include "empathy-marshal.h"
31 #include "empathy-request-util.h"
32 #include "empathy-utils.h"
33
34 /**
35  * SECTION:empathy-ft-factory
36  * @title:EmpathyFTFactory
37  * @short_description: creates #EmpathyFTHandler objects
38  * @include: libempathy/empathy-ft-factory.h
39  *
40  * #EmpathyFTFactory takes care of the creation of the #EmpathyFTHandler
41  * objects used for file transfer. As the creation of the handlers is
42  * async, a client will have to connect to the ::new-ft-handler signal
43  * to receive the handler.
44  * In case of an incoming file transfer, the handler will need the destination
45  * file before being useful; as this is usually decided by the user (e.g. with
46  * a file selector), a ::new-incoming-transfer is emitted by the factory when
47  * a destination file is needed, which can be set later with
48  * empathy_ft_factory_set_destination_for_incoming_handler().
49  */
50
51 G_DEFINE_TYPE (EmpathyFTFactory, empathy_ft_factory, G_TYPE_OBJECT);
52
53 enum {
54   NEW_FT_HANDLER,
55   NEW_INCOMING_TRANSFER,
56   LAST_SIGNAL
57 };
58
59 static EmpathyFTFactory *factory_singleton = NULL;
60 static guint signals[LAST_SIGNAL] = { 0 };
61
62 /* private structure */
63 typedef struct {
64   TpBaseClient *handler;
65 } EmpathyFTFactoryPriv;
66
67 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyFTFactory)
68
69 static GObject *
70 do_constructor (GType type,
71     guint n_props,
72     GObjectConstructParam *props)
73 {
74   GObject *retval;
75
76   if (factory_singleton != NULL)
77     {
78       retval = g_object_ref (factory_singleton);
79     }
80   else
81     {
82       retval = G_OBJECT_CLASS (empathy_ft_factory_parent_class)->constructor
83         (type, n_props, props);
84
85       factory_singleton = EMPATHY_FT_FACTORY (retval);
86       g_object_add_weak_pointer (retval, (gpointer *) &factory_singleton);
87     }
88
89   return retval;
90 }
91
92 static void
93 empathy_ft_factory_dispose (GObject *object)
94 {
95   EmpathyFTFactory *self = (EmpathyFTFactory *) object;
96   EmpathyFTFactoryPriv *priv = GET_PRIV (self);
97
98   tp_clear_object (&priv->handler);
99
100   (G_OBJECT_CLASS (empathy_ft_factory_parent_class)->dispose) (object);
101 }
102
103 static void
104 empathy_ft_factory_class_init (EmpathyFTFactoryClass *klass)
105 {
106   GObjectClass *object_class = G_OBJECT_CLASS (klass);
107
108   g_type_class_add_private (klass, sizeof (EmpathyFTFactoryPriv));
109
110   object_class->constructor = do_constructor;
111   object_class->dispose = empathy_ft_factory_dispose;
112
113   /**
114    * EmpathyFTFactory::new-ft-handler
115    * @factory: the object which received the signal
116    * @handler: the handler made available by the factory
117    * @error: a #GError or %NULL
118    *
119    * The signal is emitted when a new #EmpathyFTHandler is available.
120    * Note that @handler is never %NULL even if @error is set, as you might want
121    * to display the error in an UI; in that case, the handler won't support
122    * any transfer.
123    */
124   signals[NEW_FT_HANDLER] =
125     g_signal_new ("new-ft-handler",
126       G_TYPE_FROM_CLASS (klass),
127       G_SIGNAL_RUN_LAST, 0,
128       NULL, NULL,
129       _empathy_marshal_VOID__OBJECT_POINTER,
130       G_TYPE_NONE, 2, EMPATHY_TYPE_FT_HANDLER, G_TYPE_POINTER);
131
132   /**
133    * EmpathyFTFactory::new-incoming-transfer
134    * @factory: the object which received the signal
135    * @handler: the incoming handler being constructed
136    * @error: a #GError or %NULL
137    *
138    * The signal is emitted when a new incoming #EmpathyFTHandler is being
139    * constructed, and needs a destination #GFile to be useful.
140    * Clients that connect to this signal will have to call
141    * empathy_ft_factory_set_destination_for_incoming_handler() when they
142    * have a #GFile.
143    * Note that @handler is never %NULL even if @error is set, as you might want
144    * to display the error in an UI; in that case, the handler won't support
145    * any transfer.
146    */
147   signals[NEW_INCOMING_TRANSFER] =
148     g_signal_new ("new-incoming-transfer",
149       G_TYPE_FROM_CLASS (klass),
150       G_SIGNAL_RUN_LAST, 0,
151       NULL, NULL,
152       _empathy_marshal_VOID__OBJECT_POINTER,
153       G_TYPE_NONE, 2, EMPATHY_TYPE_FT_HANDLER, G_TYPE_POINTER);
154 }
155
156 static void
157 ft_handler_incoming_ready_cb (EmpathyFTHandler *handler,
158     GError *error,
159     gpointer user_data)
160 {
161   EmpathyFTFactory *factory = user_data;
162
163   g_signal_emit (factory, signals[NEW_INCOMING_TRANSFER], 0, handler, error);
164 }
165
166 static void
167 handle_channels_cb (TpSimpleHandler *handler,
168     TpAccount *account,
169     TpConnection *connection,
170     GList *channels,
171     GList *requests_satisfied,
172     gint64 user_action_time,
173     TpHandleChannelsContext *context,
174     gpointer user_data)
175 {
176   EmpathyFTFactory *self = user_data;
177   GList *l;
178
179   for (l = channels; l != NULL; l = g_list_next (l))
180     {
181       TpChannel *channel = l->data;
182       EmpathyTpFile *tp_file;
183
184       if (tp_proxy_get_invalidated (channel) != NULL)
185         continue;
186
187       if (tp_channel_get_channel_type_id (channel) !=
188           TP_IFACE_QUARK_CHANNEL_TYPE_FILE_TRANSFER)
189         continue;
190
191       tp_file = empathy_tp_file_new (channel);
192
193       /* We handle only incoming FT */
194       empathy_ft_handler_new_incoming (tp_file, ft_handler_incoming_ready_cb,
195           self);
196
197       g_object_unref (tp_file);
198     }
199
200
201   tp_handle_channels_context_accept (context);
202 }
203
204 static void
205 empathy_ft_factory_init (EmpathyFTFactory *self)
206 {
207   EmpathyFTFactoryPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
208     EMPATHY_TYPE_FT_FACTORY, EmpathyFTFactoryPriv);
209   TpDBusDaemon *dbus;
210   GError *error = NULL;
211
212   self->priv = priv;
213
214   dbus = tp_dbus_daemon_dup (&error);
215   if (dbus == NULL)
216     {
217       g_warning ("Failed to get TpDBusDaemon: %s", error->message);
218       g_error_free (error);
219       return;
220     }
221
222   priv->handler = tp_simple_handler_new (dbus, FALSE, FALSE,
223       EMPATHY_FT_BUS_NAME_SUFFIX, FALSE, handle_channels_cb, self, NULL);
224
225   tp_base_client_take_handler_filter (priv->handler, tp_asv_new (
226         TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
227           TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER,
228         TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
229         /* Only handle *incoming* channels as outgoing FT channels has to be
230          * handled by the requester. */
231         TP_PROP_CHANNEL_REQUESTED, G_TYPE_BOOLEAN, FALSE,
232         NULL));
233
234   g_object_unref (dbus);
235 }
236
237 static void
238 ft_handler_outgoing_ready_cb (EmpathyFTHandler *handler,
239     GError *error,
240     gpointer user_data)
241 {
242   EmpathyFTFactory *factory = user_data;
243
244   g_signal_emit (factory, signals[NEW_FT_HANDLER], 0, handler, error);
245 }
246
247 /* public methods */
248
249 /**
250  * empathy_ft_factory_dup_singleton:
251  *
252  * Gives the caller a reference to the #EmpathyFTFactory singleton,
253  * (creating it if necessary).
254  *
255  * Return value: an #EmpathyFTFactory object
256  */
257 EmpathyFTFactory *
258 empathy_ft_factory_dup_singleton (void)
259 {
260   return g_object_new (EMPATHY_TYPE_FT_FACTORY, NULL);
261 }
262
263 /**
264  * empathy_ft_factory_new_transfer_outgoing:
265  * @factory: an #EmpathyFTFactory
266  * @contact: the #EmpathyContact destination of the transfer
267  * @source: the #GFile to be transferred to @contact
268  *
269  * Trigger the creation of an #EmpathyFTHandler object to send @source to
270  * the specified @contact.
271  */
272 void
273 empathy_ft_factory_new_transfer_outgoing (EmpathyFTFactory *factory,
274     EmpathyContact *contact,
275     GFile *source)
276 {
277   g_return_if_fail (EMPATHY_IS_FT_FACTORY (factory));
278   g_return_if_fail (EMPATHY_IS_CONTACT (contact));
279   g_return_if_fail (G_IS_FILE (source));
280
281   empathy_ft_handler_new_outgoing (contact, source,
282       ft_handler_outgoing_ready_cb, factory);
283 }
284
285 /**
286  * empathy_ft_factory_set_destination_for_incoming_handler:
287  * @factory: an #EmpathyFTFactory
288  * @handler: the #EmpathyFTHandler to set the destination of
289  * @destination: the #GFile destination of the transfer
290  *
291  * Sets @destination as destination file for the transfer. After the call of
292  * this method, the ::new-ft-handler will be emitted for the incoming handler.
293  */
294 void
295 empathy_ft_factory_set_destination_for_incoming_handler (
296     EmpathyFTFactory *factory,
297     EmpathyFTHandler *handler,
298     GFile *destination)
299 {
300   g_return_if_fail (EMPATHY_IS_FT_FACTORY (factory));
301   g_return_if_fail (EMPATHY_IS_FT_HANDLER (handler));
302   g_return_if_fail (G_IS_FILE (destination));
303
304   empathy_ft_handler_incoming_set_destination (handler, destination);
305
306   g_signal_emit (factory, signals[NEW_FT_HANDLER], 0, handler, NULL);
307 }
308
309 gboolean
310 empathy_ft_factory_register (EmpathyFTFactory *self,
311     GError **error)
312 {
313   EmpathyFTFactoryPriv *priv = GET_PRIV (self);
314
315   return tp_base_client_register (priv->handler, error);
316 }