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