#include <string.h>
#include <glib.h>
+#include <glib/gstdio.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
-#include <unique/unique.h>
-#if HAVE_LIBCHAMPLAIN
+#ifdef HAVE_LIBCHAMPLAIN
#include <clutter-gtk/clutter-gtk.h>
#endif
#include <telepathy-glib/connection-manager.h>
#include <telepathy-glib/interfaces.h>
-#ifdef ENABLE_TPL
#include <telepathy-logger/log-manager.h>
-#include <telepathy-logger/log-store-empathy.h>
-#else
-#include <libempathy/empathy-log-manager.h>
-#endif /* ENABLE_TPL */
-#include <libempathy/empathy-idle.h>
+#include <libempathy/empathy-client-factory.h>
+#include <libempathy/empathy-connection-aggregator.h>
+#include <libempathy/empathy-presence-manager.h>
#include <libempathy/empathy-utils.h>
-#include <libempathy/empathy-call-factory.h>
#include <libempathy/empathy-chatroom-manager.h>
#include <libempathy/empathy-account-settings.h>
#include <libempathy/empathy-connectivity.h>
#include <libempathy/empathy-connection-managers.h>
-#include <libempathy/empathy-dispatcher.h>
-#include <libempathy/empathy-dispatch-operation.h>
+#include <libempathy/empathy-request-util.h>
#include <libempathy/empathy-ft-factory.h>
+#include <libempathy/empathy-gsettings.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 <libempathy-gtk/empathy-notify-manager.h>
-#include "empathy-main-window.h"
-#include "empathy-import-mc4-accounts.h"
+#include "empathy-roster-window.h"
#include "empathy-accounts-common.h"
#include "empathy-accounts-dialog.h"
-#include "empathy-chat-manager.h"
#include "empathy-status-icon.h"
-#include "empathy-call-window.h"
-#include "empathy-chat-window.h"
#include "empathy-ft-manager.h"
+#include "empathy-notifications-approver.h"
#include "extensions/extensions.h"
#define DEBUG_FLAG EMPATHY_DEBUG_OTHER
#include <libempathy/empathy-debug.h>
-#include <gst/gst.h>
+#define EMPATHY_DBUS_NAME "org.gnome.Empathy"
-static gboolean start_hidden = FALSE;
-static gboolean no_connect = FALSE;
+#define EMPATHY_TYPE_APP (empathy_app_get_type ())
+#define EMPATHY_APP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMPATHY_TYPE_APP, EmpathyApp))
+#define EMPATHY_APP_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), EMPATHY_TYPE_APP, EmpathyAppClass))
+#define EMPATHY_IS_EMPATHY_APP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMPATHY_TYPE_APP))
+#define EMPATHY_IS_EMPATHY_APP_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), EMPATHY_TYPE_APP))
+#define EMPATHY_APP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_APP, EmpathyAppClass))
+
+typedef struct _EmpathyApp EmpathyApp;
+typedef struct _EmpathyAppClass EmpathyAppClass;
+
+enum
+{
+ PROP_NO_CONNECT = 1,
+ PROP_START_HIDDEN
+};
+
+GType empathy_app_get_type (void);
+
+struct _EmpathyAppClass
+{
+ GtkApplicationClass parent_class;
+};
+
+struct _EmpathyApp
+{
+ GtkApplication parent;
+
+ /* Properties */
+ gboolean no_connect;
+ gboolean start_hidden;
+ gboolean show_preferences;
+ gchar *preferences_tab;
+
+ gboolean activated;
+
+ GtkWidget *window;
+ EmpathyStatusIcon *icon;
+ TpAccountManager *account_manager;
+ TplLogManager *log_manager;
+ EmpathyChatroomManager *chatroom_manager;
+ EmpathyFTFactory *ft_factory;
+ EmpathyPresenceManager *presence_mgr;
+ EmpathyConnectivity *connectivity;
+ GSettings *gsettings;
+ EmpathyNotificationsApprover *notifications_approver;
+ EmpathyConnectionAggregator *conn_aggregator;
+#ifdef HAVE_GEOCLUE
+ EmpathyLocationManager *location_manager;
+#endif
+#ifdef ENABLE_DEBUG
+ TpDebugSender *debug_sender;
+#endif
+
+ gboolean shell_running;
+};
+
+
+G_DEFINE_TYPE(EmpathyApp, empathy_app, GTK_TYPE_APPLICATION)
+
+static void
+empathy_app_dispose (GObject *object)
+{
+ EmpathyApp *self = EMPATHY_APP (object);
+ void (*dispose) (GObject *) =
+ G_OBJECT_CLASS (empathy_app_parent_class)->dispose;
+
+ /* Only set our presence to offline when exiting if GNOME Shell is not
+ * running */
+ if (self->presence_mgr != NULL &&
+ !self->shell_running)
+ {
+ empathy_presence_manager_set_state (self->presence_mgr,
+ TP_CONNECTION_PRESENCE_TYPE_OFFLINE);
+ }
+
+#ifdef ENABLE_DEBUG
+ tp_clear_object (&self->debug_sender);
+#endif
+
+ tp_clear_object (&self->presence_mgr);
+ tp_clear_object (&self->connectivity);
+ tp_clear_object (&self->icon);
+ tp_clear_object (&self->account_manager);
+ tp_clear_object (&self->log_manager);
+ tp_clear_object (&self->chatroom_manager);
+#ifdef HAVE_GEOCLUE
+ tp_clear_object (&self->location_manager);
+#endif
+ tp_clear_object (&self->ft_factory);
+ tp_clear_object (&self->gsettings);
+ tp_clear_object (&self->notifications_approver);
+ tp_clear_object (&self->conn_aggregator);
+
+ if (dispose != NULL)
+ dispose (object);
+}
+
+static void
+empathy_app_finalize (GObject *object)
+{
+ EmpathyApp *self = EMPATHY_APP (object);
+ void (*finalize) (GObject *) =
+ G_OBJECT_CLASS (empathy_app_parent_class)->finalize;
+
+ g_free (self->preferences_tab);
+
+ if (finalize != NULL)
+ finalize (object);
+}
static void account_manager_ready_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data);
static void
-dispatch_cb (EmpathyDispatcher *dispatcher,
- EmpathyDispatchOperation *operation,
+empathy_app_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EmpathyApp *self = EMPATHY_APP (object);
+
+ switch (prop_id)
+ {
+ case PROP_NO_CONNECT:
+ self->no_connect = g_value_get_boolean (value);
+ break;
+ case PROP_START_HIDDEN:
+ self->start_hidden = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+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)
{
- GQuark channel_type;
+ if (error)
+ empathy_ft_manager_display_error (handler, error);
+ else
+ empathy_ft_manager_add_handler (handler);
- channel_type = empathy_dispatch_operation_get_channel_type_id (operation);
+ g_object_unref (handler);
+}
- if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_TEXT)
- {
- EmpathyTpChat *tp_chat;
- EmpathyChat *chat = NULL;
- const gchar *id;
+static gboolean
+empathy_app_local_command_line (GApplication *app,
+ gchar ***arguments,
+ gint *exit_status);
- tp_chat = EMPATHY_TP_CHAT
- (empathy_dispatch_operation_get_channel_wrapper (operation));
+static void
+empathy_presence_manager_set_auto_away_cb (GSettings *gsettings,
+ const gchar *key,
+ gpointer user_data)
+{
+ EmpathyPresenceManager *presence_mgr = user_data;
- id = empathy_tp_chat_get_id (tp_chat);
- if (!EMP_STR_EMPTY (id))
- {
- TpConnection *connection;
- TpAccount *account;
+ empathy_presence_manager_set_auto_away (presence_mgr,
+ g_settings_get_boolean (gsettings, key));
+}
- connection = empathy_tp_chat_get_connection (tp_chat);
- account = empathy_get_account_for_connection (connection);
- chat = empathy_chat_window_find_chat (account, id);
- }
+#define GNOME_SHELL_BUS_NAME "org.gnome.Shell"
- if (chat)
- {
- empathy_chat_set_tp_chat (chat, tp_chat);
- }
- else
- {
- chat = empathy_chat_new (tp_chat);
- /* empathy_chat_new returns a floating reference as EmpathyChat is
- * a GtkWidget. This reference will be taken by a container
- * (a GtkNotebook) when we'll call empathy_chat_window_present_chat */
- }
+static void
+list_names_cb (TpDBusDaemon *bus_daemon,
+ const gchar * const *names,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ EmpathyApp *self = (EmpathyApp *) weak_object;
+ guint i;
- empathy_chat_window_present_chat (chat,
- empathy_dispatch_operation_get_user_action_time (operation));
+ if (error != NULL)
+ goto out;
- if (empathy_tp_chat_is_invited (tp_chat, NULL))
+ for (i = 0; names[i] != NULL; i++)
+ {
+ if (!tp_strdiff (names[i], GNOME_SHELL_BUS_NAME))
{
- /* We have been invited to the room. Add ourself as member as this
- * channel has been approved. */
- empathy_tp_chat_join (tp_chat);
+ self->shell_running = TRUE;
+ break;
}
+ }
- empathy_dispatch_operation_claim (operation);
+out:
+ if (self->shell_running)
+ {
+ DEBUG ("GNOME Shell is running, don't create status icon");
+
+ /* Rely on GNOME Shell to watch session state */
+ empathy_presence_manager_set_auto_away (self->presence_mgr, FALSE);
+
+ empathy_roster_window_set_shell_running (
+ EMPATHY_ROSTER_WINDOW (self->window), TRUE);
}
- else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA)
+ else
{
- EmpathyCallFactory *factory;
+ gboolean autoaway;
+
+ self->icon = empathy_status_icon_new (GTK_WINDOW (self->window),
+ self->start_hidden);
+
+ /* Allow Empathy to watch session state */
+ autoaway = g_settings_get_boolean (self->gsettings,
+ EMPATHY_PREFS_AUTOAWAY);
- factory = empathy_call_factory_get ();
- empathy_call_factory_claim_channel (factory, operation);
+ g_signal_connect (self->gsettings,
+ "changed::" EMPATHY_PREFS_AUTOAWAY,
+ G_CALLBACK (empathy_presence_manager_set_auto_away_cb),
+ self->presence_mgr);
+
+ empathy_presence_manager_set_auto_away (self->presence_mgr, autoaway);
}
- else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_FILE_TRANSFER)
+}
+
+static int
+empathy_app_command_line (GApplication *app,
+ GApplicationCommandLine *cmdline)
+{
+ EmpathyApp *self = (EmpathyApp *) app;
+ gchar **args, **argv;
+ gint argc, exit_status, i;
+
+ args = g_application_command_line_get_arguments (cmdline, &argc);
+ /* We have to make an extra copy of the array, since g_option_context_parse()
+ * assumes that it can remove strings from the array without freeing them. */
+ argv = g_new (gchar*, argc + 1);
+ for (i = 0; i <= argc; i++)
+ argv[i] = args[i];
+
+ if (empathy_app_local_command_line (app, &argv, &exit_status))
+ DEBUG ("failed to parse command line!");
+
+ g_free (argv);
+ g_strfreev (args);
+
+ if (!self->activated)
{
- EmpathyFTFactory *factory;
+ GError *error = NULL;
+ TpDBusDaemon *dbus;
+
+ /* Create the FT factory */
+ self->ft_factory = empathy_ft_factory_dup_singleton ();
+ g_signal_connect (self->ft_factory, "new-ft-handler",
+ G_CALLBACK (new_ft_handler_cb), NULL);
+ g_signal_connect (self->ft_factory, "new-incoming-transfer",
+ G_CALLBACK (new_incoming_transfer_cb), NULL);
+
+ if (!empathy_ft_factory_register (self->ft_factory, &error))
+ {
+ g_warning ("Failed to register FileTransfer handler: %s",
+ error->message);
+ g_error_free (error);
+ }
+
+ self->activated = TRUE;
+
+ /* Setting up UI */
+ self->window = empathy_roster_window_dup ();
+
+ gtk_application_add_window (GTK_APPLICATION (app),
+ GTK_WINDOW (self->window));
+
+ /* check if Shell is running */
+ dbus = tp_dbus_daemon_dup (&error);
+ g_assert_no_error (error);
- factory = empathy_ft_factory_dup_singleton ();
+ tp_dbus_daemon_list_names (dbus, -1, list_names_cb,
+ self, NULL, G_OBJECT (self));
- /* if the operation is not incoming, don't claim it,
- * as it might have been triggered by another client, and
- * we are observing it.
+ g_object_unref (dbus);
+
+ self->notifications_approver =
+ empathy_notifications_approver_dup_singleton ();
+ }
+ else
+ {
+ /* We're requested to show stuff again, disable the start hidden global in
+ * case the accounts wizard wants to pop up.
*/
- if (empathy_dispatch_operation_is_incoming (operation))
- empathy_ft_factory_claim_channel (factory, operation);
+ self->start_hidden = FALSE;
+ }
+
+ if (self->show_preferences)
+ empathy_roster_window_show_preferences (
+ EMPATHY_ROSTER_WINDOW (self->window), self->preferences_tab);
+
+ if (!self->start_hidden)
+ empathy_window_present (GTK_WINDOW (self->window));
+
+ /* Display the accounts dialog if needed */
+ tp_proxy_prepare_async (self->account_manager, NULL,
+ account_manager_ready_cb, self);
+
+ return 0;
+}
+
+static gboolean
+preferences_cb (const char *option_name,
+ const char *value,
+ gpointer data,
+ GError **error)
+{
+ EmpathyApp *self = data;
+
+ self->show_preferences = TRUE;
+
+ g_free (self->preferences_tab);
+ self->preferences_tab = g_strdup (value);
+
+ return TRUE;
+}
+
+static gboolean
+show_version_cb (const char *option_name,
+ const char *value,
+ gpointer data,
+ GError **error);
+
+static gboolean
+empathy_app_local_command_line (GApplication *app,
+ gchar ***arguments,
+ gint *exit_status)
+{
+ EmpathyApp *self = (EmpathyApp *) app;
+ gint i;
+ gchar **argv;
+ gint argc = 0;
+ gboolean retval = FALSE;
+ GError *error = NULL;
+ gboolean no_connect = FALSE, start_hidden = FALSE;
+
+ GOptionContext *optcontext;
+ GOptionGroup *group;
+ GOptionEntry options[] = {
+ { "no-connect", 'n',
+ 0, G_OPTION_ARG_NONE, &no_connect,
+ N_("Don't connect on startup"),
+ NULL },
+ { "start-hidden", 'h',
+ 0, G_OPTION_ARG_NONE, &start_hidden,
+ N_("Don't display the contact list or any other dialogs on startup"),
+ NULL },
+ { "show-preferences", 'p',
+ G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, &preferences_cb,
+ NULL, NULL },
+ { "version", 'v',
+ G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version_cb,
+ NULL, NULL },
+ { NULL }
+ };
+
+ /* We create a group so that GOptionArgFuncs get the user data */
+ group = g_option_group_new ("empathy", NULL, NULL, app, NULL);
+ g_option_group_add_entries (group, options);
+
+ optcontext = g_option_context_new (N_("- Empathy IM Client"));
+ g_option_context_add_group (optcontext, gtk_get_option_group (TRUE));
+ g_option_context_set_main_group (optcontext, group);
+ g_option_context_set_translation_domain (optcontext, GETTEXT_PACKAGE);
+
+ argc = g_strv_length (*arguments);
+
+ /* We dup the args because g_option_context_parse() sets things to NULL,
+ * but we want to parse all the command line to the primary instance
+ * if necessary. */
+ argv = g_new (gchar*, argc + 1);
+ for (i = 0; i <= argc; i++)
+ argv[i] = (*arguments)[i];
+
+ if (!g_option_context_parse (optcontext, &argc, &argv, &error))
+ {
+ g_print ("%s\nRun '%s --help' to see a full list of available command "
+ "line options.\n",
+ error->message, argv[0]);
+ g_warning ("Error in empathy init: %s", error->message);
+
+ *exit_status = EXIT_FAILURE;
+ retval = TRUE;
}
+
+ g_free (argv);
+
+ g_option_context_free (optcontext);
+
+ self->no_connect = no_connect;
+ self->start_hidden = start_hidden;
+
+ return retval;
}
+static void empathy_app_constructed (GObject *object);
+
static void
-use_conn_notify_cb (EmpathyConf *conf,
+empathy_app_class_init (EmpathyAppClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GApplicationClass *g_app_class = G_APPLICATION_CLASS (klass);
+ GParamSpec *spec;
+
+ gobject_class->set_property = empathy_app_set_property;
+ gobject_class->constructed = empathy_app_constructed;
+ gobject_class->dispose = empathy_app_dispose;
+ gobject_class->finalize = empathy_app_finalize;
+
+ g_app_class->command_line = empathy_app_command_line;
+ g_app_class->local_command_line = empathy_app_local_command_line;
+
+ spec = g_param_spec_boolean ("no-connect", "no connect",
+ "Don't connect on startup",
+ FALSE,
+ G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (gobject_class, PROP_NO_CONNECT, spec);
+
+ spec = g_param_spec_boolean ("start-hidden", "start hidden",
+ "Don't display the contact list or any other dialogs on startup",
+ FALSE,
+ G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (gobject_class, PROP_START_HIDDEN, spec);
+}
+
+static void
+empathy_app_init (EmpathyApp *self)
+{
+}
+
+static void
+use_conn_notify_cb (GSettings *gsettings,
const gchar *key,
gpointer user_data)
{
EmpathyConnectivity *connectivity = user_data;
- gboolean use_conn;
- if (empathy_conf_get_bool (conf, key, &use_conn))
- {
- empathy_connectivity_set_use_conn (connectivity, use_conn);
- }
+ empathy_connectivity_set_use_conn (connectivity,
+ g_settings_get_boolean (gsettings, key));
}
static void
}
static void
-show_accounts_ui (GdkScreen *screen,
+show_accounts_ui (EmpathyApp *self,
+ GdkScreen *screen,
gboolean if_needed)
{
empathy_accounts_dialog_show_application (screen,
- NULL, if_needed, start_hidden);
-}
-
-static UniqueResponse
-unique_app_message_cb (UniqueApp *unique_app,
- gint command,
- UniqueMessageData *data,
- guint timestamp,
- gpointer user_data)
-{
- GtkWindow *window = user_data;
- TpAccountManager *account_manager;
-
- DEBUG ("Other instance launched, presenting the main window. "
- "Command=%d, timestamp %u", command, timestamp);
-
- /* XXX: the standalone app somewhat breaks this case, since
- * communicating it would be a pain */
-
- /* We're requested to show stuff again, disable the start hidden global
- * in case the accounts wizard wants to pop up.
- */
- start_hidden = FALSE;
-
- gtk_window_set_screen (GTK_WINDOW (window),
- unique_message_data_get_screen (data));
- gtk_window_set_startup_id (GTK_WINDOW (window),
- unique_message_data_get_startup_id (data));
- gtk_window_present_with_time (GTK_WINDOW (window), timestamp);
- gtk_window_set_skip_taskbar_hint (window, FALSE);
-
- account_manager = tp_account_manager_dup ();
- tp_account_manager_prepare_async (account_manager, NULL,
- account_manager_ready_cb, NULL);
- g_object_unref (account_manager);
-
- return UNIQUE_RESPONSE_OK;
+ NULL, if_needed, self->start_hidden);
}
static gboolean
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));
}
static void
gpointer user_data)
{
TpAccountManager *manager = TP_ACCOUNT_MANAGER (source_object);
+ EmpathyApp *self = user_data;
GError *error = NULL;
- EmpathyIdle *idle;
- EmpathyConnectivity *connectivity;
- gboolean autoconnect = TRUE;
TpConnectionPresenceType presence;
- if (!tp_account_manager_prepare_finish (manager, result, &error))
+ if (!tp_proxy_prepare_finish (manager, result, &error))
{
+ GtkWidget *dialog;
+
DEBUG ("Failed to prepare account manager: %s", error->message);
+
+ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ _("Error contacting the Account Manager"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("There was an error while trying to connect to the Telepathy "
+ "Account Manager. The error was:\n\n%s"),
+ error->message);
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
g_error_free (error);
return;
}
/* Autoconnect */
- idle = empathy_idle_dup_singleton ();
- connectivity = empathy_connectivity_dup_singleton ();
-
presence = tp_account_manager_get_most_available_presence (manager, NULL,
NULL);
- empathy_conf_get_bool (empathy_conf_get (),
- EMPATHY_PREFS_AUTOCONNECT, &autoconnect);
- if (autoconnect && !no_connect &&
+ if (g_settings_get_boolean (self->gsettings, EMPATHY_PREFS_AUTOCONNECT) &&
+ !self->no_connect &&
tp_connection_presence_type_cmp_availability
(presence, TP_CONNECTION_PRESENCE_TYPE_OFFLINE)
<= 0)
/* if current state is Offline, then put it online */
- empathy_idle_set_state (idle, TP_CONNECTION_PRESENCE_TYPE_AVAILABLE);
-
- /* Pop up the accounts dialog if it's needed (either when we don't have any
- * accounts yet or when we haven't imported mc4 accounts yet */
- if (!empathy_accounts_has_accounts (manager)
- || !empathy_import_mc4_has_imported ())
- show_accounts_ui (gdk_screen_get_default (), TRUE);
+ empathy_presence_manager_set_state (self->presence_mgr,
+ TP_CONNECTION_PRESENCE_TYPE_AVAILABLE);
- g_object_unref (idle);
- g_object_unref (connectivity);
+ /* Pop up the accounts dialog if we don't have any account */
+ if (!empathy_accounts_has_accounts (manager))
+ show_accounts_ui (self, gdk_screen_get_default (), TRUE);
}
-static EmpathyDispatcher *
-setup_dispatcher (void)
+static void
+account_join_chatrooms (TpAccount *account,
+ EmpathyChatroomManager *chatroom_manager)
{
- EmpathyDispatcher *d;
- GPtrArray *filters;
- struct {
- const gchar *channeltype;
- TpHandleType handletype;
- } types[] = {
- /* Text channels with handle types none, contact and room */
- { TP_IFACE_CHANNEL_TYPE_TEXT, TP_HANDLE_TYPE_NONE },
- { TP_IFACE_CHANNEL_TYPE_TEXT, TP_HANDLE_TYPE_CONTACT },
- { TP_IFACE_CHANNEL_TYPE_TEXT, TP_HANDLE_TYPE_ROOM },
- /* file transfer to contacts */
- { TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, TP_HANDLE_TYPE_CONTACT },
- /* stream media to contacts */
- { TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA, TP_HANDLE_TYPE_CONTACT },
- /* roomlists */
- { TP_IFACE_CHANNEL_TYPE_ROOM_LIST, TP_HANDLE_TYPE_NONE },
- };
- gchar *capabilities[] = {
- "org.freedesktop.Telepathy.Channel.Interface.MediaSignalling/ice-udp",
- "org.freedesktop.Telepathy.Channel.Interface.MediaSignalling/gtalk-p2p",
- NULL };
- GHashTable *asv;
- guint i;
-
- /* Setup the basic Client.Handler that matches our client filter */
- filters = g_ptr_array_new ();
- asv = tp_asv_new (
- TP_IFACE_CHANNEL ".ChannelType", G_TYPE_STRING,
- TP_IFACE_CHANNEL_TYPE_TEXT,
- TP_IFACE_CHANNEL ".TargetHandleType", G_TYPE_INT,
- TP_HANDLE_TYPE_CONTACT,
- NULL);
- g_ptr_array_add (filters, asv);
+ TpConnection *conn;
+ GList *chatrooms, *p;
- d = empathy_dispatcher_new (PACKAGE_NAME, filters, NULL);
+ /* Wait if we are not connected or the TpConnection is not prepared yet */
+ conn = tp_account_get_connection (account);
+ if (conn == NULL)
+ return;
- g_ptr_array_foreach (filters, (GFunc) g_hash_table_destroy, NULL);
- g_ptr_array_free (filters, TRUE);
+ chatrooms = empathy_chatroom_manager_get_chatrooms (
+ chatroom_manager, account);
- /* Setup the an extended Client.Handler that matches everything we can do */
- filters = g_ptr_array_new ();
- for (i = 0 ; i < G_N_ELEMENTS (types); i++)
+ for (p = chatrooms; p != NULL; p = p->next)
{
- asv = tp_asv_new (
- TP_IFACE_CHANNEL ".ChannelType", G_TYPE_STRING, types[i].channeltype,
- TP_IFACE_CHANNEL ".TargetHandleType", G_TYPE_INT, types[i].handletype,
- NULL);
+ EmpathyChatroom *room = EMPATHY_CHATROOM (p->data);
- g_ptr_array_add (filters, asv);
- }
+ if (!empathy_chatroom_get_auto_connect (room))
+ continue;
- asv = tp_asv_new (
- TP_IFACE_CHANNEL ".ChannelType",
- G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
- TP_IFACE_CHANNEL ".TargetHandleType",
- G_TYPE_INT, TP_HANDLE_TYPE_CONTACT,
- TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA ".InitialAudio",
- G_TYPE_BOOLEAN, TRUE,
- NULL);
- g_ptr_array_add (filters, asv);
-
- asv = tp_asv_new (
- TP_IFACE_CHANNEL ".ChannelType",
- G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
- TP_IFACE_CHANNEL ".TargetHandleType",
- G_TYPE_INT, TP_HANDLE_TYPE_CONTACT,
- TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA ".InitialVideo",
- G_TYPE_BOOLEAN, TRUE,
- NULL);
- g_ptr_array_add (filters, asv);
-
-
- empathy_dispatcher_add_handler (d, PACKAGE_NAME"MoreThanMeetsTheEye",
- filters, capabilities);
-
- g_ptr_array_foreach (filters, (GFunc) g_hash_table_destroy, NULL);
- g_ptr_array_free (filters, TRUE);
-
- return d;
+ empathy_join_muc (account, empathy_chatroom_get_room (room),
+ TP_USER_ACTION_TIME_NOT_USER_ACTION);
+ }
+ g_list_free (chatrooms);
}
static void
-account_status_changed_cb (TpAccount *account,
- guint old_status,
- guint new_status,
- guint reason,
- gchar *dbus_error_name,
- GHashTable *details,
- EmpathyChatroom *room)
+account_connection_changed_cb (TpAccount *account,
+ GParamSpec *spec,
+ EmpathyChatroomManager *manager)
{
- TpConnection *conn;
-
- conn = tp_account_get_connection (account);
- if (conn == NULL)
- return;
-
- empathy_dispatcher_join_muc (conn,
- empathy_chatroom_get_room (room), EMPATHY_DISPATCHER_NON_USER_ACTION,
- NULL, NULL);
+ account_join_chatrooms (account, manager);
}
static void
GList *accounts, *l;
GError *error = NULL;
- if (!tp_account_manager_prepare_finish (account_manager, result, &error))
+ if (!tp_proxy_prepare_finish (account_manager, result, &error))
{
DEBUG ("Failed to prepare account manager: %s", error->message);
g_error_free (error);
for (l = accounts; l != NULL; l = g_list_next (l))
{
TpAccount *account = TP_ACCOUNT (l->data);
- TpConnection *conn;
- GList *chatrooms, *p;
-
- conn = tp_account_get_connection (account);
-
- chatrooms = empathy_chatroom_manager_get_chatrooms (
- chatroom_manager, account);
- for (p = chatrooms; p != NULL; p = p->next)
- {
- EmpathyChatroom *room = EMPATHY_CHATROOM (p->data);
-
- if (!empathy_chatroom_get_auto_connect (room))
- continue;
-
- if (conn == NULL)
- {
- g_signal_connect (G_OBJECT (account), "status-changed",
- G_CALLBACK (account_status_changed_cb), room);
- }
- else
- {
- empathy_dispatcher_join_muc (conn,
- empathy_chatroom_get_room (room),
- EMPATHY_DISPATCHER_NON_USER_ACTION, NULL, NULL);
- }
- }
+ /* Try to join all rooms if we're connected */
+ account_join_chatrooms (account, chatroom_manager);
- g_list_free (chatrooms);
+ /* And/or join them on (re)connection */
+ tp_g_signal_connect_object (account, "notify::connection",
+ G_CALLBACK (account_connection_changed_cb), chatroom_manager, 0);
}
-
g_list_free (accounts);
}
{
TpAccountManager *account_manager = user_data;
- tp_account_manager_prepare_async (account_manager, NULL,
+ tp_proxy_prepare_async (account_manager, NULL,
account_manager_chatroom_ready_cb, chatroom_manager);
}
static void
-empathy_idle_set_auto_away_cb (EmpathyConf *conf,
- const gchar *key,
- gpointer user_data)
+empathy_app_constructed (GObject *object)
{
- gboolean autoaway;
- EmpathyIdle *idle = user_data;
-
- empathy_conf_get_bool (conf, key, &autoaway);
- empathy_idle_set_auto_away (idle, autoaway);
-}
-
-int
-main (int argc, char *argv[])
-{
-#if HAVE_GEOCLUE
- EmpathyLocationManager *location_manager = NULL;
-#endif
- EmpathyStatusIcon *icon;
- EmpathyDispatcher *dispatcher;
- TpAccountManager *account_manager;
-#ifdef ENABLE_TPL
- TplLogManager *log_manager;
-#else
- EmpathyLogManager *log_manager;
-#endif /* ENABLE_TPL */
- EmpathyChatroomManager *chatroom_manager;
- EmpathyCallFactory *call_factory;
- EmpathyFTFactory *ft_factory;
- GtkWidget *window;
- EmpathyIdle *idle;
- EmpathyConnectivity *connectivity;
- EmpathyChatManager *chat_manager;
- GError *error = NULL;
- UniqueApp *unique_app;
+ EmpathyApp *self = (EmpathyApp *) object;
gboolean chatroom_manager_ready;
- gboolean autoaway = TRUE;
-#ifdef ENABLE_DEBUG
- TpDebugSender *debug_sender;
-#endif
-
- GOptionContext *optcontext;
- GOptionEntry options[] = {
- { "no-connect", 'n',
- 0, G_OPTION_ARG_NONE, &no_connect,
- N_("Don't connect on startup"),
- NULL },
- { "start-hidden", 'h',
- 0, G_OPTION_ARG_NONE, &start_hidden,
- N_("Don't display the contact list or any other dialogs on startup"),
- NULL },
- { "version", 'v',
- G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version_cb,
- NULL, NULL },
- { NULL }
- };
-
- /* Init */
- g_thread_init (NULL);
- empathy_init ();
-
- optcontext = g_option_context_new (N_("- Empathy IM Client"));
- g_option_context_add_group (optcontext, gst_init_get_option_group ());
- g_option_context_add_group (optcontext, gtk_get_option_group (TRUE));
-#if HAVE_LIBCHAMPLAIN
- g_option_context_add_group (optcontext, clutter_get_option_group ());
-#endif
- g_option_context_add_main_entries (optcontext, options, GETTEXT_PACKAGE);
-
- if (!g_option_context_parse (optcontext, &argc, &argv, &error)) {
- g_print ("%s\nRun '%s --help' to see a full list of available command line options.\n",
- error->message, argv[0]);
- g_warning ("Error in empathy init: %s", error->message);
- return EXIT_FAILURE;
- }
-
- g_option_context_free (optcontext);
- empathy_gtk_init ();
g_set_application_name (_(PACKAGE_NAME));
- g_setenv ("PULSE_PROP_media.role", "phone", TRUE);
gtk_window_set_default_icon_name ("empathy");
textdomain (GETTEXT_PACKAGE);
#ifdef ENABLE_DEBUG
/* Set up debug sender */
- debug_sender = tp_debug_sender_dup ();
+ self->debug_sender = tp_debug_sender_dup ();
g_log_set_default_handler (tp_debug_sender_log_handler, G_LOG_DOMAIN);
#endif
- unique_app = unique_app_new ("org.gnome."PACKAGE_NAME, NULL);
-
- if (unique_app_is_running (unique_app))
- {
- unique_app_send_message (unique_app, UNIQUE_ACTIVATE, NULL);
-
- g_object_unref (unique_app);
- return EXIT_SUCCESS;
- }
-
notify_init (_(PACKAGE_NAME));
/* Setting up Idle */
- idle = empathy_idle_dup_singleton ();
-
- empathy_conf_get_bool (empathy_conf_get (),
- EMPATHY_PREFS_AUTOAWAY, &autoaway);
-
- empathy_conf_notify_add (empathy_conf_get (),
- EMPATHY_PREFS_AUTOAWAY,
- empathy_idle_set_auto_away_cb,
- idle);
+ self->presence_mgr = empathy_presence_manager_dup_singleton ();
- empathy_idle_set_auto_away (idle, autoaway);
+ self->gsettings = g_settings_new (EMPATHY_PREFS_SCHEMA);
/* Setting up Connectivity */
- connectivity = empathy_connectivity_dup_singleton ();
- use_conn_notify_cb (empathy_conf_get (), EMPATHY_PREFS_USE_CONN,
- connectivity);
- empathy_conf_notify_add (empathy_conf_get (), EMPATHY_PREFS_USE_CONN,
- use_conn_notify_cb, connectivity);
+ self->connectivity = empathy_connectivity_dup_singleton ();
+ use_conn_notify_cb (self->gsettings, EMPATHY_PREFS_USE_CONN,
+ self->connectivity);
+ g_signal_connect (self->gsettings,
+ "changed::" EMPATHY_PREFS_USE_CONN,
+ G_CALLBACK (use_conn_notify_cb), self->connectivity);
/* account management */
- account_manager = tp_account_manager_dup ();
- tp_account_manager_prepare_async (account_manager, NULL,
- account_manager_ready_cb, NULL);
-
- /* Handle channels */
- dispatcher = setup_dispatcher ();
- g_signal_connect (dispatcher, "dispatch", G_CALLBACK (dispatch_cb), NULL);
+ self->account_manager = tp_account_manager_dup ();
+ tp_proxy_prepare_async (self->account_manager, NULL,
+ account_manager_ready_cb, self);
migrate_config_to_xdg_dir ();
- /* Setting up UI */
- window = empathy_main_window_show ();
- icon = empathy_status_icon_new (GTK_WINDOW (window), start_hidden);
-
- /* Chat manager */
- chat_manager = empathy_chat_manager_dup_singleton ();
-
- g_signal_connect (unique_app, "message-received",
- G_CALLBACK (unique_app_message_cb), window);
-
/* Logging */
-#ifdef ENABLE_TPL
- log_manager = tpl_log_manager_dup_singleton ();
-#else
- log_manager = empathy_log_manager_dup_singleton ();
- empathy_log_manager_observe (log_manager, dispatcher);
-#endif
+ self->log_manager = tpl_log_manager_dup_singleton ();
- chatroom_manager = empathy_chatroom_manager_dup_singleton (NULL);
- empathy_chatroom_manager_observe (chatroom_manager, dispatcher);
+ self->chatroom_manager = empathy_chatroom_manager_dup_singleton (NULL);
- g_object_get (chatroom_manager, "ready", &chatroom_manager_ready, NULL);
+ g_object_get (self->chatroom_manager, "ready", &chatroom_manager_ready, NULL);
if (!chatroom_manager_ready)
{
- g_signal_connect (G_OBJECT (chatroom_manager), "notify::ready",
- G_CALLBACK (chatroom_manager_ready_cb), account_manager);
+ g_signal_connect (G_OBJECT (self->chatroom_manager), "notify::ready",
+ G_CALLBACK (chatroom_manager_ready_cb), self->account_manager);
}
else
{
- chatroom_manager_ready_cb (chatroom_manager, NULL, account_manager);
+ chatroom_manager_ready_cb (self->chatroom_manager, NULL,
+ self->account_manager);
}
- /* 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 ();
+#ifdef HAVE_GEOCLUE
+ self->location_manager = empathy_location_manager_dup_singleton ();
#endif
- gtk_main ();
+ self->conn_aggregator = empathy_connection_aggregator_dup_singleton ();
+
+ self->activated = FALSE;
+ self->ft_factory = NULL;
+ self->window = NULL;
+}
- empathy_idle_set_state (idle, TP_CONNECTION_PRESENCE_TYPE_OFFLINE);
+static void
+add_empathy_features (void)
+{
+ /* Add 'empathy' specific feature before doing any preparation */
+ EmpathyClientFactory *factory;
+
+ factory = empathy_client_factory_dup ();
+
+ tp_simple_client_factory_add_connection_features_varargs (
+ TP_SIMPLE_CLIENT_FACTORY (factory),
+ /* empathy_connection_aggregator_get_all_groups(), used by
+ * EmpathyGroupsWidget relies on it */
+ TP_CONNECTION_FEATURE_CONTACT_GROUPS,
+ /* empathy_connection_aggregator_dup_all_contacts(), used by
+ * EmpathyEventManager relies on it */
+ TP_CONNECTION_FEATURE_CONTACT_LIST,
+ NULL);
-#ifdef ENABLE_DEBUG
- g_object_unref (debug_sender);
-#endif
+ g_object_unref (factory);
+}
+
+int
+main (int argc, char *argv[])
+{
+ EmpathyApp *app;
+ gint retval;
- g_object_unref (chat_manager);
- g_object_unref (idle);
- g_object_unref (connectivity);
- g_object_unref (icon);
- g_object_unref (account_manager);
- g_object_unref (log_manager);
- g_object_unref (dispatcher);
- g_object_unref (chatroom_manager);
-#if HAVE_GEOCLUE
- g_object_unref (location_manager);
+ g_thread_init (NULL);
+ g_type_init ();
+
+#ifdef HAVE_LIBCHAMPLAIN
+ gtk_clutter_init (&argc, &argv);
#endif
- g_object_unref (ft_factory);
- g_object_unref (unique_app);
+
+ g_type_init ();
+ empathy_init ();
+ gtk_init (&argc, &argv);
+ empathy_gtk_init ();
+
+ add_empathy_features ();
+
+ app = g_object_new (EMPATHY_TYPE_APP,
+ "application-id", EMPATHY_DBUS_NAME,
+ "flags", G_APPLICATION_HANDLES_COMMAND_LINE,
+ NULL);
+
+ retval = g_application_run (G_APPLICATION (app), argc, argv);
notify_uninit ();
xmlCleanupParser ();
- return EXIT_SUCCESS;
+ g_object_unref (app);
+
+ return retval;
}