]> git.0d.be Git - empathy.git/blobdiff - src/empathy.c
Merge branch 'debugger'
[empathy.git] / src / empathy.c
index 242f946a1c568544aaecd185338546828a16371e..85124d1e9156056ed813130780a670dd6bd61552 100644 (file)
@@ -14,9 +14,9 @@
  *
  * You should have received a copy of the GNU General Public
  * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- * 
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA  02110-1301  USA
+ *
  * Authors: Xavier Claessens <xclaesse@gmail.com>
  */
 
 
 #include <stdlib.h>
 #include <errno.h>
+#include <string.h>
 
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 #include <gdk/gdkx.h>
 
+#if HAVE_LIBCHAMPLAIN
+#include <clutter-gtk/gtk-clutter-embed.h>
+#endif
+
 #include <libebook/e-book.h>
+#include <libnotify/notify.h>
 
+#include <telepathy-glib/dbus.h>
 #include <telepathy-glib/util.h>
 #include <libmissioncontrol/mc-account.h>
 #include <libmissioncontrol/mission-control.h>
 
 #include <libempathy/empathy-idle.h>
 #include <libempathy/empathy-utils.h>
+#include <libempathy/empathy-call-factory.h>
+#include <libempathy/empathy-chatroom-manager.h>
+#include <libempathy/empathy-account-manager.h>
+#include <libempathy/empathy-debugger.h>
 #include <libempathy/empathy-dispatcher.h>
+#include <libempathy/empathy-dispatch-operation.h>
+#include <libempathy/empathy-log-manager.h>
+#include <libempathy/empathy-ft-factory.h>
 #include <libempathy/empathy-tp-chat.h>
 #include <libempathy/empathy-tp-call.h>
 
 #include <libempathy-gtk/empathy-conf.h>
+#include <libempathy-gtk/empathy-ui-utils.h>
+#include <libempathy-gtk/empathy-location-manager.h>
 
+#include "empathy-accounts-dialog.h"
 #include "empathy-main-window.h"
 #include "empathy-status-icon.h"
 #include "empathy-call-window.h"
 #include "empathy-chat-window.h"
+#include "empathy-ft-manager.h"
 #include "bacon-message-connection.h"
 
+#include "extensions/extensions.h"
+
 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
 #include <libempathy/empathy-debug.h>
 
+#include <gst/gst.h>
+
 static BaconMessageConnection *connection = NULL;
 
 static void
-dispatch_channel_cb (EmpathyDispatcher *dispatcher,
-                    TpChannel         *channel,
-                    gpointer           user_data)
+dispatch_cb (EmpathyDispatcher *dispatcher,
+            EmpathyDispatchOperation *operation,
+            gpointer           user_data)
 {
-       gchar *channel_type;
+       GQuark channel_type;
+
+       channel_type = empathy_dispatch_operation_get_channel_type_id (operation);
 
-       g_object_get (channel, "channel-type", &channel_type, NULL);
-       if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TEXT)) {
+       if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_TEXT) {
                EmpathyTpChat *tp_chat;
                EmpathyChat   *chat = NULL;
                const gchar   *id;
 
-               tp_chat = empathy_tp_chat_new (channel);
-               empathy_run_until_ready (tp_chat);
+               tp_chat = EMPATHY_TP_CHAT (
+                       empathy_dispatch_operation_get_channel_wrapper (operation));
 
                id = empathy_tp_chat_get_id (tp_chat);
                if (!id) {
@@ -82,10 +105,16 @@ dispatch_channel_cb (EmpathyDispatcher *dispatcher,
                }
 
                if (id) {
+                       EmpathyAccountManager *manager;
+                       TpConnection *connection;
                        McAccount *account;
 
-                       account = empathy_tp_chat_get_account (tp_chat);
+                       manager = empathy_account_manager_dup_singleton ();
+                       connection = empathy_tp_chat_get_connection (tp_chat);
+                       account = empathy_account_manager_get_account (manager,
+                                                                      connection);
                        chat = empathy_chat_window_find_chat (account, id);
+                       g_object_unref (manager);
                }
 
                if (chat) {
@@ -95,14 +124,25 @@ dispatch_channel_cb (EmpathyDispatcher *dispatcher,
                }
 
                empathy_chat_window_present_chat (chat);
-               g_object_unref (tp_chat);
-       }
-       else if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA)) {
-               EmpathyTpCall *tp_call;
 
-               tp_call = empathy_tp_call_new (channel);
-               empathy_call_window_new (tp_call);
-               g_object_unref (tp_call);
+               empathy_dispatch_operation_claim (operation);
+       } else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA) {
+               EmpathyCallFactory *factory;
+
+               factory = empathy_call_factory_get ();
+               empathy_call_factory_claim_channel (factory, operation);
+       } else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_FILE_TRANSFER) {
+               EmpathyFTFactory *factory;
+
+               factory = empathy_ft_factory_dup_singleton ();
+
+               /* if the operation is not incoming, don't claim it,
+                * as it might have been triggered by another client, and
+                * we are observing it.
+                */
+               if (empathy_dispatch_operation_is_incoming (operation)) {
+                       empathy_ft_factory_claim_channel (factory, operation);
+               }
        }
 }
 
@@ -123,46 +163,46 @@ operation_error_cb (MissionControl *mc,
 
        switch (error_code) {
        case MC_DISCONNECTED_ERROR:
-               message = _("Disconnected");
+               message = "Disconnected";
                break;
        case MC_INVALID_HANDLE_ERROR:
-               message = _("Invalid handle");
+               message = "Invalid handle";
                break;
        case MC_NO_MATCHING_CONNECTION_ERROR:
-               message = _("No matching connection");
+               message = "No matching connection";
                break;
        case MC_INVALID_ACCOUNT_ERROR:
-               message = _("Invalid account");
+               message = "Invalid account";
                break;
        case MC_PRESENCE_FAILURE_ERROR:
-               message = _("Presence failure");
+               message = "Presence failure";
                break;
        case MC_NO_ACCOUNTS_ERROR:
-               message = _("No accounts");
+               message = "No accounts";
                break;
        case MC_NETWORK_ERROR:
-               message = _("Network error");
+               message = "Network error";
                break;
        case MC_CONTACT_DOES_NOT_SUPPORT_VOICE_ERROR:
-               message = _("Contact does not support voice");
+               message = "Contact does not support voice";
                break;
        case MC_LOWMEM_ERROR:
-               message = _("Lowmem");
+               message = "Lowmem";
                break;
        case MC_CHANNEL_REQUEST_GENERIC_ERROR:
-               message = _("Channel request generic error");
+               message = "Channel request generic error";
                break;
        case MC_CHANNEL_BANNED_ERROR:
-               message = _("Channel banned");
+               message = "Channel banned";
                break;
        case MC_CHANNEL_FULL_ERROR:
-               message = _("Channel full");
+               message = "Channel full";
                break;
        case MC_CHANNEL_INVITE_ONLY_ERROR:
-               message = _("Channel invite only");
+               message = "Channel invite only";
                break;
        default:
-               message = _("Unknown error code");
+               message = "Unknown error code";
        }
 
        DEBUG ("Error during operation %d: %s", operation_id, message);
@@ -199,7 +239,7 @@ create_salut_account (void)
        GError     *error = NULL;
 
        /* Check if we already created a salut account */
-       empathy_conf_get_bool (empathy_conf_get(),
+       empathy_conf_get_bool (empathy_conf_get (),
                               EMPATHY_PREFS_SALUT_ACCOUNT_CREATED,
                               &salut_created);
        if (salut_created) {
@@ -210,6 +250,10 @@ create_salut_account (void)
 
        /* Check if the salut CM is installed */
        profile = mc_profile_lookup ("salut");
+       if (!profile) {
+               DEBUG ("No salut profile");
+               return;
+       }
        protocol = mc_profile_get_protocol (profile);
        if (!protocol) {
                DEBUG ("Salut not installed");
@@ -242,13 +286,13 @@ create_salut_account (void)
 
        account = mc_account_create (profile);
        mc_account_set_display_name (account, _("People nearby"));
-       
+
        nickname = e_contact_get (contact, E_CONTACT_NICKNAME);
        first_name = e_contact_get (contact, E_CONTACT_GIVEN_NAME);
        last_name = e_contact_get (contact, E_CONTACT_FAMILY_NAME);
        email = e_contact_get (contact, E_CONTACT_EMAIL_1);
        jid = e_contact_get (contact, E_CONTACT_IM_JABBER_HOME_1);
-       
+
        if (!tp_strdiff (nickname, "nickname")) {
                g_free (nickname);
                nickname = NULL;
@@ -278,7 +322,7 @@ create_salut_account (void)
 /* The code that handles single-instance and startup notification is
  * copied from gedit.
  *
- * Copyright (C) 2005 - Paolo Maggi 
+ * Copyright (C) 2005 - Paolo Maggi
  */
 static void
 on_bacon_message_received (const char *message,
@@ -292,25 +336,30 @@ on_bacon_message_received (const char *message,
        DEBUG ("Other instance launched, presenting the main window. message='%s'",
                message);
 
-       startup_timestamp = atoi (message);
-
-       /* Set the proper interaction time on the window.
-        * Fall back to roundtripping to the X server when we
-        * don't have the timestamp, e.g. when launched from
-        * terminal. We also need to make sure that the window
-        * has been realized otherwise it will not work. lame. */
-       if (startup_timestamp == 0) {
-               /* Work if launched from the terminal */
-               DEBUG ("Using X server timestamp as a fallback");
+       if (strcmp (message, "accounts") == 0) {
+               /* accounts dialog requested */
+               empathy_accounts_dialog_show (GTK_WINDOW (window), NULL);
+       } else {
+               startup_timestamp = atoi (message);
+
+               /* Set the proper interaction time on the window.
+                * Fall back to roundtripping to the X server when we
+                * don't have the timestamp, e.g. when launched from
+                * terminal. We also need to make sure that the window
+                * has been realized otherwise it will not work. lame. */
+               if (startup_timestamp == 0) {
+                       /* Work if launched from the terminal */
+                       DEBUG ("Using X server timestamp as a fallback");
+
+                       if (!GTK_WIDGET_REALIZED (window)) {
+                               gtk_widget_realize (GTK_WIDGET (window));
+                       }
 
-               if (!GTK_WIDGET_REALIZED (window)) {
-                       gtk_widget_realize (GTK_WIDGET (window));
+                       startup_timestamp = gdk_x11_get_server_time (window->window);
                }
 
-               startup_timestamp = gdk_x11_get_server_time (window->window);
+               gtk_window_present_with_time (GTK_WINDOW (window), startup_timestamp);
        }
-
-       gtk_window_present_with_time (GTK_WINDOW (window), startup_timestamp);
 }
 
 static guint32
@@ -351,61 +400,171 @@ get_startup_timestamp ()
        return (retval > 0) ? retval : 0;
 }
 
+static gboolean
+show_version_cb (const char *option_name,
+                 const char *value,
+                 gpointer data,
+                 GError **error)
+{
+       g_print ("%s\n", PACKAGE_STRING);
+
+       exit (EXIT_SUCCESS);
+
+       return FALSE;
+}
+
+static void
+new_incoming_transfer_cb (EmpathyFTFactory *factory,
+                         EmpathyFTHandler *handler,
+                          GError *error,
+                         gpointer user_data)
+{
+       if (error) {
+               empathy_ft_manager_display_error (handler, error);
+       } else {
+               empathy_receive_file_with_file_chooser (handler);
+       }
+}
+
+static void
+new_ft_handler_cb (EmpathyFTFactory *factory,
+                  EmpathyFTHandler *handler,
+                   GError *error,
+                  gpointer user_data)
+{
+       if (error) {
+               empathy_ft_manager_display_error (handler, error);
+       } else {
+               empathy_ft_manager_add_handler (handler);
+       }
+
+       g_object_unref (handler);
+}
+
+static void
+new_call_handler_cb (EmpathyCallFactory *factory, EmpathyCallHandler *handler,
+       gboolean outgoing, gpointer user_data)
+{
+       EmpathyCallWindow *window;
+
+       window = empathy_call_window_new (handler);
+       gtk_widget_show (GTK_WIDGET (window));
+}
+
+#ifdef ENABLE_DEBUG
+static void
+default_log_handler (const gchar *log_domain,
+    GLogLevelFlags log_level,
+    const gchar *message,
+    gpointer user_data)
+{
+       g_log_default_handler (log_domain, log_level, message, NULL);
+
+       /* G_LOG_DOMAIN = "empathy". No need to send empathy messages to the
+        * debugger as they already have in empathy_debug. */
+       if (log_level != G_LOG_LEVEL_DEBUG
+           || tp_strdiff (log_domain, G_LOG_DOMAIN)) {
+               EmpathyDebugger *dbg;
+               GTimeVal now;
+
+               dbg = empathy_debugger_get_singleton ();
+               g_get_current_time (&now);
+
+               empathy_debugger_add_message (dbg, &now, log_domain,
+                                             log_level, message);
+       }
+}
+#endif /* ENABLE_DEBUG */
+
 int
 main (int argc, char *argv[])
 {
        guint32            startup_timestamp;
+#if HAVE_GEOCLUE
+       EmpathyLocationManager *location_manager = NULL;
+#endif
        EmpathyStatusIcon *icon;
        EmpathyDispatcher *dispatcher;
+       EmpathyLogManager *log_manager;
+       EmpathyChatroomManager *chatroom_manager;
+       EmpathyCallFactory *call_factory;
+       EmpathyFTFactory  *ft_factory;
        GtkWidget         *window;
        MissionControl    *mc;
        EmpathyIdle       *idle;
        gboolean           autoconnect = TRUE;
-       gboolean           no_connect = FALSE; 
+       gboolean           no_connect = FALSE;
+       gboolean           hide_contact_list = FALSE;
+       gboolean           accounts_dialog = FALSE;
        GError            *error = NULL;
+       TpDBusDaemon      *dbus_daemon;
        GOptionEntry       options[] = {
                { "no-connect", 'n',
                  0, G_OPTION_ARG_NONE, &no_connect,
                  N_("Don't connect on startup"),
                  NULL },
+               { "hide-contact-list", 'h',
+                 0, G_OPTION_ARG_NONE, &hide_contact_list,
+                 N_("Don't show the contact list on startup"),
+                 NULL },
+               { "accounts", 'a',
+                 0, G_OPTION_ARG_NONE, &accounts_dialog,
+                 N_("Show the accounts dialog"),
+                 NULL },
+               { "version", 'v',
+                 G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version_cb, NULL, NULL },
                { NULL }
        };
 
-       bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-       bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
-       textdomain (GETTEXT_PACKAGE);
-
-       startup_timestamp = get_startup_timestamp ();
+       /* Init */
+       g_thread_init (NULL);
+       empathy_init ();
 
        if (!gtk_init_with_args (&argc, &argv,
-                                _("- Empathy Instant Messenger"),
+                                N_("- Empathy Instant Messenger"),
                                 options, GETTEXT_PACKAGE, &error)) {
-               g_warning ("Error in gtk init: %s", error->message);
+               g_warning ("Error in empathy init: %s", error->message);
                return EXIT_FAILURE;
        }
 
-       if (g_getenv ("EMPATHY_TIMING") != NULL) {
-               g_log_set_default_handler (tp_debug_timestamped_log_handler, NULL);
-       }
-       empathy_debug_set_flags (g_getenv ("EMPATHY_DEBUG"));
-       tp_debug_divert_messages (g_getenv ("EMPATHY_LOGFILE"));
+       empathy_gtk_init ();
+       g_set_application_name (_(PACKAGE_NAME));
+       g_setenv ("PULSE_PROP_media.role", "phone", TRUE);
 
-       g_set_application_name (PACKAGE_NAME);
+       gst_init (&argc, &argv);
+
+#if HAVE_LIBCHAMPLAIN
+       gtk_clutter_init (&argc, &argv);
+#endif
 
        gtk_window_set_default_icon_name ("empathy");
-       gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
-                                          PKGDATADIR G_DIR_SEPARATOR_S "icons");
+       textdomain (GETTEXT_PACKAGE);
+
+#ifdef ENABLE_DEBUG
+       /* Set up debugger */
+       g_log_set_default_handler (default_log_handler, NULL);
+#endif
 
         /* Setting up the bacon connection */
+       startup_timestamp = get_startup_timestamp ();
        connection = bacon_message_connection_new ("empathy");
        if (connection != NULL) {
                if (!bacon_message_connection_get_is_server (connection)) {
                        gchar *message;
 
-                       DEBUG ("Activating existing instance");
+                       if (accounts_dialog) {
+                               DEBUG ("Showing accounts dialog from existing Empathy instance");
+
+                               message = g_strdup ("accounts");
+
+                       } else {
+
+                               DEBUG ("Activating existing instance");
+
+                               message = g_strdup_printf ("%" G_GUINT32_FORMAT,
+                                                          startup_timestamp);
+                       }
 
-                       message = g_strdup_printf ("%" G_GUINT32_FORMAT,
-                                                  startup_timestamp);
                        bacon_message_connection_send (connection, message);
 
                        /* We never popup a window, so tell startup-notification
@@ -421,8 +580,25 @@ main (int argc, char *argv[])
                g_warning ("Cannot create the 'empathy' bacon connection.");
        }
 
+       /* Take well-known name */
+       dbus_daemon = tp_dbus_daemon_dup (&error);
+       if (error == NULL) {
+               if (!tp_dbus_daemon_request_name (dbus_daemon,
+                                                 "org.gnome.Empathy",
+                                                 TRUE, &error)) {
+                       DEBUG ("Failed to request well-known name: %s",
+                              error ? error->message : "no message");
+                       g_clear_error (&error);
+               }
+               g_object_unref (dbus_daemon);
+       } else {
+               DEBUG ("Failed to dup dbus daemon: %s",
+                      error ? error->message : "no message");
+               g_clear_error (&error);
+       }
+
        /* Setting up MC */
-       mc = empathy_mission_control_new ();
+       mc = empathy_mission_control_dup_singleton ();
        g_signal_connect (mc, "ServiceEnded",
                          G_CALLBACK (service_ended_cb),
                          NULL);
@@ -430,27 +606,40 @@ main (int argc, char *argv[])
                          G_CALLBACK (operation_error_cb),
                          NULL);
 
+       if (accounts_dialog) {
+               GtkWidget *dialog;
+
+               dialog = empathy_accounts_dialog_show (NULL, NULL);
+               g_signal_connect (dialog, "destroy",
+                                 G_CALLBACK (gtk_main_quit),
+                                 NULL);
+
+               gtk_main ();
+               return 0;
+       }
+
        /* Setting up Idle */
-       idle = empathy_idle_new ();
+       idle = empathy_idle_dup_singleton ();
        empathy_idle_set_auto_away (idle, TRUE);
        use_nm_notify_cb (empathy_conf_get (), EMPATHY_PREFS_USE_NM, idle);
        empathy_conf_notify_add (empathy_conf_get (), EMPATHY_PREFS_USE_NM,
                                 use_nm_notify_cb, idle);
 
        /* Autoconnect */
-       empathy_conf_get_bool (empathy_conf_get(),
+       empathy_conf_get_bool (empathy_conf_get (),
                               EMPATHY_PREFS_AUTOCONNECT,
                               &autoconnect);
        if (autoconnect && ! no_connect &&
-           empathy_idle_get_state (idle) <= MC_PRESENCE_OFFLINE) {
+               tp_connection_presence_type_cmp_availability (empathy_idle_get_state
+                       (idle), TP_CONNECTION_PRESENCE_TYPE_OFFLINE) <= 0) {
                empathy_idle_set_state (idle, MC_PRESENCE_AVAILABLE);
        }
-       
+
        create_salut_account ();
 
        /* Setting up UI */
        window = empathy_main_window_show ();
-       icon = empathy_status_icon_new (GTK_WINDOW (window));
+       icon = empathy_status_icon_new (GTK_WINDOW (window), hide_contact_list);
 
        if (connection) {
                /* We se the callback here because we need window */
@@ -460,19 +649,49 @@ main (int argc, char *argv[])
        }
 
        /* Handle channels */
-       dispatcher = empathy_dispatcher_new ();
-       g_signal_connect (dispatcher, "dispatch-channel",
-                         G_CALLBACK (dispatch_channel_cb),
-                         NULL);
+       dispatcher = empathy_dispatcher_dup_singleton ();
+       g_signal_connect (dispatcher, "dispatch", G_CALLBACK (dispatch_cb), NULL);
+
+       /* Logging */
+       log_manager = empathy_log_manager_dup_singleton ();
+       empathy_log_manager_observe (log_manager, dispatcher);
+
+       chatroom_manager = empathy_chatroom_manager_dup_singleton (NULL);
+       empathy_chatroom_manager_observe (chatroom_manager, dispatcher);
+
+       notify_init (_(PACKAGE_NAME));
+       /* Create the call factory */
+       call_factory = empathy_call_factory_initialise ();
+       g_signal_connect (G_OBJECT (call_factory), "new-call-handler",
+               G_CALLBACK (new_call_handler_cb), NULL);
+       /* Create the FT factory */
+       ft_factory = empathy_ft_factory_dup_singleton ();
+       g_signal_connect (ft_factory, "new-ft-handler",
+               G_CALLBACK (new_ft_handler_cb), NULL);
+       g_signal_connect (ft_factory, "new-incoming-transfer",
+               G_CALLBACK (new_incoming_transfer_cb), NULL);
+
+       /* Location mananger */
+#if HAVE_GEOCLUE
+       location_manager = empathy_location_manager_dup_singleton ();
+#endif
 
        gtk_main ();
 
-       empathy_idle_set_state (idle, MC_PRESENCE_OFFLINE);
+       empathy_idle_set_state (idle, TP_CONNECTION_PRESENCE_TYPE_OFFLINE);
 
        g_object_unref (mc);
        g_object_unref (idle);
        g_object_unref (icon);
+       g_object_unref (log_manager);
        g_object_unref (dispatcher);
+       g_object_unref (chatroom_manager);
+#if HAVE_GEOCLUE
+       g_object_unref (location_manager);
+#endif
+       g_object_unref (ft_factory);
+
+       notify_uninit ();
 
        return EXIT_SUCCESS;
 }