Logo Search packages:      
Sourcecode: xchat-gnome version File versions  Download package

autoaway.c

/* autoaway.c
 *
 * An auto away plugin for xchat-gnome.
 *
 * Copyright (C) 2005 Isak Savo <isak.savo@gmail.com>
 *
 * 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.
 *
 */

#include <config.h>
#include <glib/gi18n.h>
#include <glib.h>
#include <dlfcn.h>
#include <string.h>
#include <xchat-plugin.h>

#include "autoaway.h"
#include "gscreensaver.h"
#include "xscreensaver.h"

void xchat_plugin_get_info (char **plugin_name, char **plugin_desc, char **plugin_version, void **reserved);
int  xchat_plugin_init     (xchat_plugin * plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg);
int  xchat_plugin_deinit   (void);

static xchat_plugin *ph;            /* Plugin handle. */
static xchat_hook *timeout_hook = NULL; /* Timeout handle */
static GList *networks = NULL;            /* List of connected networks */

typedef enum {
      STATE_ACTIVE,
      STATE_AWAY
} aa_state_t;

typedef enum {
      SS_NONE,    /* This plugin is useless if this is set        */
      SS_GNOME,   /* Use DBus to talk to gnome-screensaver        */
      SS_X11            /* We're talking to xscreensaver                */
} screensaver_t;

static screensaver_t screensaver_type = SS_NONE;
static aa_state_t state = STATE_ACTIVE;

static screensaver_t
get_screensaver_type (void)
{
      if (get_gs_has_ipc ())
            return SS_GNOME;

      if (get_xss_has_ipc ())
            return SS_X11;

      return SS_NONE;
}

static gboolean
is_away (void)
{
      if (xchat_get_context (ph))
            return (xchat_get_info (ph, "away") != NULL);

      return FALSE;
}

/* Use whatever available resource to find if the screensaver has kicked in or not */
static gboolean
get_screensaver_active (void)
{
      switch (screensaver_type) {
            case SS_X11:
                  return get_xss_screensaver_active ();

            case SS_GNOME:
                  return get_gs_screensaver_active();

            case SS_NONE:
                  return FALSE;
      }

      return FALSE;
}


/* Go away on all networks and do a nickname change if desired */
static void
set_away (void)
{
      GList *node = g_list_first (networks);
      xchat_context *cur_context = NULL;

      while (node)
      {
            const gchar *nw = (const gchar*) node->data;
            cur_context = xchat_find_context (ph, nw, NULL);
            if (!cur_context) {
                  node = node->next;
                  continue;
            }
            xchat_set_context (ph, cur_context);
            if (is_away()) {
                  node = g_list_next (node);
                  continue;
            }

            xchat_command (ph, "AWAY");

            node = g_list_next (node);
      }
}

/* Come back from away and restore nickname if needed */
static void
come_back (void)
{
      GList *node = g_list_first (networks);
      xchat_context *cur_context = NULL;

      /* Iterate over all networks */
      while (node) {
            const char *nw = (const gchar*) node->data;
            cur_context = xchat_find_context (ph, nw, NULL);
            if (!cur_context) {
                  node = g_list_next (node);
                  continue;
            }
            xchat_set_context (ph, cur_context);

            if (!is_away ()) {
                  node = g_list_next (node);
                  continue;
            }
            xchat_command (ph, "AWAY");

            node = g_list_next (node);
      }
}

/*** Callbacks ***/

static int
timeout_cb (gpointer user_data)
{
      xchat_set_context (ph, xchat_find_context (ph, NULL, NULL));

      if (!networks) {
            trace ("Not connected");
            return 1;
      }
      switch (state) {
            case STATE_ACTIVE:
                  if (get_screensaver_active ()) {
                        xchat_print (ph, _("Screensaver activated, going away."));
                        set_away ();
                        state = STATE_AWAY;
                  }
                  break;

            case STATE_AWAY:
                  if (get_screensaver_active () == FALSE) {
                        xchat_print (ph, _("Screensaver is off, welcome back"));
                        come_back ();
                        state = STATE_ACTIVE;
                  }
                  break;

            default:
                  break;
      }


      return 1;
}

/* New or lost connection - update network list */
static int
network_change_cb (gchar *word[], gpointer user_data)
{
      gboolean new_conn = GPOINTER_TO_INT (user_data);
      const gchar *servername;
      GList *node = NULL;

      servername = xchat_get_info (ph, "network");
      if (new_conn) {
            networks = g_list_append (networks, g_strdup (servername));
      } else {
            node = g_list_find_custom (networks, servername, (GCompareFunc) strcmp);
            if (node) {
                  g_free (node->data);
                  networks = g_list_delete_link (networks, node);
            }
      }

      return XCHAT_EAT_NONE;
}

/*** xchat-gnome plugin functions ***/
void
xchat_plugin_get_info (char **plugin_name, char **plugin_desc, char **plugin_version, void **reserved)
{
      *plugin_name = _("Auto Away");
      *plugin_desc = _("Automatically go away / come back");
      *plugin_version = AUTOAWAY_VERSION;

      if (reserved)
            *reserved = NULL;
}

/*** xchat plugin functions ***/
int
xchat_plugin_init (xchat_plugin * plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
{
      ph = plugin_handle;
      init_gs_connection ();

      /* Set the plugin info. */
      xchat_plugin_get_info (plugin_name, plugin_desc, plugin_version, NULL);

      /* Hook up our callbacks. */
      xchat_hook_print (ph, _("Disconnected"), XCHAT_PRI_NORM, network_change_cb, GINT_TO_POINTER (FALSE));
      xchat_hook_print (ph, _("Connected"),    XCHAT_PRI_NORM, network_change_cb, GINT_TO_POINTER (TRUE));

      timeout_hook = xchat_hook_timer (ph, 5000, timeout_cb, NULL);

      xchat_set_context (ph, xchat_find_context (ph, NULL, NULL));

      screensaver_type = get_screensaver_type ();

      /* All done */
      xchat_printf (ph, "Auto-away plugin %s loaded (using %s screensaver)\n", AUTOAWAY_VERSION,
                    screensaver_type == SS_GNOME ? "GNOME" : screensaver_type == SS_X11 ? "X11" : "no");

      /* FIXME: Perhaps return FALSE if we failed to find a running screensaver? */
      return TRUE;
}

int
xchat_plugin_deinit (void)
{
      xchat_unhook (ph, timeout_hook);

      if (networks) {
            g_list_foreach (networks, (GFunc) g_free, NULL);
            g_list_free (networks);
      }

      close_gs_connection ();

      xchat_set_context (ph, xchat_find_context (ph, NULL, NULL));
      xchat_print (ph, _("Auto-away plugin unloaded\n"));
      return TRUE;
}

Generated by  Doxygen 1.6.0   Back to index