]> git.0d.be Git - empathy.git/blob - src/empathy.c
Ensure EmpathyConnectionManagers stays alive when still emitting signals
[empathy.git] / src / empathy.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2007-2008 Collabora Ltd.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program 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  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA  02110-1301  USA
19  *
20  * Authors: Xavier Claessens <xclaesse@gmail.com>
21  */
22
23 #include <config.h>
24
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <string.h>
28
29 #include <glib.h>
30 #include <glib/gi18n.h>
31 #include <gtk/gtk.h>
32 #include <gdk/gdkx.h>
33
34 #if HAVE_LIBCHAMPLAIN
35 #include <clutter-gtk/gtk-clutter-embed.h>
36 #endif
37
38 #include <libebook/e-book.h>
39 #include <libnotify/notify.h>
40
41 #include <telepathy-glib/dbus.h>
42 #include <telepathy-glib/util.h>
43 #include <telepathy-glib/connection-manager.h>
44 #include <telepathy-glib/interfaces.h>
45
46 #include <libempathy/empathy-idle.h>
47 #include <libempathy/empathy-utils.h>
48 #include <libempathy/empathy-call-factory.h>
49 #include <libempathy/empathy-chatroom-manager.h>
50 #include <libempathy/empathy-account-settings.h>
51 #include <libempathy/empathy-account-manager.h>
52 #include <libempathy/empathy-connection-managers.h>
53 #include <libempathy/empathy-debugger.h>
54 #include <libempathy/empathy-dispatcher.h>
55 #include <libempathy/empathy-dispatch-operation.h>
56 #include <libempathy/empathy-log-manager.h>
57 #include <libempathy/empathy-ft-factory.h>
58 #include <libempathy/empathy-tp-chat.h>
59 #include <libempathy/empathy-tp-call.h>
60
61 #include <libempathy-gtk/empathy-conf.h>
62 #include <libempathy-gtk/empathy-ui-utils.h>
63 #include <libempathy-gtk/empathy-location-manager.h>
64
65 #include "empathy-accounts-dialog.h"
66 #include "empathy-main-window.h"
67 #include "empathy-status-icon.h"
68 #include "empathy-call-window.h"
69 #include "empathy-chat-window.h"
70 #include "empathy-ft-manager.h"
71 #include "bacon-message-connection.h"
72
73 #include "extensions/extensions.h"
74
75 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
76 #include <libempathy/empathy-debug.h>
77
78 #include <gst/gst.h>
79
80 static BaconMessageConnection *connection = NULL;
81
82 static void
83 dispatch_cb (EmpathyDispatcher *dispatcher,
84              EmpathyDispatchOperation *operation,
85              gpointer           user_data)
86 {
87         GQuark channel_type;
88
89         channel_type = empathy_dispatch_operation_get_channel_type_id (operation);
90
91         if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_TEXT) {
92                 EmpathyTpChat *tp_chat;
93                 EmpathyChat   *chat = NULL;
94                 const gchar   *id;
95
96                 tp_chat = EMPATHY_TP_CHAT (
97                         empathy_dispatch_operation_get_channel_wrapper (operation));
98
99                 id = empathy_tp_chat_get_id (tp_chat);
100                 if (!id) {
101                         EmpathyContact *contact;
102
103                         contact = empathy_tp_chat_get_remote_contact (tp_chat);
104                         if (contact) {
105                                 id = empathy_contact_get_id (contact);
106                         }
107                 }
108
109                 if (id) {
110                         EmpathyAccountManager *manager;
111                         TpConnection *connection;
112                         EmpathyAccount *account;
113
114                         manager = empathy_account_manager_dup_singleton ();
115                         connection = empathy_tp_chat_get_connection (tp_chat);
116                         account = empathy_account_manager_get_account (manager,
117                                                                        connection);
118                         chat = empathy_chat_window_find_chat (account, id);
119                         g_object_unref (manager);
120                 }
121
122                 if (chat) {
123                         empathy_chat_set_tp_chat (chat, tp_chat);
124                 } else {
125                         chat = empathy_chat_new (tp_chat);
126                 }
127
128                 empathy_chat_window_present_chat (chat);
129
130                 empathy_dispatch_operation_claim (operation);
131         } else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA) {
132                 EmpathyCallFactory *factory;
133
134                 factory = empathy_call_factory_get ();
135                 empathy_call_factory_claim_channel (factory, operation);
136         } else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_FILE_TRANSFER) {
137                 EmpathyFTFactory *factory;
138
139                 factory = empathy_ft_factory_dup_singleton ();
140
141                 /* if the operation is not incoming, don't claim it,
142                  * as it might have been triggered by another client, and
143                  * we are observing it.
144                  */
145                 if (empathy_dispatch_operation_is_incoming (operation)) {
146                         empathy_ft_factory_claim_channel (factory, operation);
147                 }
148         }
149 }
150
151 static void
152 use_nm_notify_cb (EmpathyConf *conf,
153                   const gchar *key,
154                   gpointer     user_data)
155 {
156         EmpathyIdle *idle = user_data;
157         gboolean     use_nm;
158
159         if (empathy_conf_get_bool (conf, key, &use_nm)) {
160                 empathy_idle_set_use_nm (idle, use_nm);
161         }
162 }
163
164 /* Salut account creation */
165 static gboolean
166 should_create_salut_account (void)
167 {
168         EmpathyAccountManager *manager;
169         gboolean salut_created = FALSE;
170         GList *accounts, *l;
171
172         /* Check if we already created a salut account */
173         empathy_conf_get_bool (empathy_conf_get (),
174                                EMPATHY_PREFS_SALUT_ACCOUNT_CREATED,
175                                &salut_created);
176
177         if (salut_created)
178                 {
179                         DEBUG ("Gconf says we already created a salut account once");
180                         return FALSE;
181                 }
182
183         manager = empathy_account_manager_dup_singleton ();
184         accounts = empathy_account_manager_dup_accounts (manager);
185
186         for (l = accounts; l != NULL;  l = g_list_next (l)) {
187                 EmpathyAccount *account = EMPATHY_ACCOUNT (l->data);
188
189                 if (!tp_strdiff (empathy_account_get_protocol (account), "local-xmpp"))
190                         salut_created = TRUE;
191
192                 g_object_unref (account);
193         }
194
195         g_object_unref (manager);
196
197         if (salut_created)
198                 {
199                         DEBUG ("Existing salut account already exists, flagging so in gconf");
200                         empathy_conf_set_bool (empathy_conf_get (),
201                                 EMPATHY_PREFS_SALUT_ACCOUNT_CREATED,
202                                 TRUE);
203                 }
204
205         return !salut_created;
206 }
207
208 static void
209 salut_account_created (GObject *source,
210         GAsyncResult *result, gpointer user_data)
211 {
212         EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (source);
213         EmpathyAccount *account;
214         GError *error = NULL;
215
216         if (!empathy_account_settings_apply_finish (settings, result, &error))
217                 {
218                         DEBUG ("Failed to create salut account: %s", error->message);
219                         g_error_free (error);
220                         return;
221                 }
222
223         account = empathy_account_settings_get_account (settings);
224
225         empathy_account_set_enabled (account, TRUE);
226         empathy_conf_set_bool (empathy_conf_get (),
227                                EMPATHY_PREFS_SALUT_ACCOUNT_CREATED,
228                                TRUE);
229 }
230
231 static void
232 create_salut_account_if_needed (EmpathyConnectionManagers *managers)
233 {
234         EmpathyAccountSettings  *settings;
235         TpConnectionManager *manager;
236         const TpConnectionManagerProtocol *protocol;
237         EBook      *book;
238         EContact   *contact;
239         gchar      *nickname = NULL;
240         gchar      *first_name = NULL;
241         gchar      *last_name = NULL;
242         gchar      *email = NULL;
243         gchar      *jid = NULL;
244         GError     *error = NULL;
245
246
247         if (!should_create_salut_account ())
248                 return;
249
250         manager = empathy_connection_managers_get_cm (managers, "salut");
251         if (manager == NULL)
252                 {
253                         DEBUG ("Salut not installed, not making a salut account");
254                         return;
255                 }
256
257         protocol = tp_connection_manager_get_protocol (manager, "local-xmpp");
258         if (protocol == NULL)
259                 {
260                         DEBUG ("Salut doesn't support local-xmpp!!");
261                         return;
262                 }
263
264         DEBUG ("Trying to add a salut account...");
265
266         /* Get self EContact from EDS */
267         if (!e_book_get_self (&contact, &book, &error)) {
268                 DEBUG ("Failed to get self econtact: %s",
269                         error ? error->message : "No error given");
270                 g_clear_error (&error);
271                 return;
272         }
273
274         settings = empathy_account_settings_new ("salut", "local-xmpp",
275                 _("People nearby"));
276
277         nickname = e_contact_get (contact, E_CONTACT_NICKNAME);
278         first_name = e_contact_get (contact, E_CONTACT_GIVEN_NAME);
279         last_name = e_contact_get (contact, E_CONTACT_FAMILY_NAME);
280         email = e_contact_get (contact, E_CONTACT_EMAIL_1);
281         jid = e_contact_get (contact, E_CONTACT_IM_JABBER_HOME_1);
282
283         if (!tp_strdiff (nickname, "nickname")) {
284                 g_free (nickname);
285                 nickname = NULL;
286         }
287
288         DEBUG ("Salut account created:\nnickname=%s\nfirst-name=%s\n"
289                 "last-name=%s\nemail=%s\njid=%s\n",
290                 nickname, first_name, last_name, email, jid);
291
292         empathy_account_settings_set_string (settings, "nickname", nickname ? nickname : "");
293         empathy_account_settings_set_string (settings, "first-name", first_name ? first_name : "");
294         empathy_account_settings_set_string (settings, "last-name", last_name ? last_name : "");
295         empathy_account_settings_set_string (settings, "email", email ? email : "");
296         empathy_account_settings_set_string (settings, "jid", jid ? jid : "");
297
298         empathy_account_settings_apply_async (settings,
299                 salut_account_created, NULL);
300
301         g_free (nickname);
302         g_free (first_name);
303         g_free (last_name);
304         g_free (email);
305         g_free (jid);
306         g_object_unref (settings);
307         g_object_unref (contact);
308         g_object_unref (book);
309 }
310
311 static void
312 connection_managers_ready_cb (EmpathyConnectionManagers *managers,
313         GParamSpec *spec, gpointer user_data)
314 {
315         if (empathy_connection_managers_is_ready (managers))
316                 {
317                         create_salut_account_if_needed (managers);
318                         g_object_unref (managers);
319                         managers = NULL;
320                 }
321 }
322
323 static void
324 create_salut_account (void)
325 {
326         EmpathyConnectionManagers *managers;
327
328         if (!should_create_salut_account ())
329                 return;
330
331         managers = empathy_connection_managers_dup_singleton ();
332
333         if (empathy_connection_managers_is_ready (managers))
334                 {
335                         create_salut_account_if_needed (managers);
336                         g_object_unref (managers);
337                 }
338         else
339                 {
340                         g_signal_connect (managers, "notify::ready",
341                                 G_CALLBACK (connection_managers_ready_cb), NULL);
342                 }
343 }
344
345 /* The code that handles single-instance and startup notification is
346  * copied from gedit.
347  *
348  * Copyright (C) 2005 - Paolo Maggi
349  */
350 static void
351 on_bacon_message_received (const char *message,
352                            gpointer    data)
353 {
354         GtkWidget *window = data;
355         guint32    startup_timestamp;
356
357         g_return_if_fail (message != NULL);
358
359         DEBUG ("Other instance launched, presenting the main window. message='%s'",
360                 message);
361
362         if (strcmp (message, "accounts") == 0) {
363                 /* accounts dialog requested */
364                 empathy_accounts_dialog_show (GTK_WINDOW (window), NULL);
365         } else {
366                 startup_timestamp = atoi (message);
367
368                 /* Set the proper interaction time on the window.
369                  * Fall back to roundtripping to the X server when we
370                  * don't have the timestamp, e.g. when launched from
371                  * terminal. We also need to make sure that the window
372                  * has been realized otherwise it will not work. lame. */
373                 if (startup_timestamp == 0) {
374                         /* Work if launched from the terminal */
375                         DEBUG ("Using X server timestamp as a fallback");
376
377                         if (!GTK_WIDGET_REALIZED (window)) {
378                                 gtk_widget_realize (GTK_WIDGET (window));
379                         }
380
381                         startup_timestamp = gdk_x11_get_server_time (window->window);
382                 }
383
384                 gtk_window_present_with_time (GTK_WINDOW (window), startup_timestamp);
385         }
386 }
387
388 static guint32
389 get_startup_timestamp ()
390 {
391         const gchar *startup_id_env;
392         gchar       *startup_id = NULL;
393         gchar       *time_str;
394         gchar       *end;
395         gulong       retval = 0;
396
397         /* we don't unset the env, since startup-notification
398          * may still need it */
399         startup_id_env = g_getenv ("DESKTOP_STARTUP_ID");
400         if (startup_id_env == NULL) {
401                 goto out;
402         }
403
404         startup_id = g_strdup (startup_id_env);
405
406         time_str = g_strrstr (startup_id, "_TIME");
407         if (time_str == NULL) {
408                 goto out;
409         }
410
411         errno = 0;
412
413         /* Skip past the "_TIME" part */
414         time_str += 5;
415
416         retval = strtoul (time_str, &end, 0);
417         if (end == time_str || errno != 0)
418                 retval = 0;
419
420  out:
421         g_free (startup_id);
422
423         return (retval > 0) ? retval : 0;
424 }
425
426 static gboolean
427 show_version_cb (const char *option_name,
428                  const char *value,
429                  gpointer data,
430                  GError **error)
431 {
432         g_print ("%s\n", PACKAGE_STRING);
433
434         exit (EXIT_SUCCESS);
435
436         return FALSE;
437 }
438
439 static void
440 new_incoming_transfer_cb (EmpathyFTFactory *factory,
441                           EmpathyFTHandler *handler,
442                           GError *error,
443                           gpointer user_data)
444 {
445         if (error) {
446                 empathy_ft_manager_display_error (handler, error);
447         } else {
448                 empathy_receive_file_with_file_chooser (handler);
449         }
450 }
451
452 static void
453 new_ft_handler_cb (EmpathyFTFactory *factory,
454                    EmpathyFTHandler *handler,
455                    GError *error,
456                    gpointer user_data)
457 {
458         if (error) {
459                 empathy_ft_manager_display_error (handler, error);
460         } else {
461                 empathy_ft_manager_add_handler (handler);
462         }
463
464         g_object_unref (handler);
465 }
466
467 static void
468 new_call_handler_cb (EmpathyCallFactory *factory, EmpathyCallHandler *handler,
469         gboolean outgoing, gpointer user_data)
470 {
471         EmpathyCallWindow *window;
472
473         window = empathy_call_window_new (handler);
474         gtk_widget_show (GTK_WIDGET (window));
475 }
476
477 #ifdef ENABLE_DEBUG
478 static void
479 default_log_handler (const gchar *log_domain,
480     GLogLevelFlags log_level,
481     const gchar *message,
482     gpointer user_data)
483 {
484         g_log_default_handler (log_domain, log_level, message, NULL);
485
486         /* G_LOG_DOMAIN = "empathy". No need to send empathy messages to the
487          * debugger as they already have in empathy_debug. */
488         if (log_level != G_LOG_LEVEL_DEBUG
489             || tp_strdiff (log_domain, G_LOG_DOMAIN)) {
490                 EmpathyDebugger *dbg;
491                 GTimeVal now;
492
493                 dbg = empathy_debugger_get_singleton ();
494                 g_get_current_time (&now);
495
496                 empathy_debugger_add_message (dbg, &now, log_domain,
497                                               log_level, message);
498         }
499 }
500 #endif /* ENABLE_DEBUG */
501
502 static void
503 account_manager_ready_cb (EmpathyAccountManager *manager,
504         GParamSpec *spec,
505         gpointer user_data)
506 {
507         if (!empathy_account_manager_is_ready (manager))
508                 return;
509
510         if (empathy_account_manager_get_count (manager) == 0)
511                 {
512                         empathy_accounts_dialog_show (GTK_WINDOW (empathy_main_window_get ()),
513                                 NULL);
514                 }
515         create_salut_account ();
516 }
517
518 int
519 main (int argc, char *argv[])
520 {
521         guint32            startup_timestamp;
522 #if HAVE_GEOCLUE
523         EmpathyLocationManager *location_manager = NULL;
524 #endif
525         EmpathyStatusIcon *icon;
526         EmpathyDispatcher *dispatcher;
527         EmpathyAccountManager *account_manager;
528         EmpathyLogManager *log_manager;
529         EmpathyChatroomManager *chatroom_manager;
530         EmpathyCallFactory *call_factory;
531         EmpathyFTFactory  *ft_factory;
532         GtkWidget         *window;
533         EmpathyIdle       *idle;
534         gboolean           autoconnect = TRUE;
535         gboolean           no_connect = FALSE;
536         gboolean           hide_contact_list = FALSE;
537         gboolean           accounts_dialog = FALSE;
538         GError            *error = NULL;
539         TpDBusDaemon      *dbus_daemon;
540         GOptionEntry       options[] = {
541                 { "no-connect", 'n',
542                   0, G_OPTION_ARG_NONE, &no_connect,
543                   N_("Don't connect on startup"),
544                   NULL },
545                 { "hide-contact-list", 'h',
546                   0, G_OPTION_ARG_NONE, &hide_contact_list,
547                   N_("Don't show the contact list on startup"),
548                   NULL },
549                 { "accounts", 'a',
550                   0, G_OPTION_ARG_NONE, &accounts_dialog,
551                   N_("Show the accounts dialog"),
552                   NULL },
553                 { "version", 'v',
554                   G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version_cb, NULL, NULL },
555                 { NULL }
556         };
557
558         /* Init */
559         g_thread_init (NULL);
560         empathy_init ();
561
562         if (!gtk_init_with_args (&argc, &argv,
563                                  N_("- Empathy Instant Messenger"),
564                                  options, GETTEXT_PACKAGE, &error)) {
565                 g_warning ("Error in empathy init: %s", error->message);
566                 return EXIT_FAILURE;
567         }
568
569         empathy_gtk_init ();
570         g_set_application_name (_(PACKAGE_NAME));
571         g_setenv ("PULSE_PROP_media.role", "phone", TRUE);
572
573         gst_init (&argc, &argv);
574
575 #if HAVE_LIBCHAMPLAIN
576         gtk_clutter_init (&argc, &argv);
577 #endif
578
579         gtk_window_set_default_icon_name ("empathy");
580         textdomain (GETTEXT_PACKAGE);
581
582 #ifdef ENABLE_DEBUG
583         /* Set up debugger */
584         g_log_set_default_handler (default_log_handler, NULL);
585 #endif
586
587         /* Setting up the bacon connection */
588         startup_timestamp = get_startup_timestamp ();
589         connection = bacon_message_connection_new ("empathy");
590         if (connection != NULL) {
591                 if (!bacon_message_connection_get_is_server (connection)) {
592                         gchar *message;
593
594                         if (accounts_dialog) {
595                                 DEBUG ("Showing accounts dialog from existing Empathy instance");
596
597                                 message = g_strdup ("accounts");
598
599                         } else {
600
601                                 DEBUG ("Activating existing instance");
602
603                                 message = g_strdup_printf ("%" G_GUINT32_FORMAT,
604                                                            startup_timestamp);
605                         }
606
607                         bacon_message_connection_send (connection, message);
608
609                         /* We never popup a window, so tell startup-notification
610                          * that we are done. */
611                         gdk_notify_startup_complete ();
612
613                         g_free (message);
614                         bacon_message_connection_free (connection);
615
616                         return EXIT_SUCCESS;
617                 }
618         } else {
619                 g_warning ("Cannot create the 'empathy' bacon connection.");
620         }
621
622         /* Take well-known name */
623         dbus_daemon = tp_dbus_daemon_dup (&error);
624         if (error == NULL) {
625                 if (!tp_dbus_daemon_request_name (dbus_daemon,
626                                                   "org.gnome.Empathy",
627                                                   TRUE, &error)) {
628                         DEBUG ("Failed to request well-known name: %s",
629                                error ? error->message : "no message");
630                         g_clear_error (&error);
631                 }
632                 g_object_unref (dbus_daemon);
633         } else {
634                 DEBUG ("Failed to dup dbus daemon: %s",
635                        error ? error->message : "no message");
636                 g_clear_error (&error);
637         }
638
639         if (accounts_dialog) {
640                 GtkWidget *dialog;
641
642                 dialog = empathy_accounts_dialog_show (NULL, NULL);
643                 g_signal_connect (dialog, "destroy",
644                                   G_CALLBACK (gtk_main_quit),
645                                   NULL);
646
647                 gtk_main ();
648                 return 0;
649         }
650
651         /* Setting up Idle */
652         idle = empathy_idle_dup_singleton ();
653         empathy_idle_set_auto_away (idle, TRUE);
654         use_nm_notify_cb (empathy_conf_get (), EMPATHY_PREFS_USE_NM, idle);
655         empathy_conf_notify_add (empathy_conf_get (), EMPATHY_PREFS_USE_NM,
656                                  use_nm_notify_cb, idle);
657
658         /* Autoconnect */
659         empathy_conf_get_bool (empathy_conf_get (),
660                                EMPATHY_PREFS_AUTOCONNECT,
661                                &autoconnect);
662         if (autoconnect && ! no_connect &&
663                 tp_connection_presence_type_cmp_availability (empathy_idle_get_state
664                         (idle), TP_CONNECTION_PRESENCE_TYPE_OFFLINE) <= 0) {
665                 empathy_idle_set_state (idle, TP_CONNECTION_PRESENCE_TYPE_AVAILABLE);
666         }
667
668         /* account management */
669         account_manager = empathy_account_manager_dup_singleton ();
670         g_signal_connect (account_manager, "notify::ready",
671                 G_CALLBACK (account_manager_ready_cb), NULL);
672
673         /* Setting up UI */
674         window = empathy_main_window_show ();
675         icon = empathy_status_icon_new (GTK_WINDOW (window), hide_contact_list);
676
677         if (connection) {
678                 /* We se the callback here because we need window */
679                 bacon_message_connection_set_callback (connection,
680                                                        on_bacon_message_received,
681                                                        window);
682         }
683
684         /* Handle channels */
685         dispatcher = empathy_dispatcher_dup_singleton ();
686         g_signal_connect (dispatcher, "dispatch", G_CALLBACK (dispatch_cb), NULL);
687
688         /* Logging */
689         log_manager = empathy_log_manager_dup_singleton ();
690         empathy_log_manager_observe (log_manager, dispatcher);
691
692         chatroom_manager = empathy_chatroom_manager_dup_singleton (NULL);
693         empathy_chatroom_manager_observe (chatroom_manager, dispatcher);
694
695         notify_init (_(PACKAGE_NAME));
696         /* Create the call factory */
697         call_factory = empathy_call_factory_initialise ();
698         g_signal_connect (G_OBJECT (call_factory), "new-call-handler",
699                 G_CALLBACK (new_call_handler_cb), NULL);
700         /* Create the FT factory */
701         ft_factory = empathy_ft_factory_dup_singleton ();
702         g_signal_connect (ft_factory, "new-ft-handler",
703                 G_CALLBACK (new_ft_handler_cb), NULL);
704         g_signal_connect (ft_factory, "new-incoming-transfer",
705                 G_CALLBACK (new_incoming_transfer_cb), NULL);
706
707         /* Location mananger */
708 #if HAVE_GEOCLUE
709         location_manager = empathy_location_manager_dup_singleton ();
710 #endif
711
712         gtk_main ();
713
714         empathy_idle_set_state (idle, TP_CONNECTION_PRESENCE_TYPE_OFFLINE);
715
716         g_object_unref (idle);
717         g_object_unref (icon);
718         g_object_unref (account_manager);
719         g_object_unref (log_manager);
720         g_object_unref (dispatcher);
721         g_object_unref (chatroom_manager);
722 #if HAVE_GEOCLUE
723         g_object_unref (location_manager);
724 #endif
725         g_object_unref (ft_factory);
726
727         notify_uninit ();
728
729         return EXIT_SUCCESS;
730 }