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

« back to all changes in this revision

Viewing changes to .pc/reword_subscription_dailog_to_be_less_technical.patch/src/empathy-event-manager.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Ancell, Omer Akram
  • Date: 2011-01-06 14:32:31 UTC
  • Revision ID: james.westby@ubuntu.com-20110106143231-ol0gyfqi7h1ch8kv
Tags: 2.32.2-0ubuntu3
* debian/patches/00git_folks_api.patch:
  - Update to latest folks API

[ Omer Akram ]
* debian/patches/enable_pidgin_imported_contacts.patch:
  - Enable pidgin imported accounts by default. (LP: #622215)
* debian/patches/reword_subscription_dailog_to_be_less_technical.patch:
  - Reword subscription request dialog to be less technical. (LP: #670197)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2007-2008 Collabora Ltd.
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Lesser General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 2.1 of the License, or (at your option) any later version.
 
8
 *
 
9
 * This library is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * Lesser General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Lesser General Public
 
15
 * License along with this library; if not, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
17
 *
 
18
 * Authors: Xavier Claessens <xclaesse@gmail.com>
 
19
 *          Sjoerd Simons <sjoerd.simons@collabora.co.uk>
 
20
 */
 
21
 
 
22
#include <config.h>
 
23
 
 
24
#include <string.h>
 
25
#include <glib/gi18n.h>
 
26
 
 
27
#include <telepathy-glib/account-manager.h>
 
28
#include <telepathy-glib/util.h>
 
29
#include <telepathy-glib/interfaces.h>
 
30
#include <telepathy-glib/simple-approver.h>
 
31
 
 
32
#include <libempathy/empathy-idle.h>
 
33
#include <libempathy/empathy-tp-contact-factory.h>
 
34
#include <libempathy/empathy-contact-manager.h>
 
35
#include <libempathy/empathy-tp-chat.h>
 
36
#include <libempathy/empathy-tp-call.h>
 
37
#include <libempathy/empathy-tp-file.h>
 
38
#include <libempathy/empathy-utils.h>
 
39
#include <libempathy/empathy-call-factory.h>
 
40
#include <libempathy/empathy-gsettings.h>
 
41
 
 
42
#include <extensions/extensions.h>
 
43
 
 
44
#include <libempathy-gtk/empathy-images.h>
 
45
#include <libempathy-gtk/empathy-contact-dialogs.h>
 
46
#include <libempathy-gtk/empathy-sound.h>
 
47
 
 
48
#include "empathy-event-manager.h"
 
49
#include "empathy-main-window.h"
 
50
 
 
51
#define DEBUG_FLAG EMPATHY_DEBUG_DISPATCHER
 
52
#include <libempathy/empathy-debug.h>
 
53
 
 
54
#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyEventManager)
 
55
 
 
56
#define NOTIFICATION_TIMEOUT 2 /* seconds */
 
57
 
 
58
/* The time interval in milliseconds between 2 incoming rings */
 
59
#define MS_BETWEEN_RING 500
 
60
 
 
61
typedef struct {
 
62
  EmpathyEventManager *manager;
 
63
  TpChannelDispatchOperation *operation;
 
64
  gulong invalidated_handler;
 
65
  /* Remove contact if applicable */
 
66
  EmpathyContact *contact;
 
67
  /* option signal handler and it's instance */
 
68
  gulong handler;
 
69
  GObject *handler_instance;
 
70
  /* optional accept widget */
 
71
  GtkWidget *dialog;
 
72
  /* Channel of the CDO that will be used during the approval */
 
73
  TpChannel *main_channel;
 
74
  gboolean auto_approved;
 
75
} EventManagerApproval;
 
76
 
 
77
typedef struct {
 
78
  TpBaseClient *approver;
 
79
  EmpathyContactManager *contact_manager;
 
80
  GSList *events;
 
81
  /* Ongoing approvals */
 
82
  GSList *approvals;
 
83
 
 
84
  gint ringing;
 
85
} EmpathyEventManagerPriv;
 
86
 
 
87
typedef struct _EventPriv EventPriv;
 
88
typedef void (*EventFunc) (EventPriv *event);
 
89
 
 
90
struct _EventPriv {
 
91
  EmpathyEvent public;
 
92
  EmpathyEventManager *manager;
 
93
  EventManagerApproval *approval;
 
94
  EventFunc func;
 
95
  gboolean inhibit;
 
96
  gpointer user_data;
 
97
  guint autoremove_timeout_id;
 
98
};
 
99
 
 
100
enum {
 
101
  EVENT_ADDED,
 
102
  EVENT_REMOVED,
 
103
  EVENT_UPDATED,
 
104
  LAST_SIGNAL
 
105
};
 
106
 
 
107
static guint signals[LAST_SIGNAL];
 
108
 
 
109
G_DEFINE_TYPE (EmpathyEventManager, empathy_event_manager, G_TYPE_OBJECT);
 
110
 
 
111
static EmpathyEventManager * manager_singleton = NULL;
 
112
 
 
113
static EventManagerApproval *
 
114
event_manager_approval_new (EmpathyEventManager *manager,
 
115
  TpChannelDispatchOperation *operation,
 
116
  TpChannel *main_channel)
 
117
{
 
118
  EventManagerApproval *result = g_slice_new0 (EventManagerApproval);
 
119
  result->operation = g_object_ref (operation);
 
120
  result->manager = manager;
 
121
  result->main_channel = g_object_ref (main_channel);
 
122
 
 
123
  return result;
 
124
}
 
125
 
 
126
static void
 
127
event_manager_approval_free (EventManagerApproval *approval)
 
128
{
 
129
  g_signal_handler_disconnect (approval->operation,
 
130
    approval->invalidated_handler);
 
131
  g_object_unref (approval->operation);
 
132
 
 
133
  g_object_unref (approval->main_channel);
 
134
 
 
135
  if (approval->handler != 0)
 
136
    g_signal_handler_disconnect (approval->handler_instance,
 
137
      approval->handler);
 
138
 
 
139
  if (approval->handler_instance != NULL)
 
140
    g_object_unref (approval->handler_instance);
 
141
 
 
142
  if (approval->contact != NULL)
 
143
    g_object_unref (approval->contact);
 
144
 
 
145
  if (approval->dialog != NULL)
 
146
    {
 
147
      gtk_widget_destroy (approval->dialog);
 
148
    }
 
149
 
 
150
  g_slice_free (EventManagerApproval, approval);
 
151
}
 
152
 
 
153
static void event_remove (EventPriv *event);
 
154
 
 
155
static void
 
156
event_free (EventPriv *event)
 
157
{
 
158
  g_free (event->public.icon_name);
 
159
  g_free (event->public.header);
 
160
  g_free (event->public.message);
 
161
 
 
162
  if (event->autoremove_timeout_id != 0)
 
163
    g_source_remove (event->autoremove_timeout_id);
 
164
 
 
165
  if (event->public.contact)
 
166
    {
 
167
      g_object_unref (event->public.contact);
 
168
    }
 
169
 
 
170
  g_slice_free (EventPriv, event);
 
171
}
 
172
 
 
173
static void
 
174
event_remove (EventPriv *event)
 
175
{
 
176
  EmpathyEventManagerPriv *priv = GET_PRIV (event->manager);
 
177
 
 
178
  DEBUG ("Removing event %p", event);
 
179
 
 
180
  priv->events = g_slist_remove (priv->events, event);
 
181
  g_signal_emit (event->manager, signals[EVENT_REMOVED], 0, event);
 
182
  event_free (event);
 
183
}
 
184
 
 
185
static gboolean
 
186
autoremove_event_timeout_cb (EventPriv *event)
 
187
{
 
188
  event->autoremove_timeout_id = 0;
 
189
  event_remove (event);
 
190
  return FALSE;
 
191
}
 
192
 
 
193
static gboolean
 
194
display_notify_area (void)
 
195
 
 
196
{
 
197
  GSettings *gsettings;
 
198
  gboolean result;
 
199
 
 
200
  gsettings = g_settings_new (EMPATHY_PREFS_UI_SCHEMA);
 
201
 
 
202
  result = g_settings_get_boolean (gsettings,
 
203
      EMPATHY_PREFS_UI_EVENTS_NOTIFY_AREA);
 
204
  g_object_unref (gsettings);
 
205
 
 
206
  return result;
 
207
}
 
208
 
 
209
static void
 
210
event_manager_add (EmpathyEventManager *manager,
 
211
    EmpathyContact *contact,
 
212
    EmpathyEventType type,
 
213
    const gchar *icon_name,
 
214
    const gchar *header,
 
215
    const gchar *message,
 
216
    EventManagerApproval *approval,
 
217
    EventFunc func,
 
218
    gpointer user_data)
 
219
{
 
220
  EmpathyEventManagerPriv *priv = GET_PRIV (manager);
 
221
  EventPriv               *event;
 
222
 
 
223
  event = g_slice_new0 (EventPriv);
 
224
  event->public.contact = contact ? g_object_ref (contact) : NULL;
 
225
  event->public.type = type;
 
226
  event->public.icon_name = g_strdup (icon_name);
 
227
  event->public.header = g_strdup (header);
 
228
  event->public.message = g_strdup (message);
 
229
  event->public.must_ack = (func != NULL);
 
230
  event->inhibit = FALSE;
 
231
  event->func = func;
 
232
  event->user_data = user_data;
 
233
  event->manager = manager;
 
234
  event->approval = approval;
 
235
 
 
236
  DEBUG ("Adding event %p", event);
 
237
  priv->events = g_slist_prepend (priv->events, event);
 
238
 
 
239
  if (!display_notify_area ())
 
240
    {
 
241
      /* Don't fire the 'event-added' signal as we activate the event now */
 
242
      if (approval != NULL)
 
243
        approval->auto_approved = TRUE;
 
244
 
 
245
      empathy_event_activate (&event->public);
 
246
      return;
 
247
    }
 
248
 
 
249
  g_signal_emit (event->manager, signals[EVENT_ADDED], 0, event);
 
250
 
 
251
  if (!event->public.must_ack)
 
252
    {
 
253
      event->autoremove_timeout_id = g_timeout_add_seconds (
 
254
          NOTIFICATION_TIMEOUT, (GSourceFunc) autoremove_event_timeout_cb,
 
255
          event);
 
256
    }
 
257
}
 
258
 
 
259
static void
 
260
handle_with_cb (GObject *source,
 
261
    GAsyncResult *result,
 
262
    gpointer user_data)
 
263
{
 
264
  TpChannelDispatchOperation *cdo = TP_CHANNEL_DISPATCH_OPERATION (source);
 
265
  GError *error = NULL;
 
266
 
 
267
  if (!tp_channel_dispatch_operation_handle_with_finish (cdo, result, &error))
 
268
    {
 
269
      DEBUG ("HandleWith failed: %s\n", error->message);
 
270
      g_error_free (error);
 
271
    }
 
272
}
 
273
 
 
274
static void
 
275
handle_with_time_cb (GObject *source,
 
276
    GAsyncResult *result,
 
277
    gpointer user_data)
 
278
{
 
279
  TpChannelDispatchOperation *cdo = TP_CHANNEL_DISPATCH_OPERATION (source);
 
280
  GError *error = NULL;
 
281
 
 
282
  if (!tp_channel_dispatch_operation_handle_with_time_finish (cdo, result,
 
283
        &error))
 
284
    {
 
285
      if (g_error_matches (error, TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED))
 
286
        {
 
287
          EventManagerApproval *approval = user_data;
 
288
 
 
289
          DEBUG ("HandleWithTime() is not implemented, falling back to "
 
290
              "HandleWith(). Please upgrade to telepathy-mission-control "
 
291
              "5.5.0 or later");
 
292
 
 
293
          tp_channel_dispatch_operation_handle_with_async (approval->operation,
 
294
              NULL, handle_with_cb, approval);
 
295
        }
 
296
      else
 
297
        {
 
298
          DEBUG ("HandleWithTime failed: %s\n", error->message);
 
299
        }
 
300
      g_error_free (error);
 
301
    }
 
302
}
 
303
 
 
304
static void
 
305
event_manager_approval_approve (EventManagerApproval *approval)
 
306
{
 
307
  gint64 timestamp;
 
308
 
 
309
  if (approval->auto_approved)
 
310
    {
 
311
      timestamp = TP_USER_ACTION_TIME_NOT_USER_ACTION;
 
312
    }
 
313
  else
 
314
    {
 
315
      timestamp = tp_user_action_time_from_x11 (gtk_get_current_event_time ());
 
316
    }
 
317
 
 
318
  g_assert (approval->operation != NULL);
 
319
 
 
320
  tp_channel_dispatch_operation_handle_with_time_async (approval->operation,
 
321
      NULL, timestamp, handle_with_time_cb, approval);
 
322
}
 
323
 
 
324
static void
 
325
event_channel_process_func (EventPriv *event)
 
326
{
 
327
  event_manager_approval_approve (event->approval);
 
328
}
 
329
 
 
330
static void
 
331
event_text_channel_process_func (EventPriv *event)
 
332
{
 
333
  EmpathyTpChat *tp_chat;
 
334
  gint64 timestamp;
 
335
 
 
336
  timestamp = tp_user_action_time_from_x11 (gtk_get_current_event_time ());
 
337
 
 
338
  if (event->approval->handler != 0)
 
339
    {
 
340
      tp_chat = EMPATHY_TP_CHAT (event->approval->handler_instance);
 
341
 
 
342
      g_signal_handler_disconnect (tp_chat, event->approval->handler);
 
343
      event->approval->handler = 0;
 
344
    }
 
345
 
 
346
  event_manager_approval_approve (event->approval);
 
347
}
 
348
 
 
349
static EventPriv *
 
350
event_lookup_by_approval (EmpathyEventManager *manager,
 
351
  EventManagerApproval *approval)
 
352
{
 
353
  EmpathyEventManagerPriv *priv = GET_PRIV (manager);
 
354
  GSList *l;
 
355
  EventPriv *retval = NULL;
 
356
 
 
357
  for (l = priv->events; l; l = l->next)
 
358
    {
 
359
      EventPriv *event = l->data;
 
360
 
 
361
      if (event->approval == approval)
 
362
        {
 
363
          retval = event;
 
364
          break;
 
365
        }
 
366
    }
 
367
 
 
368
  return retval;
 
369
}
 
370
 
 
371
static void
 
372
event_update (EmpathyEventManager *manager, EventPriv *event,
 
373
  const char *icon_name, const char *header, const char *msg)
 
374
{
 
375
  g_free (event->public.icon_name);
 
376
  g_free (event->public.header);
 
377
  g_free (event->public.message);
 
378
 
 
379
  event->public.icon_name = g_strdup (icon_name);
 
380
  event->public.header = g_strdup (header);
 
381
  event->public.message = g_strdup (msg);
 
382
 
 
383
  g_signal_emit (manager, signals[EVENT_UPDATED], 0, event);
 
384
}
 
385
 
 
386
static void
 
387
reject_channel_claim_cb (GObject *source,
 
388
    GAsyncResult *result,
 
389
    gpointer user_data)
 
390
{
 
391
  TpChannelDispatchOperation *cdo = TP_CHANNEL_DISPATCH_OPERATION (source);
 
392
  GError *error = NULL;
 
393
 
 
394
  if (!tp_channel_dispatch_operation_claim_finish (cdo, result, &error))
 
395
    {
 
396
      DEBUG ("Failed to claim channel: %s", error->message);
 
397
 
 
398
      g_error_free (error);
 
399
      goto out;
 
400
    }
 
401
 
 
402
  if (EMPATHY_IS_TP_CALL (user_data))
 
403
    {
 
404
      empathy_tp_call_close (user_data);
 
405
    }
 
406
  else if (EMPATHY_IS_TP_CHAT (user_data))
 
407
    {
 
408
      empathy_tp_chat_leave (user_data);
 
409
    }
 
410
  else if (EMPATHY_IS_TP_FILE (user_data))
 
411
    {
 
412
      empathy_tp_file_close (user_data);
 
413
    }
 
414
 
 
415
out:
 
416
  g_object_unref (user_data);
 
417
}
 
418
 
 
419
static void
 
420
reject_approval (EventManagerApproval *approval)
 
421
{
 
422
  /* We have to claim the channel before closing it */
 
423
  tp_channel_dispatch_operation_claim_async (approval->operation,
 
424
      reject_channel_claim_cb, g_object_ref (approval->handler_instance));
 
425
}
 
426
 
 
427
static void
 
428
event_manager_call_window_confirmation_dialog_response_cb (GtkDialog *dialog,
 
429
  gint response, gpointer user_data)
 
430
{
 
431
  EventManagerApproval *approval = user_data;
 
432
 
 
433
  gtk_widget_destroy (approval->dialog);
 
434
  approval->dialog = NULL;
 
435
 
 
436
  if (response != GTK_RESPONSE_ACCEPT)
 
437
    {
 
438
      reject_approval (approval);
 
439
    }
 
440
  else
 
441
    {
 
442
      event_manager_approval_approve (approval);
 
443
    }
 
444
}
 
445
 
 
446
static void
 
447
event_channel_process_voip_func (EventPriv *event)
 
448
{
 
449
  GtkWidget *dialog;
 
450
  GtkWidget *button;
 
451
  GtkWidget *image;
 
452
  EmpathyTpCall *call;
 
453
  gboolean video;
 
454
  gchar *title;
 
455
 
 
456
  if (event->approval->dialog != NULL)
 
457
    {
 
458
      gtk_window_present (GTK_WINDOW (event->approval->dialog));
 
459
      return;
 
460
    }
 
461
 
 
462
  call = EMPATHY_TP_CALL (event->approval->handler_instance);
 
463
 
 
464
  video = empathy_tp_call_has_initial_video (call);
 
465
 
 
466
  dialog = gtk_message_dialog_new (NULL, 0,
 
467
      GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
 
468
      video ? _("Incoming video call"): _("Incoming call"));
 
469
 
 
470
  gtk_message_dialog_format_secondary_text (
 
471
    GTK_MESSAGE_DIALOG (dialog), video ?
 
472
      _("%s is video calling you. Do you want to answer?"):
 
473
      _("%s is calling you. Do you want to answer?"),
 
474
      empathy_contact_get_alias (event->approval->contact));
 
475
 
 
476
  title = g_strdup_printf (_("Incoming call from %s"),
 
477
      empathy_contact_get_alias (event->approval->contact));
 
478
 
 
479
  gtk_window_set_title (GTK_WINDOW (dialog), title);
 
480
  g_free (title);
 
481
 
 
482
  /* Set image of the dialog */
 
483
  if (video)
 
484
    {
 
485
      image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_VIDEO_CALL,
 
486
          GTK_ICON_SIZE_DIALOG);
 
487
    }
 
488
  else
 
489
    {
 
490
      image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_VOIP,
 
491
          GTK_ICON_SIZE_DIALOG);
 
492
    }
 
493
 
 
494
  gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), image);
 
495
  gtk_widget_show (image);
 
496
 
 
497
  gtk_dialog_set_default_response (GTK_DIALOG (dialog),
 
498
      GTK_RESPONSE_OK);
 
499
 
 
500
  button = gtk_dialog_add_button (GTK_DIALOG (dialog),
 
501
      _("_Reject"), GTK_RESPONSE_REJECT);
 
502
  image = gtk_image_new_from_icon_name ("call-stop",
 
503
    GTK_ICON_SIZE_BUTTON);
 
504
  gtk_button_set_image (GTK_BUTTON (button), image);
 
505
 
 
506
  button = gtk_dialog_add_button (GTK_DIALOG (dialog),
 
507
      _("_Answer"), GTK_RESPONSE_ACCEPT);
 
508
 
 
509
  image = gtk_image_new_from_icon_name ("call-start", GTK_ICON_SIZE_BUTTON);
 
510
  gtk_button_set_image (GTK_BUTTON (button), image);
 
511
 
 
512
  g_signal_connect (dialog, "response",
 
513
      G_CALLBACK (event_manager_call_window_confirmation_dialog_response_cb),
 
514
      event->approval);
 
515
 
 
516
  gtk_widget_show (dialog);
 
517
 
 
518
  event->approval->dialog = dialog;
 
519
}
 
520
 
 
521
static void
 
522
event_manager_chat_message_received_cb (EmpathyTpChat *tp_chat,
 
523
  EmpathyMessage *message,
 
524
  EventManagerApproval *approval)
 
525
{
 
526
  GtkWidget       *window = empathy_main_window_dup ();
 
527
  EmpathyContact  *sender;
 
528
  const gchar     *header;
 
529
  const gchar     *msg;
 
530
  TpChannel       *channel;
 
531
  EventPriv       *event;
 
532
 
 
533
  /* try to update the event if it's referring to a chat which is already in the
 
534
   * queue. */
 
535
  event = event_lookup_by_approval (approval->manager, approval);
 
536
 
 
537
  sender = empathy_message_get_sender (message);
 
538
  header = empathy_contact_get_alias (sender);
 
539
  msg = empathy_message_get_body (message);
 
540
 
 
541
  channel = empathy_tp_chat_get_channel (tp_chat);
 
542
 
 
543
  if (event != NULL)
 
544
    event_update (approval->manager, event, EMPATHY_IMAGE_NEW_MESSAGE, header,
 
545
        msg);
 
546
  else
 
547
    event_manager_add (approval->manager, sender, EMPATHY_EVENT_TYPE_CHAT,
 
548
        EMPATHY_IMAGE_NEW_MESSAGE, header, msg, approval,
 
549
        event_text_channel_process_func, NULL);
 
550
 
 
551
  empathy_sound_play (window, EMPATHY_SOUND_CONVERSATION_NEW);
 
552
 
 
553
  g_object_unref (window);
 
554
}
 
555
 
 
556
static void
 
557
event_manager_approval_done (EventManagerApproval *approval)
 
558
{
 
559
  EmpathyEventManagerPriv *priv = GET_PRIV (approval->manager);
 
560
  GSList                  *l;
 
561
 
 
562
  if (approval->operation != NULL)
 
563
    {
 
564
      GQuark channel_type;
 
565
 
 
566
      channel_type = tp_channel_get_channel_type_id (approval->main_channel);
 
567
 
 
568
      if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA)
 
569
        {
 
570
          priv->ringing--;
 
571
          if (priv->ringing == 0)
 
572
            empathy_sound_stop (EMPATHY_SOUND_PHONE_INCOMING);
 
573
        }
 
574
    }
 
575
 
 
576
  priv->approvals = g_slist_remove (priv->approvals, approval);
 
577
 
 
578
  for (l = priv->events; l; l = l->next)
 
579
    {
 
580
      EventPriv *event = l->data;
 
581
 
 
582
      if (event->approval == approval)
 
583
        {
 
584
          event_remove (event);
 
585
          break;
 
586
        }
 
587
    }
 
588
 
 
589
  event_manager_approval_free (approval);
 
590
}
 
591
 
 
592
static void
 
593
cdo_invalidated_cb (TpProxy *cdo,
 
594
    guint domain,
 
595
    gint code,
 
596
    gchar *message,
 
597
    EventManagerApproval *approval)
 
598
{
 
599
  DEBUG ("ChannelDispatchOperation has been invalidated: %s", message);
 
600
 
 
601
  event_manager_approval_done (approval);
 
602
}
 
603
 
 
604
static void
 
605
event_manager_media_channel_got_contact (EventManagerApproval *approval)
 
606
{
 
607
  EmpathyEventManagerPriv *priv = GET_PRIV (approval->manager);
 
608
  GtkWidget *window = empathy_main_window_dup ();
 
609
  gchar *header;
 
610
  EmpathyTpCall *call;
 
611
  gboolean video;
 
612
 
 
613
  call = EMPATHY_TP_CALL (approval->handler_instance);
 
614
 
 
615
  video = empathy_tp_call_has_initial_video (call);
 
616
 
 
617
  header = g_strdup_printf (
 
618
    video ? _("Incoming video call from %s") :_("Incoming call from %s"),
 
619
    empathy_contact_get_alias (approval->contact));
 
620
 
 
621
  event_manager_add (approval->manager, approval->contact,
 
622
      EMPATHY_EVENT_TYPE_VOIP,
 
623
      video ? EMPATHY_IMAGE_VIDEO_CALL : EMPATHY_IMAGE_VOIP,
 
624
      header, NULL, approval,
 
625
      event_channel_process_voip_func, NULL);
 
626
 
 
627
  g_free (header);
 
628
 
 
629
  priv->ringing++;
 
630
  if (priv->ringing == 1)
 
631
    empathy_sound_start_playing (window,
 
632
        EMPATHY_SOUND_PHONE_INCOMING, MS_BETWEEN_RING);
 
633
 
 
634
  g_object_unref (window);
 
635
}
 
636
 
 
637
static void
 
638
event_manager_media_channel_contact_changed_cb (EmpathyTpCall *call,
 
639
  GParamSpec *param, EventManagerApproval *approval)
 
640
{
 
641
  EmpathyContact *contact;
 
642
 
 
643
  g_object_get (G_OBJECT (call), "contact", &contact, NULL);
 
644
 
 
645
  if (contact == NULL)
 
646
    return;
 
647
 
 
648
  approval->contact = contact;
 
649
  event_manager_media_channel_got_contact (approval);
 
650
}
 
651
 
 
652
static void
 
653
invite_dialog_response_cb (GtkDialog *dialog,
 
654
                           gint response,
 
655
                           EventManagerApproval *approval)
 
656
{
 
657
  EmpathyTpChat *tp_chat;
 
658
 
 
659
  gtk_widget_destroy (GTK_WIDGET (approval->dialog));
 
660
  approval->dialog = NULL;
 
661
 
 
662
  tp_chat = EMPATHY_TP_CHAT (approval->handler_instance);
 
663
 
 
664
  if (response != GTK_RESPONSE_OK)
 
665
    {
 
666
      /* close channel */
 
667
      DEBUG ("Muc invitation rejected");
 
668
 
 
669
      reject_approval (approval);
 
670
 
 
671
      return;
 
672
    }
 
673
 
 
674
  DEBUG ("Muc invitation accepted");
 
675
 
 
676
  /* We'll join the room when handling the channel */
 
677
  event_manager_approval_approve (approval);
 
678
}
 
679
 
 
680
static void
 
681
event_room_channel_process_func (EventPriv *event)
 
682
{
 
683
  GtkWidget *dialog, *button, *image;
 
684
  TpChannel *channel = event->approval->main_channel;
 
685
  gchar *title;
 
686
 
 
687
  if (event->approval->dialog != NULL)
 
688
    {
 
689
      gtk_window_present (GTK_WINDOW (event->approval->dialog));
 
690
      return;
 
691
    }
 
692
 
 
693
  /* create dialog */
 
694
  dialog = gtk_message_dialog_new (NULL, 0,
 
695
      GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, _("Room invitation"));
 
696
 
 
697
  title = g_strdup_printf (_("Invitation to join %s"),
 
698
      tp_channel_get_identifier (channel));
 
699
 
 
700
  gtk_window_set_title (GTK_WINDOW (dialog), title);
 
701
  g_free (title);
 
702
 
 
703
  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
 
704
      _("%s is inviting you to join %s"),
 
705
      empathy_contact_get_alias (event->approval->contact),
 
706
      tp_channel_get_identifier (channel));
 
707
 
 
708
  gtk_dialog_set_default_response (GTK_DIALOG (dialog),
 
709
      GTK_RESPONSE_OK);
 
710
 
 
711
  button = gtk_dialog_add_button (GTK_DIALOG (dialog),
 
712
      _("_Decline"), GTK_RESPONSE_CANCEL);
 
713
  image = gtk_image_new_from_icon_name (GTK_STOCK_CANCEL, GTK_ICON_SIZE_BUTTON);
 
714
  gtk_button_set_image (GTK_BUTTON (button), image);
 
715
 
 
716
  button = gtk_dialog_add_button (GTK_DIALOG (dialog),
 
717
      _("_Join"), GTK_RESPONSE_OK);
 
718
  image = gtk_image_new_from_icon_name (GTK_STOCK_APPLY, GTK_ICON_SIZE_BUTTON);
 
719
  gtk_button_set_image (GTK_BUTTON (button), image);
 
720
 
 
721
  g_signal_connect (dialog, "response",
 
722
      G_CALLBACK (invite_dialog_response_cb), event->approval);
 
723
 
 
724
  gtk_widget_show (dialog);
 
725
 
 
726
  event->approval->dialog = dialog;
 
727
}
 
728
 
 
729
static void
 
730
display_invite_room_dialog (EventManagerApproval *approval)
 
731
{
 
732
  GtkWidget *window = empathy_main_window_dup ();
 
733
  const gchar *invite_msg;
 
734
  gchar *msg;
 
735
  TpHandle self_handle;
 
736
 
 
737
  self_handle = tp_channel_group_get_self_handle (approval->main_channel);
 
738
  tp_channel_group_get_local_pending_info (approval->main_channel, self_handle,
 
739
      NULL, NULL, &invite_msg);
 
740
 
 
741
  if (approval->contact != NULL)
 
742
    {
 
743
      msg = g_strdup_printf (_("%s invited you to join %s"),
 
744
          empathy_contact_get_alias (approval->contact),
 
745
          tp_channel_get_identifier (approval->main_channel));
 
746
    }
 
747
  else
 
748
    {
 
749
      msg = g_strdup_printf (_("You have been invited to join %s"),
 
750
          tp_channel_get_identifier (approval->main_channel));
 
751
    }
 
752
 
 
753
  event_manager_add (approval->manager, approval->contact,
 
754
      EMPATHY_EVENT_TYPE_INVITATION, EMPATHY_IMAGE_GROUP_MESSAGE, msg,
 
755
      invite_msg, approval, event_room_channel_process_func, NULL);
 
756
 
 
757
  empathy_sound_play (window, EMPATHY_SOUND_CONVERSATION_NEW);
 
758
 
 
759
  g_free (msg);
 
760
  g_object_unref (window);
 
761
}
 
762
 
 
763
static void
 
764
event_manager_muc_invite_got_contact_cb (TpConnection *connection,
 
765
                                         EmpathyContact *contact,
 
766
                                         const GError *error,
 
767
                                         gpointer user_data,
 
768
                                         GObject *object)
 
769
{
 
770
  EventManagerApproval *approval = (EventManagerApproval *) user_data;
 
771
 
 
772
  if (error != NULL)
 
773
    {
 
774
      DEBUG ("Error: %s", error->message);
 
775
    }
 
776
  else
 
777
    {
 
778
      approval->contact = g_object_ref (contact);
 
779
    }
 
780
 
 
781
  display_invite_room_dialog (approval);
 
782
}
 
783
 
 
784
static void
 
785
event_manager_ft_got_contact_cb (TpConnection *connection,
 
786
                                 EmpathyContact *contact,
 
787
                                 const GError *error,
 
788
                                 gpointer user_data,
 
789
                                 GObject *object)
 
790
{
 
791
  EventManagerApproval *approval = (EventManagerApproval *) user_data;
 
792
  GtkWidget *window = empathy_main_window_dup ();
 
793
  char *header;
 
794
 
 
795
  approval->contact = g_object_ref (contact);
 
796
 
 
797
  header = g_strdup_printf (_("Incoming file transfer from %s"),
 
798
                            empathy_contact_get_alias (approval->contact));
 
799
 
 
800
  event_manager_add (approval->manager, approval->contact,
 
801
      EMPATHY_EVENT_TYPE_TRANSFER, EMPATHY_IMAGE_DOCUMENT_SEND, header, NULL,
 
802
      approval, event_channel_process_func, NULL);
 
803
 
 
804
  /* FIXME better sound for incoming file transfers ?*/
 
805
  empathy_sound_play (window, EMPATHY_SOUND_CONVERSATION_NEW);
 
806
 
 
807
  g_free (header);
 
808
  g_object_unref (window);
 
809
}
 
810
 
 
811
/* If there is a file-transfer or media channel consider it as the
 
812
 * main one. */
 
813
static TpChannel *
 
814
find_main_channel (GList *channels)
 
815
{
 
816
  GList *l;
 
817
  TpChannel *text = NULL;
 
818
 
 
819
  for (l = channels; l != NULL; l = g_list_next (l))
 
820
    {
 
821
      TpChannel *channel = l->data;
 
822
      GQuark channel_type;
 
823
 
 
824
      if (tp_proxy_get_invalidated (channel) != NULL)
 
825
        continue;
 
826
 
 
827
      channel_type = tp_channel_get_channel_type_id (channel);
 
828
 
 
829
      if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA ||
 
830
          channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_FILE_TRANSFER)
 
831
        return channel;
 
832
 
 
833
      else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_TEXT)
 
834
        text = channel;
 
835
    }
 
836
 
 
837
  return text;
 
838
}
 
839
 
 
840
static void
 
841
approve_channels (TpSimpleApprover *approver,
 
842
    TpAccount *account,
 
843
    TpConnection *connection,
 
844
    GList *channels,
 
845
    TpChannelDispatchOperation *dispatch_operation,
 
846
    TpAddDispatchOperationContext *context,
 
847
    gpointer user_data)
 
848
{
 
849
  EmpathyEventManager *self = user_data;
 
850
  EmpathyEventManagerPriv *priv = GET_PRIV (self);
 
851
  TpChannel *channel;
 
852
  EventManagerApproval *approval;
 
853
  GQuark channel_type;
 
854
 
 
855
  channel = find_main_channel (channels);
 
856
  if (channel == NULL)
 
857
    {
 
858
      GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
 
859
          "Unknown channel type" };
 
860
 
 
861
      DEBUG ("Failed to find the main channel; ignoring");
 
862
 
 
863
      tp_add_dispatch_operation_context_fail (context, &error);
 
864
      return;
 
865
    }
 
866
 
 
867
  approval = event_manager_approval_new (self, dispatch_operation, channel);
 
868
  priv->approvals = g_slist_prepend (priv->approvals, approval);
 
869
 
 
870
  approval->invalidated_handler = g_signal_connect (dispatch_operation,
 
871
      "invalidated", G_CALLBACK (cdo_invalidated_cb), approval);
 
872
 
 
873
  channel_type = tp_channel_get_channel_type_id (channel);
 
874
 
 
875
  if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_TEXT)
 
876
    {
 
877
      EmpathyTpChat *tp_chat;
 
878
 
 
879
      tp_chat = empathy_tp_chat_new (account, channel);
 
880
      approval->handler_instance = G_OBJECT (tp_chat);
 
881
 
 
882
      if (tp_proxy_has_interface (channel, TP_IFACE_CHANNEL_INTERFACE_GROUP))
 
883
        {
 
884
          /* Are we in local-pending ? */
 
885
          TpHandle inviter;
 
886
 
 
887
          if (empathy_tp_chat_is_invited (tp_chat, &inviter))
 
888
            {
 
889
              /* We are invited to a room */
 
890
              DEBUG ("Have been invited to %s. Ask user if he wants to accept",
 
891
                  tp_channel_get_identifier (channel));
 
892
 
 
893
              if (inviter != 0)
 
894
                {
 
895
                  empathy_tp_contact_factory_get_from_handle (connection,
 
896
                      inviter, event_manager_muc_invite_got_contact_cb,
 
897
                      approval, NULL, G_OBJECT (self));
 
898
                }
 
899
              else
 
900
                {
 
901
                  display_invite_room_dialog (approval);
 
902
                }
 
903
 
 
904
              goto out;
 
905
            }
 
906
 
 
907
          /* We are not invited, approve the channel right now */
 
908
          tp_add_dispatch_operation_context_accept (context);
 
909
 
 
910
          approval->auto_approved = TRUE;
 
911
          event_manager_approval_approve (approval);
 
912
          return;
 
913
        }
 
914
 
 
915
      /* 1-1 text channel, wait for the first message */
 
916
      approval->handler = g_signal_connect (tp_chat, "message-received",
 
917
        G_CALLBACK (event_manager_chat_message_received_cb), approval);
 
918
    }
 
919
  else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA)
 
920
    {
 
921
      EmpathyContact *contact;
 
922
      EmpathyTpCall *call = empathy_tp_call_new (account, channel);
 
923
 
 
924
      approval->handler_instance = G_OBJECT (call);
 
925
 
 
926
      g_object_get (G_OBJECT (call), "contact", &contact, NULL);
 
927
 
 
928
      if (contact == NULL)
 
929
        {
 
930
          g_signal_connect (call, "notify::contact",
 
931
            G_CALLBACK (event_manager_media_channel_contact_changed_cb),
 
932
            approval);
 
933
        }
 
934
      else
 
935
        {
 
936
          approval->contact = contact;
 
937
          event_manager_media_channel_got_contact (approval);
 
938
        }
 
939
 
 
940
    }
 
941
  else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_FILE_TRANSFER)
 
942
    {
 
943
      TpHandle handle;
 
944
      EmpathyTpFile *tp_file = empathy_tp_file_new (channel);
 
945
 
 
946
      approval->handler_instance = G_OBJECT (tp_file);
 
947
 
 
948
      handle = tp_channel_get_handle (channel, NULL);
 
949
 
 
950
      connection = tp_channel_borrow_connection (channel);
 
951
      empathy_tp_contact_factory_get_from_handle (connection, handle,
 
952
        event_manager_ft_got_contact_cb, approval, NULL, G_OBJECT (self));
 
953
    }
 
954
  else
 
955
    {
 
956
      GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
 
957
          "Invalid channel type" };
 
958
 
 
959
      DEBUG ("Unknown channel type (%s), ignoring..",
 
960
          g_quark_to_string (channel_type));
 
961
 
 
962
      tp_add_dispatch_operation_context_fail (context, &error);
 
963
      return;
 
964
    }
 
965
 
 
966
out:
 
967
  tp_add_dispatch_operation_context_accept (context);
 
968
}
 
969
 
 
970
static void
 
971
event_pending_subscribe_func (EventPriv *event)
 
972
{
 
973
  empathy_subscription_dialog_show (event->public.contact, NULL);
 
974
  event_remove (event);
 
975
}
 
976
 
 
977
static void
 
978
event_manager_pendings_changed_cb (EmpathyContactList  *list,
 
979
  EmpathyContact *contact, EmpathyContact *actor,
 
980
  guint reason, gchar *message, gboolean is_pending,
 
981
  EmpathyEventManager *manager)
 
982
{
 
983
  EmpathyEventManagerPriv *priv = GET_PRIV (manager);
 
984
  gchar                   *header, *event_msg;
 
985
 
 
986
  if (!is_pending)
 
987
    {
 
988
      GSList *l;
 
989
 
 
990
      for (l = priv->events; l; l = l->next)
 
991
        {
 
992
          EventPriv *event = l->data;
 
993
 
 
994
          if (event->public.contact == contact &&
 
995
              event->func == event_pending_subscribe_func)
 
996
            {
 
997
              event_remove (event);
 
998
              break;
 
999
            }
 
1000
        }
 
1001
 
 
1002
      return;
 
1003
    }
 
1004
 
 
1005
  header = g_strdup_printf (_("Subscription requested by %s"),
 
1006
    empathy_contact_get_alias (contact));
 
1007
 
 
1008
  if (!EMP_STR_EMPTY (message))
 
1009
    event_msg = g_strdup_printf (_("\nMessage: %s"), message);
 
1010
  else
 
1011
    event_msg = NULL;
 
1012
 
 
1013
  event_manager_add (manager, contact, EMPATHY_EVENT_TYPE_SUBSCRIPTION,
 
1014
      GTK_STOCK_DIALOG_QUESTION, header, event_msg, NULL,
 
1015
      event_pending_subscribe_func, NULL);
 
1016
 
 
1017
  g_free (event_msg);
 
1018
  g_free (header);
 
1019
}
 
1020
 
 
1021
static void
 
1022
event_manager_presence_changed_cb (EmpathyContact *contact,
 
1023
    TpConnectionPresenceType current,
 
1024
    TpConnectionPresenceType previous,
 
1025
    EmpathyEventManager *manager)
 
1026
{
 
1027
  TpAccount *account;
 
1028
  gchar *header = NULL;
 
1029
  EmpathyIdle *idle;
 
1030
  GSettings *gsettings = g_settings_new (EMPATHY_PREFS_NOTIFICATIONS_SCHEMA);
 
1031
  GtkWidget *window = empathy_main_window_dup ();
 
1032
 
 
1033
  account = empathy_contact_get_account (contact);
 
1034
  idle = empathy_idle_dup_singleton ();
 
1035
 
 
1036
  if (empathy_idle_account_is_just_connected (idle, account))
 
1037
    goto out;
 
1038
 
 
1039
  if (tp_connection_presence_type_cmp_availability (previous,
 
1040
        TP_CONNECTION_PRESENCE_TYPE_OFFLINE) > 0)
 
1041
    {
 
1042
      /* contact was online */
 
1043
      if (tp_connection_presence_type_cmp_availability (current,
 
1044
          TP_CONNECTION_PRESENCE_TYPE_OFFLINE) <= 0)
 
1045
        {
 
1046
          /* someone is logging off */
 
1047
          empathy_sound_play (window, EMPATHY_SOUND_CONTACT_DISCONNECTED);
 
1048
 
 
1049
          if (g_settings_get_boolean (gsettings,
 
1050
                EMPATHY_PREFS_NOTIFICATIONS_CONTACT_SIGNOUT))
 
1051
            {
 
1052
              header = g_strdup_printf (_("%s is now offline."),
 
1053
                  empathy_contact_get_alias (contact));
 
1054
 
 
1055
              event_manager_add (manager, contact, EMPATHY_EVENT_TYPE_PRESENCE,
 
1056
                  EMPATHY_IMAGE_AVATAR_DEFAULT, header, NULL, NULL, NULL, NULL);
 
1057
            }
 
1058
        }
 
1059
    }
 
1060
  else
 
1061
    {
 
1062
      /* contact was offline */
 
1063
      if (tp_connection_presence_type_cmp_availability (current,
 
1064
            TP_CONNECTION_PRESENCE_TYPE_OFFLINE) > 0)
 
1065
        {
 
1066
          /* someone is logging in */
 
1067
          empathy_sound_play (window, EMPATHY_SOUND_CONTACT_CONNECTED);
 
1068
 
 
1069
          if (g_settings_get_boolean (gsettings,
 
1070
                EMPATHY_PREFS_NOTIFICATIONS_CONTACT_SIGNIN))
 
1071
            {
 
1072
              header = g_strdup_printf (_("%s is now online."),
 
1073
                  empathy_contact_get_alias (contact));
 
1074
 
 
1075
              event_manager_add (manager, contact, EMPATHY_EVENT_TYPE_PRESENCE,
 
1076
                  EMPATHY_IMAGE_AVATAR_DEFAULT, header, NULL, NULL, NULL, NULL);
 
1077
            }
 
1078
        }
 
1079
    }
 
1080
  g_free (header);
 
1081
 
 
1082
out:
 
1083
  g_object_unref (idle);
 
1084
  g_object_unref (gsettings);
 
1085
  g_object_unref (window);
 
1086
}
 
1087
 
 
1088
static void
 
1089
event_manager_members_changed_cb (EmpathyContactList  *list,
 
1090
    EmpathyContact *contact,
 
1091
    EmpathyContact *actor,
 
1092
    guint reason,
 
1093
    gchar *message,
 
1094
    gboolean is_member,
 
1095
    EmpathyEventManager *manager)
 
1096
{
 
1097
  if (is_member)
 
1098
    g_signal_connect (contact, "presence-changed",
 
1099
        G_CALLBACK (event_manager_presence_changed_cb), manager);
 
1100
  else
 
1101
    g_signal_handlers_disconnect_by_func (contact,
 
1102
        event_manager_presence_changed_cb, manager);
 
1103
}
 
1104
 
 
1105
static GObject *
 
1106
event_manager_constructor (GType type,
 
1107
                           guint n_props,
 
1108
                           GObjectConstructParam *props)
 
1109
{
 
1110
        GObject *retval;
 
1111
 
 
1112
        if (manager_singleton) {
 
1113
                retval = g_object_ref (manager_singleton);
 
1114
        } else {
 
1115
                retval = G_OBJECT_CLASS (empathy_event_manager_parent_class)->constructor
 
1116
                        (type, n_props, props);
 
1117
 
 
1118
                manager_singleton = EMPATHY_EVENT_MANAGER (retval);
 
1119
                g_object_add_weak_pointer (retval, (gpointer) &manager_singleton);
 
1120
        }
 
1121
 
 
1122
        return retval;
 
1123
}
 
1124
 
 
1125
static void
 
1126
event_manager_finalize (GObject *object)
 
1127
{
 
1128
  EmpathyEventManagerPriv *priv = GET_PRIV (object);
 
1129
 
 
1130
  if (priv->ringing > 0)
 
1131
    empathy_sound_stop (EMPATHY_SOUND_PHONE_INCOMING);
 
1132
 
 
1133
  g_slist_foreach (priv->events, (GFunc) event_free, NULL);
 
1134
  g_slist_free (priv->events);
 
1135
  g_slist_foreach (priv->approvals, (GFunc) event_manager_approval_free, NULL);
 
1136
  g_slist_free (priv->approvals);
 
1137
  g_object_unref (priv->contact_manager);
 
1138
  g_object_unref (priv->approver);
 
1139
}
 
1140
 
 
1141
static void
 
1142
empathy_event_manager_class_init (EmpathyEventManagerClass *klass)
 
1143
{
 
1144
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
1145
 
 
1146
  object_class->finalize = event_manager_finalize;
 
1147
  object_class->constructor = event_manager_constructor;
 
1148
 
 
1149
  signals[EVENT_ADDED] =
 
1150
    g_signal_new ("event-added",
 
1151
      G_TYPE_FROM_CLASS (klass),
 
1152
      G_SIGNAL_RUN_LAST,
 
1153
      0,
 
1154
      NULL, NULL,
 
1155
      g_cclosure_marshal_VOID__POINTER,
 
1156
      G_TYPE_NONE,
 
1157
      1, G_TYPE_POINTER);
 
1158
 
 
1159
  signals[EVENT_REMOVED] =
 
1160
  g_signal_new ("event-removed",
 
1161
      G_TYPE_FROM_CLASS (klass),
 
1162
      G_SIGNAL_RUN_LAST,
 
1163
      0,
 
1164
      NULL, NULL,
 
1165
      g_cclosure_marshal_VOID__POINTER,
 
1166
      G_TYPE_NONE, 1, G_TYPE_POINTER);
 
1167
 
 
1168
  signals[EVENT_UPDATED] =
 
1169
  g_signal_new ("event-updated",
 
1170
      G_TYPE_FROM_CLASS (klass),
 
1171
      G_SIGNAL_RUN_LAST,
 
1172
      0,
 
1173
      NULL, NULL,
 
1174
      g_cclosure_marshal_VOID__POINTER,
 
1175
      G_TYPE_NONE, 1, G_TYPE_POINTER);
 
1176
 
 
1177
 
 
1178
  g_type_class_add_private (object_class, sizeof (EmpathyEventManagerPriv));
 
1179
}
 
1180
 
 
1181
static void
 
1182
empathy_event_manager_init (EmpathyEventManager *manager)
 
1183
{
 
1184
  EmpathyEventManagerPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
 
1185
    EMPATHY_TYPE_EVENT_MANAGER, EmpathyEventManagerPriv);
 
1186
  TpDBusDaemon *dbus;
 
1187
  GError *error = NULL;
 
1188
 
 
1189
  manager->priv = priv;
 
1190
 
 
1191
  priv->contact_manager = empathy_contact_manager_dup_singleton ();
 
1192
  g_signal_connect (priv->contact_manager, "pendings-changed",
 
1193
    G_CALLBACK (event_manager_pendings_changed_cb), manager);
 
1194
 
 
1195
  g_signal_connect (priv->contact_manager, "members-changed",
 
1196
    G_CALLBACK (event_manager_members_changed_cb), manager);
 
1197
 
 
1198
  dbus = tp_dbus_daemon_dup (&error);
 
1199
  if (dbus == NULL)
 
1200
    {
 
1201
      DEBUG ("Failed to get TpDBusDaemon: %s", error->message);
 
1202
      g_error_free (error);
 
1203
      return;
 
1204
    }
 
1205
 
 
1206
  priv->approver = tp_simple_approver_new (dbus, "Empathy.EventManager", FALSE,
 
1207
      approve_channels, manager, NULL);
 
1208
 
 
1209
  /* Private text channels */
 
1210
  tp_base_client_take_approver_filter (priv->approver,
 
1211
      tp_asv_new (
 
1212
        TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_TEXT,
 
1213
        TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
 
1214
        NULL));
 
1215
 
 
1216
  /* Muc text channels */
 
1217
  tp_base_client_take_approver_filter (priv->approver,
 
1218
      tp_asv_new (
 
1219
        TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_TEXT,
 
1220
        TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_ROOM,
 
1221
        NULL));
 
1222
 
 
1223
  /* File transfer */
 
1224
  tp_base_client_take_approver_filter (priv->approver,
 
1225
      tp_asv_new (
 
1226
        TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
 
1227
          TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER,
 
1228
        TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
 
1229
        NULL));
 
1230
 
 
1231
  /* Calls */
 
1232
  tp_base_client_take_approver_filter (priv->approver,
 
1233
      tp_asv_new (
 
1234
        TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
 
1235
          TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
 
1236
        TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
 
1237
        NULL));
 
1238
 
 
1239
  if (!tp_base_client_register (priv->approver, &error))
 
1240
    {
 
1241
      DEBUG ("Failed to register Approver: %s", error->message);
 
1242
      g_error_free (error);
 
1243
    }
 
1244
 
 
1245
  g_object_unref (dbus);
 
1246
}
 
1247
 
 
1248
EmpathyEventManager *
 
1249
empathy_event_manager_dup_singleton (void)
 
1250
{
 
1251
  return g_object_new (EMPATHY_TYPE_EVENT_MANAGER, NULL);
 
1252
}
 
1253
 
 
1254
GSList *
 
1255
empathy_event_manager_get_events (EmpathyEventManager *manager)
 
1256
{
 
1257
  EmpathyEventManagerPriv *priv = GET_PRIV (manager);
 
1258
 
 
1259
  g_return_val_if_fail (EMPATHY_IS_EVENT_MANAGER (manager), NULL);
 
1260
 
 
1261
  return priv->events;
 
1262
}
 
1263
 
 
1264
EmpathyEvent *
 
1265
empathy_event_manager_get_top_event (EmpathyEventManager *manager)
 
1266
{
 
1267
  EmpathyEventManagerPriv *priv = GET_PRIV (manager);
 
1268
 
 
1269
  g_return_val_if_fail (EMPATHY_IS_EVENT_MANAGER (manager), NULL);
 
1270
 
 
1271
  return priv->events ? priv->events->data : NULL;
 
1272
}
 
1273
 
 
1274
void
 
1275
empathy_event_activate (EmpathyEvent *event_public)
 
1276
{
 
1277
  EventPriv *event = (EventPriv *) event_public;
 
1278
 
 
1279
  g_return_if_fail (event_public != NULL);
 
1280
 
 
1281
  if (event->func)
 
1282
    event->func (event);
 
1283
  else
 
1284
    event_remove (event);
 
1285
}
 
1286
 
 
1287
void
 
1288
empathy_event_inhibit_updates (EmpathyEvent *event_public)
 
1289
{
 
1290
  EventPriv *event = (EventPriv *) event_public;
 
1291
 
 
1292
  g_return_if_fail (event_public != NULL);
 
1293
 
 
1294
  event->inhibit = TRUE;
 
1295
}
 
1296
 
 
1297
void
 
1298
empathy_event_approve (EmpathyEvent *event_public)
 
1299
{
 
1300
  EventPriv *event = (EventPriv *) event_public;
 
1301
 
 
1302
  g_return_if_fail (event_public != NULL);
 
1303
 
 
1304
  event_manager_approval_approve (event->approval);
 
1305
}
 
1306
 
 
1307
void
 
1308
empathy_event_decline (EmpathyEvent *event_public)
 
1309
{
 
1310
  EventPriv *event = (EventPriv *) event_public;
 
1311
 
 
1312
  g_return_if_fail (event_public != NULL);
 
1313
 
 
1314
  reject_approval (event->approval);
 
1315
}