~ubuntu-branches/ubuntu/natty/empathy/natty

« back to all changes in this revision

Viewing changes to src/empathy-call-factory.c

  • Committer: Bazaar Package Importer
  • Author(s): Ken VanDine
  • Date: 2011-02-24 11:54:47 UTC
  • mfrom: (1.1.66 upstream)
  • Revision ID: james.westby@ubuntu.com-20110224115447-meoue6yzk3u6s2br
Tags: 2.33.2-0ubuntu1
* New upstream release
* -debian/patches/reword_subscription_dailog_to_be_less_technical.patch
  - merged upstream
* debian/control
  - Bumped build depends for tp-logger, tp-glib, folks and libunity-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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-dispatcher.h>
 
33
#include <libempathy/empathy-channel-factory.h>
 
34
#include <libempathy/empathy-tp-contact-factory.h>
 
35
#include <libempathy/empathy-utils.h>
 
36
 
 
37
#include <libempathy-gtk/empathy-call-utils.h>
 
38
 
 
39
#include "empathy-call-factory.h"
 
40
#include "empathy-call-handler.h"
 
41
#include "src-marshal.h"
 
42
 
 
43
#define DEBUG_FLAG EMPATHY_DEBUG_VOIP
 
44
#include <libempathy/empathy-debug.h>
 
45
 
 
46
G_DEFINE_TYPE(EmpathyCallFactory, empathy_call_factory, G_TYPE_OBJECT)
 
47
 
 
48
static void handle_channels_cb (TpSimpleHandler *handler,
 
49
    TpAccount *account,
 
50
    TpConnection *connection,
 
51
    GList *channels,
 
52
    GList *requests_satisfied,
 
53
    gint64 user_action_time,
 
54
    TpHandleChannelsContext *context,
 
55
    gpointer user_data);
 
56
 
 
57
/* signal enum */
 
58
enum
 
59
{
 
60
    NEW_CALL_HANDLER,
 
61
    LAST_SIGNAL
 
62
};
 
63
 
 
64
static guint signals[LAST_SIGNAL] = {0};
 
65
 
 
66
/* private structure */
 
67
typedef struct {
 
68
  TpBaseClient *handler;
 
69
  gboolean dispose_has_run;
 
70
} EmpathyCallFactoryPriv;
 
71
 
 
72
#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyCallFactory)
 
73
 
 
74
static GObject *call_factory = NULL;
 
75
 
 
76
static void
 
77
empathy_call_factory_init (EmpathyCallFactory *obj)
 
78
{
 
79
  EmpathyCallFactoryPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj,
 
80
    EMPATHY_TYPE_CALL_FACTORY, EmpathyCallFactoryPriv);
 
81
  TpDBusDaemon *dbus;
 
82
  EmpathyChannelFactory *factory;
 
83
  GError *error = NULL;
 
84
 
 
85
  obj->priv = priv;
 
86
 
 
87
  dbus = tp_dbus_daemon_dup (&error);
 
88
  if (dbus == NULL)
 
89
    {
 
90
      g_warning ("Failed to get TpDBusDaemon: %s", error->message);
 
91
      g_error_free (error);
 
92
      return;
 
93
    }
 
94
 
 
95
  priv->handler = tp_simple_handler_new (dbus, FALSE, FALSE,
 
96
      "Empathy.Call", FALSE, handle_channels_cb, obj, NULL);
 
97
 
 
98
  factory = empathy_channel_factory_new ();
 
99
  tp_base_client_set_channel_factory (priv->handler,
 
100
      TP_CLIENT_CHANNEL_FACTORY (factory));
 
101
  g_object_unref (factory);
 
102
 
 
103
  tp_base_client_take_handler_filter (priv->handler, tp_asv_new (
 
104
        TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
 
105
          TPY_IFACE_CHANNEL_TYPE_CALL,
 
106
        TP_PROP_CHANNEL_TARGET_HANDLE_TYPE,
 
107
          G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
 
108
        NULL));
 
109
 
 
110
  tp_base_client_take_handler_filter (priv->handler, tp_asv_new (
 
111
        TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
 
112
          TPY_IFACE_CHANNEL_TYPE_CALL,
 
113
        TP_PROP_CHANNEL_TARGET_HANDLE_TYPE,
 
114
          G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
 
115
        TPY_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, G_TYPE_BOOLEAN, TRUE,
 
116
        NULL));
 
117
 
 
118
  tp_base_client_take_handler_filter (priv->handler, tp_asv_new (
 
119
        TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
 
120
          TPY_IFACE_CHANNEL_TYPE_CALL,
 
121
        TP_PROP_CHANNEL_TARGET_HANDLE_TYPE,
 
122
          G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
 
123
        TPY_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, G_TYPE_BOOLEAN, TRUE,
 
124
        NULL));
 
125
 
 
126
  tp_base_client_add_handler_capabilities_varargs (priv->handler,
 
127
    "org.freedesktop.Telepathy.Channel.Interface.MediaSignalling/ice-udp",
 
128
    "org.freedesktop.Telepathy.Channel.Interface.MediaSignalling/gtalk-p2p",
 
129
    "org.freedesktop.Telepathy.Channel.Interface.MediaSignalling/video/h264",
 
130
    NULL);
 
131
 
 
132
  g_object_unref (dbus);
 
133
}
 
134
 
 
135
static GObject *
 
136
empathy_call_factory_constructor (GType type, guint n_construct_params,
 
137
  GObjectConstructParam *construct_params)
 
138
{
 
139
  g_return_val_if_fail (call_factory == NULL, NULL);
 
140
 
 
141
  call_factory = G_OBJECT_CLASS (empathy_call_factory_parent_class)->constructor
 
142
          (type, n_construct_params, construct_params);
 
143
  g_object_add_weak_pointer (call_factory, (gpointer)&call_factory);
 
144
 
 
145
  return call_factory;
 
146
}
 
147
 
 
148
static void
 
149
empathy_call_factory_finalize (GObject *object)
 
150
{
 
151
  /* free any data held directly by the object here */
 
152
 
 
153
  if (G_OBJECT_CLASS (empathy_call_factory_parent_class)->finalize)
 
154
    G_OBJECT_CLASS (empathy_call_factory_parent_class)->finalize (object);
 
155
}
 
156
 
 
157
static void
 
158
empathy_call_factory_dispose (GObject *object)
 
159
{
 
160
  EmpathyCallFactoryPriv *priv = GET_PRIV (object);
 
161
 
 
162
  if (priv->dispose_has_run)
 
163
    return;
 
164
 
 
165
  priv->dispose_has_run = TRUE;
 
166
 
 
167
  tp_clear_object (&priv->handler);
 
168
 
 
169
  if (G_OBJECT_CLASS (empathy_call_factory_parent_class)->dispose)
 
170
    G_OBJECT_CLASS (empathy_call_factory_parent_class)->dispose (object);
 
171
}
 
172
 
 
173
static void
 
174
empathy_call_factory_class_init (
 
175
  EmpathyCallFactoryClass *empathy_call_factory_class)
 
176
{
 
177
  GObjectClass *object_class = G_OBJECT_CLASS (empathy_call_factory_class);
 
178
 
 
179
  g_type_class_add_private (empathy_call_factory_class,
 
180
    sizeof (EmpathyCallFactoryPriv));
 
181
 
 
182
  object_class->constructor = empathy_call_factory_constructor;
 
183
  object_class->dispose = empathy_call_factory_dispose;
 
184
  object_class->finalize = empathy_call_factory_finalize;
 
185
 
 
186
  signals[NEW_CALL_HANDLER] =
 
187
    g_signal_new ("new-call-handler",
 
188
      G_TYPE_FROM_CLASS (empathy_call_factory_class),
 
189
      G_SIGNAL_RUN_LAST, 0,
 
190
      NULL, NULL,
 
191
      _src_marshal_VOID__OBJECT_BOOLEAN,
 
192
      G_TYPE_NONE,
 
193
      2, EMPATHY_TYPE_CALL_HANDLER, G_TYPE_BOOLEAN);
 
194
}
 
195
 
 
196
EmpathyCallFactory *
 
197
empathy_call_factory_initialise (void)
 
198
{
 
199
  g_return_val_if_fail (call_factory == NULL, NULL);
 
200
 
 
201
  return EMPATHY_CALL_FACTORY (g_object_new (EMPATHY_TYPE_CALL_FACTORY, NULL));
 
202
}
 
203
 
 
204
EmpathyCallFactory *
 
205
empathy_call_factory_get (void)
 
206
{
 
207
  g_return_val_if_fail (call_factory != NULL, NULL);
 
208
 
 
209
  return EMPATHY_CALL_FACTORY (call_factory);
 
210
}
 
211
 
 
212
static void
 
213
create_call_channel_cb (GObject *source,
 
214
    GAsyncResult *result,
 
215
    gpointer user_data)
 
216
{
 
217
  GError *error = NULL;
 
218
 
 
219
  if (!tp_account_channel_request_create_channel_finish (
 
220
        TP_ACCOUNT_CHANNEL_REQUEST (source), result, &error))
 
221
    {
 
222
      DEBUG ("Failed to create call channel: %s", error->message);
 
223
      g_error_free (error);
 
224
    }
 
225
}
 
226
 
 
227
/**
 
228
 * empathy_call_factory_new_call_with_streams:
 
229
 * @factory: an #EmpathyCallFactory
 
230
 * @contact: an #EmpathyContact
 
231
 * @initial_audio: if %TRUE the call will be started with audio
 
232
 * @initial_video: if %TRUE the call will be started with video
 
233
 *
 
234
 * Initiate a new Call with @contact.
 
235
 */
 
236
void
 
237
empathy_call_factory_new_call_with_streams (EmpathyContact *contact,
 
238
    gboolean initial_audio,
 
239
    gboolean initial_video,
 
240
    gint64 timestamp,
 
241
    gpointer user_data)
 
242
{
 
243
  GHashTable *call_request;
 
244
  TpAccount *account;
 
245
  TpAccountChannelRequest *call_req;
 
246
 
 
247
  call_request = empathy_call_create_call_request (
 
248
      empathy_contact_get_id (contact),
 
249
      initial_audio, initial_video);
 
250
 
 
251
  account = empathy_contact_get_account (contact);
 
252
 
 
253
  call_req = tp_account_channel_request_new (account, call_request, timestamp);
 
254
 
 
255
  tp_account_channel_request_create_channel_async (call_req, NULL, NULL,
 
256
      create_call_channel_cb, NULL);
 
257
 
 
258
  g_hash_table_unref (call_request);
 
259
  g_object_unref (call_req);
 
260
}
 
261
 
 
262
static void
 
263
call_channel_got_contact (TpConnection *connection,
 
264
  EmpathyContact *contact,
 
265
  const GError *error,
 
266
  gpointer user_data,
 
267
  GObject *weak_object)
 
268
{
 
269
  EmpathyCallFactory *factory = EMPATHY_CALL_FACTORY (weak_object);
 
270
  EmpathyCallHandler *handler;
 
271
  TpyCallChannel *call = TPY_CALL_CHANNEL (user_data);
 
272
 
 
273
  if (contact == NULL)
 
274
    {
 
275
      /* FIXME use hangup with an appropriate error */
 
276
      tp_channel_close_async (TP_CHANNEL (call), NULL, NULL);
 
277
      goto out;
 
278
    }
 
279
 
 
280
  handler = empathy_call_handler_new_for_channel (call, contact);
 
281
 
 
282
  g_signal_emit (factory, signals[NEW_CALL_HANDLER], 0,
 
283
    handler, FALSE);
 
284
 
 
285
  g_object_unref (handler);
 
286
 
 
287
out:
 
288
  g_object_unref (call);
 
289
}
 
290
 
 
291
 
 
292
static void
 
293
handle_channels_cb (TpSimpleHandler *handler,
 
294
    TpAccount *account,
 
295
    TpConnection *connection,
 
296
    GList *channels,
 
297
    GList *requests_satisfied,
 
298
    gint64 user_action_time,
 
299
    TpHandleChannelsContext *context,
 
300
    gpointer user_data)
 
301
{
 
302
  EmpathyCallFactory *self = user_data;
 
303
  GList *l;
 
304
 
 
305
  for (l = channels; l != NULL; l = g_list_next (l))
 
306
    {
 
307
      TpChannel *channel = l->data;
 
308
      TpyCallChannel *call;
 
309
      const gchar *id;
 
310
 
 
311
      if (tp_proxy_get_invalidated (channel) != NULL)
 
312
        continue;
 
313
 
 
314
      if (tp_channel_get_channel_type_id (channel) !=
 
315
          TPY_IFACE_QUARK_CHANNEL_TYPE_CALL)
 
316
        continue;
 
317
 
 
318
      if (!TPY_IS_CALL_CHANNEL (channel))
 
319
        continue;
 
320
 
 
321
      call = TPY_CALL_CHANNEL (channel);
 
322
 
 
323
      id = tp_channel_get_identifier (channel);
 
324
      empathy_tp_contact_factory_get_from_id (connection,
 
325
        id,
 
326
        call_channel_got_contact,
 
327
        g_object_ref (channel),
 
328
        g_object_unref,
 
329
        (GObject *) self);
 
330
    }
 
331
 
 
332
  tp_handle_channels_context_accept (context);
 
333
}
 
334
 
 
335
gboolean
 
336
empathy_call_factory_register (EmpathyCallFactory *self,
 
337
    GError **error)
 
338
{
 
339
  EmpathyCallFactoryPriv *priv = GET_PRIV (self);
 
340
 
 
341
  return tp_base_client_register (priv->handler, error);
 
342
}