Logo Search packages:      
Sourcecode: gaim-galago version File versions  Download package

gaim-galago.c

Go to the documentation of this file.
/**
 * @file gaim-galago.c Gaim Galago plugin
 *
 * Copyright (C) 2004-2006 Christian Hammond.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * 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
 */
#define GAIM_PLUGINS

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "account.h"
#include "blist.h"
#include "debug.h"
#include "plugin.h"
#include "server.h"
#include "util.h"
#include "version.h"

#if GAIM_VERSION_CHECK(2,0,0)
#  include "status.h"
#endif

#include <libgalago/galago.h>

#include <dbus/dbus-glib.h>
#include <ctype.h>
#include <string.h>

#ifdef ENABLE_NLS
#  include <locale.h>
#  include <libintl.h>
#  define _(x) gettext(x)
#  ifdef gettext_noop
#    define N_(String) gettext_noop (String)
#  else
#    define N_(String) (String)
#  endif
#else
#  include <locale.h>
#  define N_(String) (String)
#  define _(x) (x)
#  define ngettext(Singular, Plural, Number) ((Number == 1) ? (Singular) : (Plural))
#endif

static GHashTable *person_table = NULL;
static GalagoPerson *me = NULL;

static const char *
get_service_for_prpl_id(const char *prpl_id, const char *user)
{
      if (prpl_id == NULL)
            return NULL;

      if (!g_ascii_strcasecmp(prpl_id, "prpl-oscar"))
      {
            if (isdigit(*user))
                  return GALAGO_SERVICE_ID_ICQ;
            else
                  return GALAGO_SERVICE_ID_AIM;
      }
      else if (!g_ascii_strcasecmp(prpl_id, "prpl-novell"))
            return GALAGO_SERVICE_ID_GROUPWISE;
      else if (!g_ascii_strcasecmp(prpl_id, "prpl-gg"))
            return GALAGO_SERVICE_ID_GADUGADU;

      if (!strncmp(prpl_id, "prpl-", 5))
            return prpl_id + 5;

      return prpl_id;
}

static GalagoService *
get_galago_service(GaimAccount *account)
{
      const char *username, *protocol_id, *service_id;

      g_return_val_if_fail(account != NULL, NULL);

      username    = gaim_account_get_username(account);
      protocol_id = gaim_account_get_protocol_id(account);

      service_id = get_service_for_prpl_id(protocol_id, username);

      return galago_create_service(service_id, service_id, 0);
}

static GalagoAccount *
get_my_galago_account(GaimAccount *account)
{
      GalagoService *service;
      const char *username;

      service = get_galago_service(account);

      if (service == NULL)
            return NULL;

      username = gaim_account_get_username(account);

      return galago_service_create_account(service, me, username);
}

static void
update_avatar(GaimBuddy *buddy, GalagoAccount *gaccount)
{
      GaimBuddyIcon *buddy_icon;
      GalagoImage *avatar;
      const unsigned char *data;
      unsigned char *old_data = NULL;
      size_t len, old_len = 0;

      if ((buddy_icon = gaim_buddy_get_icon(buddy)) == NULL)
            return;

      data   = gaim_buddy_icon_get_data(buddy_icon, &len);
      avatar = galago_account_get_avatar(gaccount, FALSE);

      if (avatar != NULL)
            galago_image_get_data(avatar, &old_data, &old_len);

      if (avatar == NULL || len != old_len || memcmp(data, old_data, len))
      {
            GalagoService *service = galago_account_get_service(gaccount);

            gaim_debug_info("galago",
                                    "Setting avatar for %s on account %s on %s\n",
                                    buddy->name, gaim_account_get_username(buddy->account),
                                    galago_service_get_id(service));
            galago_account_set_avatar(gaccount,
                  galago_image_new_from_data(data, len));
      }
}

static void
#if GAIM_VERSION_CHECK(2,0,0) /* more ugly preproc */
buddy_idle_changed_cb(GaimBuddy *buddy, gboolean old_idle, gboolean new_idle)
#else
buddy_idle_changed_cb(GaimBuddy *buddy)
#endif /* end of more ugly preproc */
{
      GalagoPresence *presence;
      GalagoService *service;
      GalagoAccount *my_gaccount, *gaccount;
      guint32 idle_start_time = 0;
      gboolean idle;

      my_gaccount = get_my_galago_account(buddy->account);
      service     = galago_account_get_service(my_gaccount);

      gaccount = galago_service_get_account(service, buddy->name, FALSE);

      if (gaccount == NULL)
            return;

      /* This is a hack, but a necessary one. */
      update_avatar(buddy, gaccount);

      presence = galago_account_get_presence(gaccount, FALSE);

      if (presence == NULL)
            return;

#if GAIM_VERSION_CHECK(2,0,0)
      {
            GaimPresence *bpresence;

            bpresence = gaim_buddy_get_presence(buddy);

            if((idle = gaim_presence_is_idle(bpresence)))
                  idle_start_time = time(NULL) -
                                    gaim_presence_get_idle_time(bpresence);
      }
#else
      idle = (buddy->idle > 0);

      if (idle)
            idle_start_time = buddy->idle;
#endif

      if (idle != galago_presence_is_idle(presence))
            galago_presence_set_idle(presence, idle, idle_start_time);
}

static void
#if GAIM_VERSION_CHECK(2,0,0) /* yes this is ugly... */
buddy_status_changed_cb(GaimBuddy *buddy, GaimStatus *old_status,
                                    GaimStatus *new_status)
#else
buddy_status_changed_cb(GaimBuddy *buddy)
#endif /* end of ugly preproc... */
{
      GaimPlugin *prpl;
      GaimPluginProtocolInfo *prpl_info = NULL;
      GalagoPresence *presence;
      GalagoService *service;
      GalagoAccount *my_gaccount, *gaccount;
      GalagoStatus *status;
      GalagoStatusType status_type;
      const char *status_id;
      char *status_message = NULL;

      my_gaccount = get_my_galago_account(buddy->account);
      service     = galago_account_get_service(my_gaccount);

      gaccount = galago_service_get_account(service, buddy->name, FALSE);

      if (gaim_account_is_connected(buddy->account))
      {
            if (gaccount == NULL)
            {
                  GalagoPerson *person;
                  GaimContact *contact;

                  contact = (GaimContact *)((GaimBlistNode *)buddy)->parent;

                  person = g_hash_table_lookup(person_table, contact);

                  if (person == NULL)
                  {
                        person = galago_create_person(NULL);
                        g_hash_table_insert(person_table, contact, person);
                  }

                  gaccount = galago_service_create_account(service, person,
                                                                               buddy->name);
                  galago_account_set_display_name(gaccount,
                                                                  gaim_buddy_get_alias(buddy));
                  galago_account_add_contact(my_gaccount, gaccount);
            }
      }
      else
      {
            if (gaccount != NULL)
                  galago_account_set_connected(gaccount, FALSE);

            return;
      }

      if (!GAIM_BUDDY_IS_ONLINE(buddy))
      {
            galago_account_set_connected(gaccount, FALSE);

            return;
      }

      if (!galago_account_is_connected(gaccount))
            galago_account_set_connected(gaccount, TRUE);

      presence = galago_account_create_presence(gaccount);

      gaim_debug_info("galago",
                              "Adding presence for %s on account %s on %s\n",
                              buddy->name, gaim_account_get_username(buddy->account),
                              galago_service_get_id(service));

#if GAIM_VERSION_CHECK(2,0,0)
      {
            GaimPresence *bpresence = NULL;
            GaimStatus *bstatus = NULL;
            GaimStatusType *bstatus_type = NULL;

            bpresence = gaim_buddy_get_presence(buddy);
            bstatus = gaim_presence_get_active_status(bpresence);
            bstatus_type = gaim_status_get_type(bstatus);

            switch(gaim_status_type_get_primitive(bstatus_type)) {
                  case GAIM_STATUS_AVAILABLE:
                        status_type = GALAGO_STATUS_AVAILABLE;
                        status_id = GALAGO_STATUS_ID_AVAILABLE;
                        break;
                  case GAIM_STATUS_UNAVAILABLE:
                  case GAIM_STATUS_AWAY:
                        status_type = GALAGO_STATUS_AWAY;
                        status_id = GALAGO_STATUS_ID_AWAY;
                        break;
                  case GAIM_STATUS_INVISIBLE:
                        status_type = GALAGO_STATUS_HIDDEN;
                        status_id = GALAGO_STATUS_ID_HIDDEN;
                        break;
                  case GAIM_STATUS_EXTENDED_AWAY:
                        status_type = GALAGO_STATUS_EXTENDED_AWAY;
                        status_id = GALAGO_STATUS_ID_EXTENDED_AWAY;
                        break;
                  case GAIM_STATUS_UNSET:
                  case GAIM_STATUS_OFFLINE:
                  default:
                        status_type = GALAGO_STATUS_OFFLINE;
                        status_id = GALAGO_STATUS_ID_OFFLINE;
                        break;
            }
      }
#else
      if (buddy->uc & UC_UNAVAILABLE)
      {
            status_type = GALAGO_STATUS_AWAY;
            status_id   = GALAGO_STATUS_ID_AWAY;
      }
      else
      {
            status_type = GALAGO_STATUS_AVAILABLE;
            status_id   = GALAGO_STATUS_ID_AVAILABLE;
      }
#endif

      prpl = gaim_find_prpl(gaim_account_get_protocol_id(buddy->account));

      if (prpl != NULL)
            prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl);

      if (prpl != NULL && prpl_info->status_text != NULL)
      {
            char *temp = prpl_info->status_text(buddy);

            if (temp != NULL)
            {
                  status_message = g_strdup(temp);

                  g_free(temp);
            }
      }

      if (galago_presence_has_status(presence, status_id))
      {
            status = galago_presence_get_status(presence, status_id);

            if (status_message != NULL)
            {
                  galago_object_set_attr_string(GALAGO_OBJECT(status),
                                                              "message", status_message);
            }
      }
      else
      {
            status = galago_status_new(status_type, status_id, NULL, TRUE);

            if (status_message != NULL)
            {
                  galago_object_set_attr_string(GALAGO_OBJECT(status),
                                                              "message", status_message);
            }

            galago_presence_add_status(presence, status);
      }

      if (status_message != NULL)
            g_free(status_message);

      update_avatar(buddy, gaccount);
}

static void
signed_on_cb(GaimConnection *gc)
{
      GaimBlistNode *bnode, *cnode, *group;
      GaimAccount *account;
      GalagoPerson *me;
      GalagoAccount *my_gaccount;

      me = galago_get_me(TRUE, FALSE);

      account     = gaim_connection_get_account(gc);
      my_gaccount = get_my_galago_account(account);

      galago_account_set_connected(my_gaccount, TRUE);

      for (group = gaim_get_blist()->root; group != NULL; group = group->next)
      {
            for (cnode = group->child; cnode != NULL; cnode = cnode->next)
            {
                  if (GAIM_BLIST_NODE_IS_CONTACT(cnode))
                  {
                        for (bnode = cnode->child; bnode != NULL; bnode = bnode->next)
                        {
                              GaimBuddy *buddy = (GaimBuddy *)bnode;

                              if (account == buddy->account)
                              {
#if GAIM_VERSION_CHECK(2,0,0)
                                    GaimPresence *presence;
                                    GaimStatus *status;

                                    presence = gaim_buddy_get_presence(buddy);
                                    status = gaim_presence_get_active_status(presence);
                                    buddy_status_changed_cb(buddy, status, status);
#else
                                    buddy_status_changed_cb(buddy);
                                    buddy_idle_changed_cb(buddy);
#endif
                              }
                        }
                  }
            }
      }
}

static void
signed_off_cb(GaimConnection *gc)
{
      GaimAccount *account;
      GalagoAccount *my_gaccount;
      GalagoPerson *me;
      GalagoPresence *presence;

      me = galago_get_me(TRUE, FALSE);

      account     = gaim_connection_get_account(gc);
      my_gaccount = get_my_galago_account(account);

      galago_account_set_connected(my_gaccount, FALSE);

      presence = galago_account_create_presence(my_gaccount);

      if (!galago_presence_has_status(presence, GALAGO_STATUS_ID_OFFLINE))
      {
            GalagoStatus *status;

            status = galago_status_new(GALAGO_STATUS_OFFLINE,
                                                   GALAGO_STATUS_ID_OFFLINE, NULL, TRUE);
            galago_presence_add_status(presence, status);
      }
}

#if GAIM_VERSION_CHECK(2,0,0)
static void
buddy_icon_changed_cb(GaimBuddyIcon *icon, GaimBuddy *buddy,
                                const gchar *filename, const gchar *oldfilename)
{
      GalagoAccount *my_gaccount, *gaccount;
      GalagoService *service;

      /* this could probably be cleaned up more, but seeing as I'm not too
       * familiar with galago right now...
       *
       * - grim
       */

      my_gaccount = get_my_galago_account(buddy->account);
      service = galago_account_get_service(my_gaccount);
      gaccount = galago_service_get_account(service, buddy->name, FALSE);

      update_avatar(buddy, gaccount);
}
#endif

static void
setup_accounts(void)
{
      GList *l;

      me = galago_get_me(GALAGO_LOCAL, FALSE);

      for (l = gaim_accounts_get_all(); l != NULL; l = l->next)
      {
            GaimAccount *account = (GaimAccount *)l->data;
            GalagoAccount *my_gaccount;

            my_gaccount = get_my_galago_account(account);

            galago_account_set_connected(my_gaccount,
                                                       gaim_account_is_connected(account));
      }
}

static void
scan_presences(void)
{
      GaimBlistNode *bnode, *cnode, *group;

      if (gaim_get_blist() == NULL)
            return;

      for (group = gaim_get_blist()->root; group != NULL; group = group->next)
      {
            for (cnode = group->child; cnode != NULL; cnode = cnode->next)
            {
                  if (GAIM_BLIST_NODE_IS_CONTACT(cnode))
                  {
                        for (bnode = cnode->child; bnode != NULL; bnode = bnode->next)
                        {
                              GaimBuddy *buddy = (GaimBuddy *)bnode;

                              if (gaim_account_is_connected(buddy->account)) {
#if GAIM_VERSION_CHECK(2,0,0)
                                    GaimPresence *presence;
                                    GaimStatus *status;

                                    presence = gaim_buddy_get_presence(buddy);
                                    status = gaim_presence_get_active_status(presence);
                                    buddy_status_changed_cb(buddy, status, status);
#else
                                    buddy_status_changed_cb(buddy);
#endif
                              }
                        }
                  }
            }
      }
}

/*
 * More or less copy-and-pasted from gtkdebug.c in gaim.
 */
static void
log_handler(const gchar *domain, GLogLevelFlags flags,
                  const gchar *msg, gpointer user_data)
{
      GaimDebugLevel level;
      char *new_msg = NULL;
      char *new_domain = NULL;

      if ((flags & G_LOG_LEVEL_ERROR) == G_LOG_LEVEL_ERROR)
            level = GAIM_DEBUG_ERROR;
      else if ((flags & G_LOG_LEVEL_CRITICAL) == G_LOG_LEVEL_CRITICAL)
            level = GAIM_DEBUG_FATAL;
      else if ((flags & G_LOG_LEVEL_WARNING) == G_LOG_LEVEL_WARNING)
            level = GAIM_DEBUG_WARNING;
      else if ((flags & G_LOG_LEVEL_MESSAGE) == G_LOG_LEVEL_MESSAGE)
            level = GAIM_DEBUG_INFO;
      else if ((flags & G_LOG_LEVEL_INFO) == G_LOG_LEVEL_INFO)
            level = GAIM_DEBUG_INFO;
      else if ((flags & G_LOG_LEVEL_DEBUG) == G_LOG_LEVEL_DEBUG)
            level = GAIM_DEBUG_MISC;
      else
      {
            gaim_debug_warning("Galago",
                                       "Unknown glib logging level in %d\n", flags);

            level = GAIM_DEBUG_MISC; /* This will never happen. */
      }

      if (msg != NULL)
            new_msg = gaim_utf8_try_convert(msg);

      if (domain != NULL)
            new_domain = gaim_utf8_try_convert(domain);

      if (new_msg != NULL)
      {
            gaim_debug(level, (new_domain != NULL ? new_domain : "g_log"),
                           "%s\n", new_msg);

            g_free(new_msg);
      }

      if (new_domain != NULL)
            g_free(new_domain);
}

static gboolean
plugin_load(GaimPlugin *plugin)
{
      void *blist_handle = NULL;

      g_log_set_handler("Galago",
                                G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL |
                                G_LOG_FLAG_RECURSION,
                                log_handler, NULL);

      if (!galago_init("gaim", GALAGO_INIT_FEED))
            return FALSE;

      if (!galago_is_connected())
      {
            gaim_debug(GAIM_DEBUG_ERROR, "gaim-galago",
                           "Unable to connect to Galago service\n");

            return FALSE;
      }

      if (!galago_is_registered())
      {
            gaim_debug(GAIM_DEBUG_ERROR, "gaim-galago",
                           "Unable to register with the Galago service\n");

            return FALSE;
      }

      person_table = g_hash_table_new(NULL, NULL);

      /* Connect the signals */
      blist_handle = gaim_blist_get_handle();

      gaim_signal_connect(blist_handle, "buddy-signed-on",
                                    plugin, GAIM_CALLBACK(buddy_status_changed_cb), NULL);
      gaim_signal_connect(blist_handle, "buddy-signed-off",
                                    plugin, GAIM_CALLBACK(buddy_status_changed_cb), NULL);

#if !GAIM_VERSION_CHECK(2,0,0)
      gaim_signal_connect(blist_handle, "buddy-away",
                                    plugin, GAIM_CALLBACK(buddy_status_changed_cb), NULL);
      gaim_signal_connect(blist_handle, "buddy-back",
                                    plugin, GAIM_CALLBACK(buddy_status_changed_cb), NULL);
      gaim_signal_connect(blist_handle, "buddy-idle",
                                    plugin, GAIM_CALLBACK(buddy_idle_changed_cb), NULL);
      gaim_signal_connect(blist_handle, "buddy-unidle",
                                    plugin, GAIM_CALLBACK(buddy_idle_changed_cb), NULL);
      gaim_signal_connect(blist_handle, "buddy-idle-updated",
                                    plugin, GAIM_CALLBACK(buddy_idle_changed_cb), NULL);

#else /* gaim 2.0.0 and above... */
      gaim_signal_connect(blist_handle, "buddy-status-changed",
                                    plugin, GAIM_CALLBACK(buddy_status_changed_cb), NULL);
      gaim_signal_connect(blist_handle, "buddy-idle-changed",
                                    plugin, GAIM_CALLBACK(buddy_idle_changed_cb), NULL);
      gaim_signal_connect(gaim_buddy_icons_get_handle(), "buddy-icon-changed",
                                    plugin, GAIM_CALLBACK(buddy_icon_changed_cb), NULL);
#endif

      gaim_signal_connect(gaim_connections_get_handle(), "signed-on",
                                    plugin, GAIM_CALLBACK(signed_on_cb), NULL);
      gaim_signal_connect(gaim_connections_get_handle(), "signed-off",
                                    plugin, GAIM_CALLBACK(signed_off_cb), NULL);

      setup_accounts();
      scan_presences();

      return TRUE;
}

static gboolean
plugin_unload(GaimPlugin *plugin)
{
      galago_uninit();

      g_hash_table_destroy(person_table);
      person_table = NULL;

      return TRUE;
}

static GaimPluginInfo info =
{
      GAIM_PLUGIN_MAGIC,
      GAIM_MAJOR_VERSION,
      GAIM_MINOR_VERSION,
      GAIM_PLUGIN_STANDARD,                             /**< type           */
      NULL,                                             /**< ui_requirement */
      0,                                                /**< flags          */
      NULL,                                             /**< dependencies   */
      GAIM_PRIORITY_DEFAULT,                            /**< priority       */

      "core-chipx86-galago",                            /**< id             */
      "Galago",                                         /**< name           */
      VERSION,                                          /**< version        */
                                                        /**  summary        */
      N_("Turns gaim into a feed for Galago."),
                                                        /**  description    */
      N_("Turns gaim into a feed for Galago."),
      "Christian Hammmond <chipx86@gnupdate.org>",      /**< author         */
      "http://galago.sourceforge.net/",                 /**< homepage       */

      plugin_load,                                      /**< load           */
      plugin_unload,                                    /**< unload         */
      NULL,                                             /**< destroy        */

      NULL,                                             /**< ui_info        */
      NULL                                              /**< extra_info     */
};

static void
init_plugin(GaimPlugin *plugin)
{
}

GAIM_INIT_PLUGIN(galago, init_plugin, info)

Generated by  Doxygen 1.6.0   Back to index