]> git.0d.be Git - empathy.git/blob - src/empathy.c
don't create the status icon if GNOME Shell is running
[empathy.git] / src / empathy.c
1 /*
2  * Copyright (C) 2007-2009 Collabora Ltd.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program 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  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public
15  * License along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA  02110-1301  USA
18  *
19  * Authors: Xavier Claessens <xclaesse@gmail.com>
20  */
21
22 #include <config.h>
23
24 #include <stdlib.h>
25 #include <errno.h>
26 #include <string.h>
27
28 #include <glib.h>
29 #include <glib/gstdio.h>
30 #include <glib/gi18n.h>
31 #include <gtk/gtk.h>
32 #include <gdk/gdkx.h>
33
34 #ifdef HAVE_LIBCHAMPLAIN
35 #include <clutter-gtk/clutter-gtk.h>
36 #endif
37
38 #include <libnotify/notify.h>
39
40 #include <telepathy-glib/account-manager.h>
41 #include <telepathy-glib/dbus.h>
42 #include <telepathy-glib/debug-sender.h>
43 #include <telepathy-glib/util.h>
44 #include <telepathy-glib/connection-manager.h>
45 #include <telepathy-glib/interfaces.h>
46
47 #include <telepathy-yell/telepathy-yell.h>
48
49 #include <telepathy-logger/log-manager.h>
50
51 #include <libempathy/empathy-presence-manager.h>
52 #include <libempathy/empathy-utils.h>
53 #include <libempathy/empathy-chatroom-manager.h>
54 #include <libempathy/empathy-account-settings.h>
55 #include <libempathy/empathy-connectivity.h>
56 #include <libempathy/empathy-connection-managers.h>
57 #include <libempathy/empathy-request-util.h>
58 #include <libempathy/empathy-ft-factory.h>
59 #include <libempathy/empathy-gsettings.h>
60 #include <libempathy/empathy-tp-chat.h>
61
62 #include <libempathy-gtk/empathy-ui-utils.h>
63 #include <libempathy-gtk/empathy-location-manager.h>
64 #include <libempathy-gtk/empathy-notify-manager.h>
65
66 #include "empathy-main-window.h"
67 #include "empathy-accounts-common.h"
68 #include "empathy-accounts-dialog.h"
69 #include "empathy-status-icon.h"
70 #include "empathy-ft-manager.h"
71 #include "empathy-notifications-approver.h"
72
73 #include "extensions/extensions.h"
74
75 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
76 #include <libempathy/empathy-debug.h>
77
78 #define EMPATHY_DBUS_NAME "org.gnome.Empathy"
79
80 #define EMPATHY_TYPE_APP (empathy_app_get_type ())
81 #define EMPATHY_APP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMPATHY_TYPE_APP, EmpathyApp))
82 #define EMPATHY_APP_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), EMPATHY_TYPE_APP, EmpathyAppClass))
83 #define EMPATHY_IS_EMPATHY_APP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMPATHY_TYPE_APP))
84 #define EMPATHY_IS_EMPATHY_APP_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), EMPATHY_TYPE_APP))
85 #define EMPATHY_APP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_APP, EmpathyAppClass))
86
87 typedef struct _EmpathyApp EmpathyApp;
88 typedef struct _EmpathyAppClass EmpathyAppClass;
89
90 enum
91 {
92   PROP_NO_CONNECT = 1,
93   PROP_START_HIDDEN
94 };
95
96 GType empathy_app_get_type (void);
97
98 struct _EmpathyAppClass
99 {
100   GtkApplicationClass parent_class;
101 };
102
103 struct _EmpathyApp
104 {
105   GtkApplication parent;
106
107   /* Properties */
108   gboolean no_connect;
109   gboolean start_hidden;
110   gboolean show_preferences;
111   gchar *preferences_tab;
112
113   gboolean activated;
114
115   GtkWidget *window;
116   EmpathyStatusIcon *icon;
117   TpAccountManager *account_manager;
118   TplLogManager *log_manager;
119   EmpathyChatroomManager *chatroom_manager;
120   EmpathyFTFactory  *ft_factory;
121   EmpathyPresenceManager *presence_mgr;
122   EmpathyConnectivity *connectivity;
123   GSettings *gsettings;
124   EmpathyNotificationsApprover *notifications_approver;
125 #ifdef HAVE_GEOCLUE
126   EmpathyLocationManager *location_manager;
127 #endif
128 #ifdef ENABLE_DEBUG
129   TpDebugSender *debug_sender;
130 #endif
131 };
132
133
134 G_DEFINE_TYPE(EmpathyApp, empathy_app, GTK_TYPE_APPLICATION)
135
136 static void
137 empathy_app_dispose (GObject *object)
138 {
139   EmpathyApp *self = EMPATHY_APP (object);
140   void (*dispose) (GObject *) =
141     G_OBJECT_CLASS (empathy_app_parent_class)->dispose;
142
143   if (self->presence_mgr != NULL)
144     {
145       empathy_presence_manager_set_state (self->presence_mgr,
146           TP_CONNECTION_PRESENCE_TYPE_OFFLINE);
147     }
148
149 #ifdef ENABLE_DEBUG
150   tp_clear_object (&self->debug_sender);
151 #endif
152
153   tp_clear_object (&self->presence_mgr);
154   tp_clear_object (&self->connectivity);
155   tp_clear_object (&self->icon);
156   tp_clear_object (&self->account_manager);
157   tp_clear_object (&self->log_manager);
158   tp_clear_object (&self->chatroom_manager);
159 #ifdef HAVE_GEOCLUE
160   tp_clear_object (&self->location_manager);
161 #endif
162   tp_clear_object (&self->ft_factory);
163   tp_clear_object (&self->gsettings);
164   tp_clear_object (&self->notifications_approver);
165
166   if (dispose != NULL)
167     dispose (object);
168 }
169
170 static void
171 empathy_app_finalize (GObject *object)
172 {
173   EmpathyApp *self = EMPATHY_APP (object);
174   void (*finalize) (GObject *) =
175     G_OBJECT_CLASS (empathy_app_parent_class)->finalize;
176
177   g_free (self->preferences_tab);
178
179   if (self->window != NULL)
180     gtk_widget_destroy (self->window);
181
182   if (finalize != NULL)
183     finalize (object);
184 }
185
186 static void account_manager_ready_cb (GObject *source_object,
187     GAsyncResult *result,
188     gpointer user_data);
189
190 static void
191 empathy_app_set_property (GObject *object,
192     guint prop_id,
193     const GValue *value,
194     GParamSpec *pspec)
195 {
196   EmpathyApp *self = EMPATHY_APP (object);
197
198   switch (prop_id)
199     {
200       case PROP_NO_CONNECT:
201         self->no_connect = g_value_get_boolean (value);
202         break;
203       case PROP_START_HIDDEN:
204         self->start_hidden = g_value_get_boolean (value);
205         break;
206       default:
207         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
208         break;
209     }
210 }
211
212 static void
213 new_incoming_transfer_cb (EmpathyFTFactory *factory,
214     EmpathyFTHandler *handler,
215     GError *error,
216     gpointer user_data)
217 {
218   if (error)
219     empathy_ft_manager_display_error (handler, error);
220   else
221     empathy_receive_file_with_file_chooser (handler);
222 }
223
224 static void
225 new_ft_handler_cb (EmpathyFTFactory *factory,
226     EmpathyFTHandler *handler,
227     GError *error,
228     gpointer user_data)
229 {
230   if (error)
231     empathy_ft_manager_display_error (handler, error);
232   else
233     empathy_ft_manager_add_handler (handler);
234
235   g_object_unref (handler);
236 }
237
238 static gboolean
239 empathy_app_local_command_line (GApplication *app,
240     gchar ***arguments,
241     gint *exit_status);
242
243 #define GNOME_SHELL_BUS_NAME "org.gnome.Shell"
244
245 static void
246 list_names_cb (TpDBusDaemon *bus_daemon,
247         const gchar * const *names,
248         const GError *error,
249         gpointer user_data,
250         GObject *weak_object)
251 {
252   EmpathyApp *self = (EmpathyApp *) weak_object;
253   gboolean shell_running = FALSE;
254   guint i;
255
256   if (error != NULL)
257       goto out;
258
259   for (i = 0; names[i] != NULL; i++)
260     {
261       if (!tp_strdiff (names[i], GNOME_SHELL_BUS_NAME))
262         {
263           shell_running = TRUE;
264           break;
265         }
266     }
267
268 out:
269   if (shell_running)
270     {
271       DEBUG ("GNOMES Shell is running, don't create status icon");
272     }
273   else
274     {
275       self->icon = empathy_status_icon_new (GTK_WINDOW (self->window),
276           self->start_hidden);
277     }
278 }
279
280 static int
281 empathy_app_command_line (GApplication *app,
282     GApplicationCommandLine *cmdline)
283 {
284   EmpathyApp *self = (EmpathyApp *) app;
285   gchar **args, **argv;
286   gint argc, exit_status, i;
287
288   args = g_application_command_line_get_arguments (cmdline, &argc);
289   /* We have to make an extra copy of the array, since g_option_context_parse()
290    * assumes that it can remove strings from the array without freeing them. */
291   argv = g_new (gchar*, argc + 1);
292   for (i = 0; i <= argc; i++)
293     argv[i] = args[i];
294
295   if (empathy_app_local_command_line (app, &argv, &exit_status))
296     DEBUG ("failed to parse command line!");
297
298   g_free (argv);
299   g_strfreev (args);
300
301   if (!self->activated)
302     {
303       GError *error = NULL;
304       TpDBusDaemon *dbus;
305
306       /* Create the FT factory */
307       self->ft_factory = empathy_ft_factory_dup_singleton ();
308       g_signal_connect (self->ft_factory, "new-ft-handler",
309           G_CALLBACK (new_ft_handler_cb), NULL);
310       g_signal_connect (self->ft_factory, "new-incoming-transfer",
311           G_CALLBACK (new_incoming_transfer_cb), NULL);
312
313       if (!empathy_ft_factory_register (self->ft_factory, &error))
314         {
315           g_warning ("Failed to register FileTransfer handler: %s",
316               error->message);
317           g_error_free (error);
318         }
319
320       g_application_hold (G_APPLICATION (app));
321       self->activated = TRUE;
322
323       /* Setting up UI */
324       self->window = empathy_main_window_dup ();
325
326       /* check if Shell is running */
327       dbus = tp_dbus_daemon_dup (&error);
328       g_assert_no_error (error);
329
330       tp_dbus_daemon_list_names (dbus, -1, list_names_cb,
331               self, NULL, G_OBJECT (self));
332
333       g_object_unref (dbus);
334
335       self->notifications_approver =
336         empathy_notifications_approver_dup_singleton ();
337     }
338   else
339     {
340       /* We're requested to show stuff again, disable the start hidden global in
341        * case the accounts wizard wants to pop up.
342        */
343       self->start_hidden = FALSE;
344     }
345
346   if (self->show_preferences)
347     empathy_main_window_show_preferences (EMPATHY_MAIN_WINDOW (self->window),
348         self->preferences_tab);
349
350   if (!self->start_hidden)
351     empathy_window_present (GTK_WINDOW (self->window));
352
353   /* Display the accounts dialog if needed */
354   tp_account_manager_prepare_async (self->account_manager, NULL,
355       account_manager_ready_cb, self);
356
357   return 0;
358 }
359
360 static gboolean
361 preferences_cb (const char *option_name,
362     const char *value,
363     gpointer data,
364     GError **error)
365 {
366   EmpathyApp *self = data;
367
368   self->show_preferences = TRUE;
369
370   g_free (self->preferences_tab);
371   self->preferences_tab = g_strdup (value);
372
373   return TRUE;
374 }
375
376 static gboolean
377 show_version_cb (const char *option_name,
378     const char *value,
379     gpointer data,
380     GError **error);
381
382 static gboolean
383 empathy_app_local_command_line (GApplication *app,
384     gchar ***arguments,
385     gint *exit_status)
386 {
387   EmpathyApp *self = (EmpathyApp *) app;
388   gint i;
389   gchar **argv;
390   gint argc = 0;
391   gboolean retval = FALSE;
392   GError *error = NULL;
393   gboolean no_connect = FALSE, start_hidden = FALSE;
394
395   GOptionContext *optcontext;
396   GOptionGroup *group;
397   GOptionEntry options[] = {
398       { "no-connect", 'n',
399         0, G_OPTION_ARG_NONE, &no_connect,
400         N_("Don't connect on startup"),
401         NULL },
402       { "start-hidden", 'h',
403         0, G_OPTION_ARG_NONE, &start_hidden,
404         N_("Don't display the contact list or any other dialogs on startup"),
405         NULL },
406       { "show-preferences", 'p',
407         G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, &preferences_cb,
408         NULL, NULL },
409       { "version", 'v',
410         G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version_cb,
411         NULL, NULL },
412       { NULL }
413   };
414
415   /* We create a group so that GOptionArgFuncs get the user data */
416   group = g_option_group_new ("empathy", NULL, NULL, app, NULL);
417   g_option_group_add_entries (group, options);
418
419   optcontext = g_option_context_new (N_("- Empathy IM Client"));
420   g_option_context_add_group (optcontext, gtk_get_option_group (TRUE));
421   g_option_context_set_main_group (optcontext, group);
422   g_option_context_set_translation_domain (optcontext, GETTEXT_PACKAGE);
423
424   argc = g_strv_length (*arguments);
425
426   /* We dup the args because g_option_context_parse() sets things to NULL,
427    * but we want to parse all the command line to the primary instance
428    * if necessary. */
429   argv = g_new (gchar*, argc + 1);
430   for (i = 0; i <= argc; i++)
431     argv[i] = (*arguments)[i];
432
433   if (!g_option_context_parse (optcontext, &argc, &argv, &error))
434     {
435       g_print ("%s\nRun '%s --help' to see a full list of available command "
436           "line options.\n",
437           error->message, argv[0]);
438       g_warning ("Error in empathy init: %s", error->message);
439
440       *exit_status = EXIT_FAILURE;
441       retval = TRUE;
442     }
443
444   g_free (argv);
445
446   g_option_context_free (optcontext);
447
448   self->no_connect = no_connect;
449   self->start_hidden = start_hidden;
450
451   return retval;
452 }
453
454 static void empathy_app_constructed (GObject *object);
455
456 static void
457 empathy_app_class_init (EmpathyAppClass *klass)
458 {
459   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
460   GApplicationClass *g_app_class = G_APPLICATION_CLASS (klass);
461   GParamSpec *spec;
462
463   gobject_class->set_property = empathy_app_set_property;
464   gobject_class->constructed = empathy_app_constructed;
465   gobject_class->dispose = empathy_app_dispose;
466   gobject_class->finalize = empathy_app_finalize;
467
468   g_app_class->command_line = empathy_app_command_line;
469   g_app_class->local_command_line = empathy_app_local_command_line;
470
471   spec = g_param_spec_boolean ("no-connect", "no connect",
472       "Don't connect on startup",
473       FALSE,
474       G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
475   g_object_class_install_property (gobject_class, PROP_NO_CONNECT, spec);
476
477   spec = g_param_spec_boolean ("start-hidden", "start hidden",
478       "Don't display the contact list or any other dialogs on startup",
479       FALSE,
480       G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
481   g_object_class_install_property (gobject_class, PROP_START_HIDDEN, spec);
482 }
483
484 static void
485 empathy_app_init (EmpathyApp *self)
486 {
487 }
488
489 static void
490 use_conn_notify_cb (GSettings *gsettings,
491     const gchar *key,
492     gpointer     user_data)
493 {
494   EmpathyConnectivity *connectivity = user_data;
495
496   empathy_connectivity_set_use_conn (connectivity,
497       g_settings_get_boolean (gsettings, key));
498 }
499
500 static void
501 migrate_config_to_xdg_dir (void)
502 {
503   gchar *xdg_dir, *old_dir, *xdg_filename, *old_filename;
504   int i;
505   GFile *xdg_file, *old_file;
506   static const gchar* filenames[] = {
507     "geometry.ini",
508     "irc-networks.xml",
509     "chatrooms.xml",
510     "contact-groups.xml",
511     "status-presets.xml",
512     "accels.txt",
513     NULL
514   };
515
516   xdg_dir = g_build_filename (g_get_user_config_dir (), PACKAGE_NAME, NULL);
517   if (g_file_test (xdg_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
518     {
519       /* xdg config dir already exists */
520       g_free (xdg_dir);
521       return;
522     }
523
524   old_dir = g_build_filename (g_get_home_dir (), ".gnome2",
525       PACKAGE_NAME, NULL);
526   if (!g_file_test (old_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
527     {
528       /* old config dir didn't exist */
529       g_free (xdg_dir);
530       g_free (old_dir);
531       return;
532     }
533
534   if (g_mkdir_with_parents (xdg_dir, (S_IRUSR | S_IWUSR | S_IXUSR)) == -1)
535     {
536       DEBUG ("Failed to create configuration directory; aborting migration");
537       g_free (xdg_dir);
538       g_free (old_dir);
539       return;
540     }
541
542   for (i = 0; filenames[i]; i++)
543     {
544       old_filename = g_build_filename (old_dir, filenames[i], NULL);
545       if (!g_file_test (old_filename, G_FILE_TEST_EXISTS))
546         {
547           g_free (old_filename);
548           continue;
549         }
550       xdg_filename = g_build_filename (xdg_dir, filenames[i], NULL);
551       old_file = g_file_new_for_path (old_filename);
552       xdg_file = g_file_new_for_path (xdg_filename);
553
554       if (!g_file_move (old_file, xdg_file, G_FILE_COPY_NONE,
555           NULL, NULL, NULL, NULL))
556         DEBUG ("Failed to migrate %s", filenames[i]);
557
558       g_free (old_filename);
559       g_free (xdg_filename);
560       g_object_unref (old_file);
561       g_object_unref (xdg_file);
562     }
563
564   g_free (xdg_dir);
565   g_free (old_dir);
566 }
567
568 static void
569 show_accounts_ui (EmpathyApp *self,
570     GdkScreen *screen,
571     gboolean if_needed)
572 {
573   empathy_accounts_dialog_show_application (screen,
574       NULL, if_needed, self->start_hidden);
575 }
576
577 static gboolean
578 show_version_cb (const char *option_name,
579     const char *value,
580     gpointer data,
581     GError **error)
582 {
583   g_print ("%s\n", PACKAGE_STRING);
584
585   exit (EXIT_SUCCESS);
586 }
587
588 static void
589 account_manager_ready_cb (GObject *source_object,
590     GAsyncResult *result,
591     gpointer user_data)
592 {
593   TpAccountManager *manager = TP_ACCOUNT_MANAGER (source_object);
594   EmpathyApp *self = user_data;
595   GError *error = NULL;
596   TpConnectionPresenceType presence;
597
598   if (!tp_account_manager_prepare_finish (manager, result, &error))
599     {
600       GtkWidget *dialog;
601
602       DEBUG ("Failed to prepare account manager: %s", error->message);
603
604       dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL,
605           GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
606           _("Error contacting the Account Manager"));
607       gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
608           _("There was an error while trying to connect to the Telepathy "
609             "Account Manager. The error was:\n\n%s"),
610           error->message);
611
612       gtk_dialog_run (GTK_DIALOG (dialog));
613       gtk_widget_destroy (dialog);
614
615       g_error_free (error);
616       return;
617     }
618
619   /* Autoconnect */
620   presence = tp_account_manager_get_most_available_presence (manager, NULL,
621       NULL);
622
623   if (g_settings_get_boolean (self->gsettings, EMPATHY_PREFS_AUTOCONNECT) &&
624       !self->no_connect &&
625       tp_connection_presence_type_cmp_availability
626           (presence, TP_CONNECTION_PRESENCE_TYPE_OFFLINE)
627             <= 0)
628       /* if current state is Offline, then put it online */
629       empathy_presence_manager_set_state (self->presence_mgr,
630           TP_CONNECTION_PRESENCE_TYPE_AVAILABLE);
631
632   /* Pop up the accounts dialog if we don't have any account */
633   if (!empathy_accounts_has_accounts (manager))
634     show_accounts_ui (self, gdk_screen_get_default (), TRUE);
635 }
636
637 static void
638 account_join_chatrooms (TpAccount *account,
639   EmpathyChatroomManager *chatroom_manager)
640 {
641   TpConnection *conn;
642   GList *chatrooms, *p;
643
644   if (tp_account_get_connection_status (account, NULL) !=
645       TP_CONNECTION_STATUS_CONNECTED)
646     return;
647
648   /* If we're connected we should have a connection */
649   conn = tp_account_get_connection (account);
650   g_return_if_fail (conn != NULL);
651
652   chatrooms = empathy_chatroom_manager_get_chatrooms (
653           chatroom_manager, account);
654
655   for (p = chatrooms; p != NULL; p = p->next)
656     {
657       EmpathyChatroom *room = EMPATHY_CHATROOM (p->data);
658
659       if (!empathy_chatroom_get_auto_connect (room))
660         continue;
661
662       empathy_join_muc (account, empathy_chatroom_get_room (room),
663         TP_USER_ACTION_TIME_NOT_USER_ACTION);
664     }
665   g_list_free (chatrooms);
666 }
667
668 static void
669 account_status_changed_cb (TpAccount *account,
670     guint old_status,
671     guint new_status,
672     guint reason,
673     gchar *dbus_error_name,
674     GHashTable *details,
675     EmpathyChatroomManager *manager)
676 {
677   account_join_chatrooms (account, manager);
678 }
679
680 static void
681 account_manager_chatroom_ready_cb (GObject *source_object,
682     GAsyncResult *result,
683     gpointer user_data)
684 {
685   TpAccountManager *account_manager = TP_ACCOUNT_MANAGER (source_object);
686   EmpathyChatroomManager *chatroom_manager = user_data;
687   GList *accounts, *l;
688   GError *error = NULL;
689
690   if (!tp_account_manager_prepare_finish (account_manager, result, &error))
691     {
692       DEBUG ("Failed to prepare account manager: %s", error->message);
693       g_error_free (error);
694       return;
695     }
696
697   accounts = tp_account_manager_get_valid_accounts (account_manager);
698
699   for (l = accounts; l != NULL; l = g_list_next (l))
700     {
701       TpAccount *account = TP_ACCOUNT (l->data);
702
703       /* Try to join all rooms if we're connected */
704       account_join_chatrooms (account, chatroom_manager);
705
706       /* And/or join them on (re)connection */
707       tp_g_signal_connect_object (account, "status-changed",
708         G_CALLBACK (account_status_changed_cb), chatroom_manager, 0);
709     }
710   g_list_free (accounts);
711 }
712
713 static void
714 chatroom_manager_ready_cb (EmpathyChatroomManager *chatroom_manager,
715     GParamSpec *pspec,
716     gpointer user_data)
717 {
718   TpAccountManager *account_manager = user_data;
719
720   tp_account_manager_prepare_async (account_manager, NULL,
721       account_manager_chatroom_ready_cb, chatroom_manager);
722 }
723
724 static void
725 empathy_presence_manager_set_auto_away_cb (GSettings *gsettings,
726                                 const gchar *key,
727                                 gpointer user_data)
728 {
729         EmpathyPresenceManager *presence_mgr = user_data;
730
731         empathy_presence_manager_set_auto_away (presence_mgr,
732       g_settings_get_boolean (gsettings, key));
733 }
734
735 static void
736 empathy_app_constructed (GObject *object)
737 {
738   EmpathyApp *self = (EmpathyApp *) object;
739   gboolean chatroom_manager_ready;
740   gboolean autoaway;
741
742   g_set_application_name (_(PACKAGE_NAME));
743
744   gtk_window_set_default_icon_name ("empathy");
745   textdomain (GETTEXT_PACKAGE);
746
747 #ifdef ENABLE_DEBUG
748   /* Set up debug sender */
749   self->debug_sender = tp_debug_sender_dup ();
750   g_log_set_default_handler (tp_debug_sender_log_handler, G_LOG_DOMAIN);
751 #endif
752
753   notify_init (_(PACKAGE_NAME));
754
755   /* Setting up Idle */
756   self->presence_mgr = empathy_presence_manager_dup_singleton ();
757
758   self->gsettings = g_settings_new (EMPATHY_PREFS_SCHEMA);
759   autoaway = g_settings_get_boolean (self->gsettings, EMPATHY_PREFS_AUTOAWAY);
760
761   g_signal_connect (self->gsettings,
762       "changed::" EMPATHY_PREFS_AUTOAWAY,
763       G_CALLBACK (empathy_presence_manager_set_auto_away_cb),
764       self->presence_mgr);
765
766   empathy_presence_manager_set_auto_away (self->presence_mgr, autoaway);
767
768   /* Setting up Connectivity */
769   self->connectivity = empathy_connectivity_dup_singleton ();
770   use_conn_notify_cb (self->gsettings, EMPATHY_PREFS_USE_CONN,
771       self->connectivity);
772   g_signal_connect (self->gsettings,
773       "changed::" EMPATHY_PREFS_USE_CONN,
774       G_CALLBACK (use_conn_notify_cb), self->connectivity);
775
776   /* account management */
777   self->account_manager = tp_account_manager_dup ();
778   tp_account_manager_prepare_async (self->account_manager, NULL,
779       account_manager_ready_cb, self);
780
781   migrate_config_to_xdg_dir ();
782
783   /* Logging */
784   self->log_manager = tpl_log_manager_dup_singleton ();
785
786   self->chatroom_manager = empathy_chatroom_manager_dup_singleton (NULL);
787
788   g_object_get (self->chatroom_manager, "ready", &chatroom_manager_ready, NULL);
789   if (!chatroom_manager_ready)
790     {
791       g_signal_connect (G_OBJECT (self->chatroom_manager), "notify::ready",
792           G_CALLBACK (chatroom_manager_ready_cb), self->account_manager);
793     }
794   else
795     {
796       chatroom_manager_ready_cb (self->chatroom_manager, NULL,
797           self->account_manager);
798     }
799
800   /* Location mananger */
801 #ifdef HAVE_GEOCLUE
802   self->location_manager = empathy_location_manager_dup_singleton ();
803 #endif
804
805   self->activated = FALSE;
806   self->ft_factory = NULL;
807   self->window = NULL;
808 }
809
810 int
811 main (int argc, char *argv[])
812 {
813   EmpathyApp *app;
814   gint retval;
815
816   g_thread_init (NULL);
817   g_type_init ();
818
819 #ifdef HAVE_LIBCHAMPLAIN
820   gtk_clutter_init (&argc, &argv);
821 #endif
822
823   g_type_init ();
824   tpy_cli_init ();
825   empathy_init ();
826   gtk_init (&argc, &argv);
827   empathy_gtk_init ();
828
829   app = g_object_new (EMPATHY_TYPE_APP,
830       "application-id", EMPATHY_DBUS_NAME,
831       "flags", G_APPLICATION_HANDLES_COMMAND_LINE,
832       NULL);
833
834   retval = g_application_run (G_APPLICATION (app), argc, argv);
835
836   notify_uninit ();
837   xmlCleanupParser ();
838
839   g_object_unref (app);
840
841   return retval;
842 }