]> git.0d.be Git - empathy.git/blob - src/empathy-call-factory.c
Move empathy_call_* util functions to libempathy-gtk
[empathy.git] / src / empathy-call-factory.c
1 /*
2  * empathy-call-factory.c - Source for EmpathyCallFactory
3  * Copyright (C) 2008 Collabora Ltd.
4  * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20
21
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #include <telepathy-glib/account-channel-request.h>
26 #include <telepathy-glib/simple-handler.h>
27 #include <telepathy-glib/interfaces.h>
28 #include <telepathy-glib/util.h>
29
30 #include <telepathy-yell/telepathy-yell.h>
31
32 #include <libempathy/empathy-channel-factory.h>
33 #include <libempathy/empathy-request-util.h>
34 #include <libempathy/empathy-utils.h>
35
36 #include <libempathy-gtk/empathy-call-utils.h>
37
38 #include "empathy-call-factory.h"
39 #include "empathy-call-handler.h"
40 #include "src-marshal.h"
41
42 #define DEBUG_FLAG EMPATHY_DEBUG_VOIP
43 #include <libempathy/empathy-debug.h>
44
45 G_DEFINE_TYPE(EmpathyCallFactory, empathy_call_factory, G_TYPE_OBJECT)
46
47 static void handle_channels_cb (TpSimpleHandler *handler,
48     TpAccount *account,
49     TpConnection *connection,
50     GList *channels,
51     GList *requests_satisfied,
52     gint64 user_action_time,
53     TpHandleChannelsContext *context,
54     gpointer user_data);
55
56 /* signal enum */
57 enum
58 {
59     NEW_CALL_HANDLER,
60     LAST_SIGNAL
61 };
62
63 static guint signals[LAST_SIGNAL] = {0};
64
65 /* private structure */
66 typedef struct {
67   TpBaseClient *handler;
68   gboolean dispose_has_run;
69 } EmpathyCallFactoryPriv;
70
71 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyCallFactory)
72
73 static GObject *call_factory = NULL;
74
75 static void
76 empathy_call_factory_init (EmpathyCallFactory *obj)
77 {
78   EmpathyCallFactoryPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj,
79     EMPATHY_TYPE_CALL_FACTORY, EmpathyCallFactoryPriv);
80   TpDBusDaemon *dbus;
81   EmpathyChannelFactory *factory;
82   GError *error = NULL;
83
84   obj->priv = priv;
85
86   dbus = tp_dbus_daemon_dup (&error);
87   if (dbus == NULL)
88     {
89       g_warning ("Failed to get TpDBusDaemon: %s", error->message);
90       g_error_free (error);
91       return;
92     }
93
94   priv->handler = tp_simple_handler_new (dbus, FALSE, FALSE,
95       EMPATHY_CALL_BUS_NAME_SUFFIX, FALSE, handle_channels_cb, obj, NULL);
96
97   factory = empathy_channel_factory_new ();
98   tp_base_client_set_channel_factory (priv->handler,
99       TP_CLIENT_CHANNEL_FACTORY (factory));
100   g_object_unref (factory);
101
102   tp_base_client_take_handler_filter (priv->handler, tp_asv_new (
103         TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
104           TPY_IFACE_CHANNEL_TYPE_CALL,
105         TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
106         NULL));
107
108   tp_base_client_take_handler_filter (priv->handler, tp_asv_new (
109         TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
110           TPY_IFACE_CHANNEL_TYPE_CALL,
111         TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
112         TPY_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, G_TYPE_BOOLEAN, TRUE,
113         NULL));
114
115   tp_base_client_take_handler_filter (priv->handler, tp_asv_new (
116         TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
117           TPY_IFACE_CHANNEL_TYPE_CALL,
118         TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
119         TPY_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, G_TYPE_BOOLEAN, TRUE,
120         NULL));
121
122   tp_base_client_add_handler_capabilities_varargs (priv->handler,
123     "org.freedesktop.Telepathy.Channel.Interface.MediaSignalling/ice-udp",
124     "org.freedesktop.Telepathy.Channel.Interface.MediaSignalling/gtalk-p2p",
125     "org.freedesktop.Telepathy.Channel.Interface.MediaSignalling/video/h264",
126     NULL);
127
128   g_object_unref (dbus);
129 }
130
131 static GObject *
132 empathy_call_factory_constructor (GType type, guint n_construct_params,
133   GObjectConstructParam *construct_params)
134 {
135   g_return_val_if_fail (call_factory == NULL, NULL);
136
137   call_factory = G_OBJECT_CLASS (empathy_call_factory_parent_class)->constructor
138           (type, n_construct_params, construct_params);
139   g_object_add_weak_pointer (call_factory, (gpointer)&call_factory);
140
141   return call_factory;
142 }
143
144 static void
145 empathy_call_factory_finalize (GObject *object)
146 {
147   /* free any data held directly by the object here */
148
149   if (G_OBJECT_CLASS (empathy_call_factory_parent_class)->finalize)
150     G_OBJECT_CLASS (empathy_call_factory_parent_class)->finalize (object);
151 }
152
153 static void
154 empathy_call_factory_dispose (GObject *object)
155 {
156   EmpathyCallFactoryPriv *priv = GET_PRIV (object);
157
158   if (priv->dispose_has_run)
159     return;
160
161   priv->dispose_has_run = TRUE;
162
163   tp_clear_object (&priv->handler);
164
165   if (G_OBJECT_CLASS (empathy_call_factory_parent_class)->dispose)
166     G_OBJECT_CLASS (empathy_call_factory_parent_class)->dispose (object);
167 }
168
169 static void
170 empathy_call_factory_class_init (
171   EmpathyCallFactoryClass *empathy_call_factory_class)
172 {
173   GObjectClass *object_class = G_OBJECT_CLASS (empathy_call_factory_class);
174
175   g_type_class_add_private (empathy_call_factory_class,
176     sizeof (EmpathyCallFactoryPriv));
177
178   object_class->constructor = empathy_call_factory_constructor;
179   object_class->dispose = empathy_call_factory_dispose;
180   object_class->finalize = empathy_call_factory_finalize;
181
182   signals[NEW_CALL_HANDLER] =
183     g_signal_new ("new-call-handler",
184       G_TYPE_FROM_CLASS (empathy_call_factory_class),
185       G_SIGNAL_RUN_LAST, 0,
186       NULL, NULL,
187       _src_marshal_VOID__OBJECT_BOOLEAN,
188       G_TYPE_NONE,
189       2, EMPATHY_TYPE_CALL_HANDLER, G_TYPE_BOOLEAN);
190 }
191
192 EmpathyCallFactory *
193 empathy_call_factory_initialise (void)
194 {
195   g_return_val_if_fail (call_factory == NULL, NULL);
196
197   return EMPATHY_CALL_FACTORY (g_object_new (EMPATHY_TYPE_CALL_FACTORY, NULL));
198 }
199
200 EmpathyCallFactory *
201 empathy_call_factory_get (void)
202 {
203   g_return_val_if_fail (call_factory != NULL, NULL);
204
205   return EMPATHY_CALL_FACTORY (call_factory);
206 }
207
208 static void
209 create_call_channel_cb (GObject *source,
210     GAsyncResult *result,
211     gpointer user_data)
212 {
213   GError *error = NULL;
214
215   if (!tp_account_channel_request_create_channel_finish (
216         TP_ACCOUNT_CHANNEL_REQUEST (source), result, &error))
217     {
218       DEBUG ("Failed to create call channel: %s", error->message);
219       g_error_free (error);
220     }
221 }
222
223 /**
224  * empathy_call_factory_new_call_with_streams:
225  * @factory: an #EmpathyCallFactory
226  * @contact: an #EmpathyContact
227  * @initial_audio: if %TRUE the call will be started with audio
228  * @initial_video: if %TRUE the call will be started with video
229  *
230  * Initiate a new Call with @contact.
231  */
232 void
233 empathy_call_factory_new_call_with_streams (EmpathyContact *contact,
234     gboolean initial_audio,
235     gboolean initial_video,
236     gint64 timestamp,
237     gpointer user_data)
238 {
239   GHashTable *call_request;
240   TpAccount *account;
241   TpAccountChannelRequest *call_req;
242
243   call_request = empathy_call_create_call_request (contact,
244       initial_audio, initial_video);
245
246   account = empathy_contact_get_account (contact);
247
248   call_req = tp_account_channel_request_new (account, call_request, timestamp);
249
250   tp_account_channel_request_create_channel_async (call_req, NULL, NULL,
251       create_call_channel_cb, NULL);
252
253   g_hash_table_unref (call_request);
254   g_object_unref (call_req);
255 }
256
257 static void
258 create_call_handler (EmpathyCallFactory *factory,
259   TpyCallChannel *call)
260 {
261   EmpathyCallHandler *handler;
262
263   g_return_if_fail (factory != NULL);
264
265   handler = empathy_call_handler_new_for_channel (call);
266
267   g_signal_emit (factory, signals[NEW_CALL_HANDLER], 0,
268     handler, FALSE);
269
270   g_object_unref (handler);
271 }
272
273 static void
274 handle_channels_cb (TpSimpleHandler *handler,
275     TpAccount *account,
276     TpConnection *connection,
277     GList *channels,
278     GList *requests_satisfied,
279     gint64 user_action_time,
280     TpHandleChannelsContext *context,
281     gpointer user_data)
282 {
283   EmpathyCallFactory *self = user_data;
284   GList *l;
285
286   for (l = channels; l != NULL; l = g_list_next (l))
287     {
288       TpChannel *channel = l->data;
289       TpyCallChannel *call;
290
291       if (tp_proxy_get_invalidated (channel) != NULL)
292         continue;
293
294       if (tp_channel_get_channel_type_id (channel) !=
295           TPY_IFACE_QUARK_CHANNEL_TYPE_CALL)
296         continue;
297
298       if (!TPY_IS_CALL_CHANNEL (channel))
299         continue;
300
301       call = TPY_CALL_CHANNEL (channel);
302       create_call_handler (self, call);
303       g_object_unref (call);
304     }
305
306   tp_handle_channels_context_accept (context);
307 }
308
309 gboolean
310 empathy_call_factory_register (EmpathyCallFactory *self,
311     GError **error)
312 {
313   EmpathyCallFactoryPriv *priv = GET_PRIV (self);
314
315   return tp_base_client_register (priv->handler, error);
316 }