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