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

gaim-xmms-remote.c

/*
  Gaim-XMMS-Remote - Control xmms from gaim conversations
  Copyright (C) 2004 Gary Kramlich

  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 <glib.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>

#include <xmmsctrl.h>

#ifdef HAVE_CONFIG_H
# include "../gxr_config.h"
#endif

#include "internal.h"

#include "cmds.h"
#include "conversation.h"
#include "debug.h"
#include "gtkconv.h"
#include "gtkplugin.h"
#include "gtkprefs.h"
#include "gtkutils.h"
#include "prefs.h"
#include "version.h"

/*******************************************************************************
 * Constants
 ******************************************************************************/
#define GXR_SESSION \
      (gaim_prefs_get_int("/plugins/gtk/amc_grim/gaim-xmms-remote/session"))

#define GXR_STOCK_NEXT "gxr-next"
#define GXR_STOCK_PAUSE "gxr-pause"
#define GXR_STOCK_PLAY "gxr-play"
#define GXR_STOCK_PREVIOUS "gxr-previous"
#define GXR_STOCK_STOP "gxr-stop"
#define GXR_STOCK_XMMS "gxr-xmms"

/*******************************************************************************
 * Globals
 ******************************************************************************/
static GList *buttons = NULL;
static GtkIconFactory *icon_factory;
static GaimCmdId gxr_cmd;
static guint button_type_cb_id;

/*******************************************************************************
 * Callbacks
 ******************************************************************************/
static void
gxr_menu_play_cb(GtkMenuItem *item, gpointer data) {
      xmms_remote_play(GXR_SESSION);
}

static void
gxr_menu_pause_cb(GtkMenuItem *item, gpointer data) {
      xmms_remote_pause(GXR_SESSION);
}

static void
gxr_menu_stop_cb(GtkMenuItem *item, gpointer data) {
      xmms_remote_stop(GXR_SESSION);
}

static void
gxr_menu_next_cb(GtkMenuItem *item, gpointer data) {
      xmms_remote_playlist_next(GXR_SESSION);
}

static void
gxr_menu_prev_cb(GtkMenuItem *item, gpointer data) {
      xmms_remote_playlist_prev(GXR_SESSION);
}

static void
gxr_menu_repeat_cb(GtkMenuItem *item, gpointer data) {
      xmms_remote_toggle_repeat(GXR_SESSION);
}

static void
gxr_menu_shuffle_cb(GtkMenuItem *item, gpointer data) {
      xmms_remote_toggle_shuffle(GXR_SESSION);
}

static void
gxr_menu_playlist_cb(GtkMenuItem *item, gpointer data) {
      gint position = GPOINTER_TO_INT(data);

      xmms_remote_set_playlist_pos(GXR_SESSION, position);

      if(!xmms_remote_is_playing(GXR_SESSION))
            xmms_remote_play(GXR_SESSION);
}

/*******************************************************************************
 * Helpers
 ******************************************************************************/
static gchar *
gxr_format_info() {
      GString *str;
      gchar *ret, *song = NULL;
      const gchar *format;
      gint session, rate = 0, freq = 0, chan = 0;
      gint pos, length, volume, time_total, time_elapsed;
      gint min, sec;

      session = GXR_SESSION;
      
      pos = xmms_remote_get_playlist_pos(session);
      time_total= xmms_remote_get_playlist_time(session, pos);
      time_elapsed = xmms_remote_get_output_time(session);
      xmms_remote_get_info(session, &rate, &freq, &chan);
      length = xmms_remote_get_playlist_length(session);
      volume = xmms_remote_get_main_volume(session);
      song = xmms_remote_get_playlist_title(session, pos);

      str = g_string_new("");
      format = gaim_prefs_get_string("/plugins/gtk/amc_grim/gaim-xmms-remote/format");

      while(format) {
            if(format[0] != '%') {
                  str = g_string_append_c(str, format[0]);
                  format++;
                  continue;
            }

            format++;
            if(!format[0])
                  break;

            switch(format[0]) {
                  case '%':
                        str = g_string_append_c(str, '%');
                        break;
                  case 'C':
                        g_string_append_printf(str, "%d", chan);
                        break;
                  case 'F':
                        g_string_append_printf(str, "%g", (gfloat)freq / 1000.0f);
                        break;
                  case 'f':
                        g_string_append_printf(str, "%d", freq);
                        break;
                  case 'L':
                        g_string_append_printf(str, "%d", length);
                        break;
                  case 'P':
                        g_string_append_printf(str, "%d", pos + 1);
                        break;
                  case 'B':
                        g_string_append_printf(str, "%g", (gfloat)rate / 1000.0f);
                        break;
                  case 'b':
                        g_string_append_printf(str, "%d", rate);
                        break;
                  case 'T':
                        str = g_string_append(str, song);
                        break;
                  case 'V':
                        g_string_append_printf(str, "%d", volume);
                        break;
                  case 't':
                        min = (gint)(time_total / 60000);
                        sec = (gint)(time_total / 1000 % 60);
                        g_string_append_printf(str, "%d:%02d", min, sec);
                        break;
                  case 'e':
                        min = (gint)(time_elapsed / 60000);
                        sec = (gint)(time_elapsed / 1000 % 60);
                        g_string_append_printf(str, "%d:%02d", min, sec);
                        break;
                  case 'r':
                        min = (gint)((time_total - time_elapsed) / 60000);
                        sec = (gint)((time_total = time_elapsed) / 1000 % 60);
                        g_string_append_printf(str, "%d:%02d", min, sec);
                        break;
            }

            format++;
      }

      ret = str->str;
      g_string_free(str, FALSE);

      if(song)
            g_free(song);

      return ret;
}

static void
gxr_display_title(GaimConversation *conv) {
      GaimConversationType type;
      gchar *text = NULL;

      g_return_if_fail(conv);

      type = gaim_conversation_get_type(conv);

      text = gxr_format_info();

      if(!text)
            return;

      switch(type) {
            case GAIM_CONV_IM:
                  gaim_conv_im_send(GAIM_CONV_IM(conv), text);
                  break;
            case GAIM_CONV_CHAT:
                  gaim_conv_chat_send(GAIM_CONV_CHAT(conv), text);
                  break;
            case GAIM_CONV_UNKNOWN:
            case GAIM_CONV_MISC:
            default:
                  break;
      }

      if(text)
            g_free(text);
}

static void
gxr_menu_display_title_cb(GtkMenuItem *item, gpointer data) {
      GaimConversation *conv;

      conv = (GaimConversation *)data;

      gxr_display_title(conv);
}

static GtkWidget *
gxr_make_item(GtkWidget *menu, const gchar *text, GtkSignalFunc sf,
                    gpointer data)
{
      GtkWidget *item;

      item = gtk_menu_item_new_with_label(text);
      if(menu != NULL)
            gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
      gtk_widget_show(item);

      if(sf != NULL)
            g_signal_connect(G_OBJECT(item), "activate", sf, data);

      return item;
}

static void
gxr_make_playlist(GtkWidget *menu_item) {
      GtkWidget *menu, *item;
      gint i, count, current;
      gint session = GXR_SESSION;
      gchar *title, *song;

      menu = gtk_menu_new();

      count = xmms_remote_get_playlist_length(session);
      current = xmms_remote_get_playlist_pos(session);

      for(i = 0; i < count; i++) {
            song = xmms_remote_get_playlist_title(session, i);
            title = g_strdup_printf("%d. %s", i + 1, song);
            g_free(song);

            if(i == current)
                  gaim_new_check_item(menu, title, G_CALLBACK(gxr_menu_playlist_cb),
                                                GINT_TO_POINTER(i), TRUE);
            else
                  item = gxr_make_item(menu, title, G_CALLBACK(gxr_menu_playlist_cb),
                                                 GINT_TO_POINTER(i));

            g_free(title);
      }

      gtk_widget_show_all(menu);

      gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), menu);

      if(count == 0)
            gtk_widget_set_sensitive(menu_item, FALSE);
}

#if 0 /* #ifdef DEBUG */
static void
gxr_menu_dump_button_list(GtkMenuItem *item, gpointer data) {
      GaimConversation *conv;
      GtkWidget *button;
      GList *l;

      for(l = buttons; l; l = l->next) {
            button = l->data;

            conv = g_object_get_data(G_OBJECT(button), "conv");

            gaim_debug_info("gxr", "conv %s\n", (conv) ? conv->name : "(NULL)");
      }
}
#endif /* DEBUG */

static GtkWidget *
gxr_make_menu(GaimConversation *conv) {
      GtkWidget *menu, *item;
      gint session = GXR_SESSION;

      menu = gtk_menu_new();

      if(!xmms_remote_is_running(session)) {
            item = gaim_new_item_from_stock(menu, "Please start XMMS",
                                                            GXR_STOCK_XMMS, NULL, NULL, 0, 0, NULL);
            gtk_widget_set_sensitive(item, FALSE);

            return menu;
      }

      /* play */
      item = gaim_new_item_from_stock(menu, "Play", GXR_STOCK_PLAY,
                                                      G_CALLBACK(gxr_menu_play_cb), NULL, 0,
                                                      0, NULL);
      if(xmms_remote_is_playing(session) && !xmms_remote_is_paused(session))
            gtk_widget_set_sensitive(item, FALSE);

      /* pause */
      item = gaim_new_item_from_stock(menu, "Pause", GXR_STOCK_PAUSE,
                                                      G_CALLBACK(gxr_menu_pause_cb), NULL, 0,
                                                      0, NULL);
      if(!xmms_remote_is_playing(session) && !xmms_remote_is_paused(session))
            gtk_widget_set_sensitive(item, FALSE);
      if(xmms_remote_is_paused(session))
            gtk_widget_set_sensitive(item, FALSE);

      /* stop */
      item = gaim_new_item_from_stock(menu, "Stop", GXR_STOCK_STOP,
                                                      G_CALLBACK(gxr_menu_stop_cb), NULL, 0,
                                                      0, NULL);
      if(!xmms_remote_is_playing(session) && !xmms_remote_is_paused(session))
            gtk_widget_set_sensitive(item, FALSE);

      /* next */
      gaim_new_item_from_stock(menu, "Next", GXR_STOCK_NEXT,
                                           G_CALLBACK(gxr_menu_next_cb), NULL, 0, 0,
                                           NULL);

      /* previous */
      gaim_new_item_from_stock(menu, "Previous", GXR_STOCK_PREVIOUS,
                                           G_CALLBACK(gxr_menu_prev_cb), NULL, 0, 0,
                                           NULL);

      /* separator */
      gaim_separator(menu);

      /* repeat */
      gaim_new_check_item(menu, "Repeat", G_CALLBACK(gxr_menu_repeat_cb),
                                    NULL, xmms_remote_is_repeat(session));

      /* shuffle */
      gaim_new_check_item(menu, "Shuffle", G_CALLBACK(gxr_menu_shuffle_cb),
                                    NULL, xmms_remote_is_shuffle(session));

      if(gaim_prefs_get_bool("/plugins/gtk/amc_grim/gaim-xmms-remote/show_playlist")) {
            /* separator */
            gaim_separator(menu);

            /* playlist */
            item = gxr_make_item(menu, "Playlist", NULL, NULL);
            gxr_make_playlist(item);
      }

      /* separator */
      gaim_separator(menu);

      /* title */
      item = gxr_make_item(menu, "Display title",
                                     G_CALLBACK(gxr_menu_display_title_cb),
                                     (gpointer)conv); 

#if 0 /* #ifdef DEBUG */
      gaim_separator(menu);
      item = gxr_make_item(menu, "dump button list",
                                     G_CALLBACK(gxr_menu_dump_button_list),
                                     NULL);
#endif /* DEBUG */

      return menu;
}

static void
gxr_button_clicked_cb(GtkButton *button, gpointer data) {
      GaimConversation *conv;
      GtkWidget *menu;

      conv = g_object_get_data(G_OBJECT(button), "conv");
      menu = gxr_make_menu(conv);

      gtk_widget_grab_focus(GAIM_GTK_CONVERSATION(conv)->entry);

      gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0,
                           gtk_get_current_event_time());
}

static void
gxr_add_button(GaimConversation *conv) {
      GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv);
      GaimConversationType type = gaim_conversation_get_type(conv);
      GtkWidget *button = NULL;
      GList *l;

      if(type != GAIM_CONV_IM && type != GAIM_CONV_CHAT)
            return;

      if(type == GAIM_CONV_IM &&
         !gaim_prefs_get_bool("/plugins/gtk/amc_grim/gaim-xmms-remote/im"))
            return;

      if(type == GAIM_CONV_CHAT &&
         !gaim_prefs_get_bool("/plugins/gtk/amc_grim/gaim-xmms-remote/chat"))
            return;

      for(l = buttons; l; l = l->next) {
            button = l->data;
            if(g_object_get_data(G_OBJECT(button), "conv") == conv)
                  return;
      }

      button = gaim_gtkconv_button_new(GXR_STOCK_XMMS, "XMMS", "XMMS Control",
                                                       gtkconv->tooltips, gxr_button_clicked_cb,
                                                       (gpointer)conv);

      g_object_set_data(G_OBJECT(button), "conv", conv);

      buttons = g_list_append(buttons, (gpointer)button);

      gtk_box_pack_end(GTK_BOX(gtkconv->bbox), button, TRUE, TRUE, 0);
      gtk_widget_show(button);
      gtk_size_group_add_widget(gtkconv->sg, button);
}

static void
gxr_show_buttons(GaimConversationType type) {
      GList *wins, *convs;
      GaimConvWindow *window;
      GaimConversation *conv;

      for(wins = gaim_get_windows(); wins; wins = wins->next) {
            window = (GaimConvWindow *)wins->data;

            for(convs = gaim_conv_window_get_conversations(window); convs;
                  convs = convs->next)
            {
                  conv = (GaimConversation *)convs->data;
                  if(gaim_conversation_get_type(conv) == type)
                        gxr_add_button(conv);
            }
      }
}

static void
gxr_hide_buttons(GaimConversationType type) {
      GaimConversation *conv;
      GtkWidget *button;
      GList *l, *l_next;

      for(l = buttons; l; l = l_next) {
            l_next = l->next;

            button = GTK_WIDGET(l->data);
            conv = g_object_get_data(G_OBJECT(button), "conv");

            if(!conv) {
                  buttons = g_list_remove(buttons, button);
            } else if(gaim_conversation_get_type(conv) == type) {
                  gtk_widget_destroy(button);
                  buttons = g_list_remove(buttons, button);
            }
      }
}

static void
gxr_button_show_cb(const char *name, GaimPrefType type, gpointer val,
                           gpointer data)
{
      gboolean show = GPOINTER_TO_INT(val);

      if(show)
            gxr_show_buttons(GPOINTER_TO_INT(data));
      else
            gxr_hide_buttons(GPOINTER_TO_INT(data));
}

static void
gxr_button_type_changed_cb(const char *name, GaimPrefType type,
                                       gpointer val, gpointer data)
{
      GaimConversation *conv;
      GaimGtkConversation *gtkconv;
      GtkWidget *button;
      GList *l, *tmp = NULL;

      for(l = buttons; l != NULL; l = l->next) {
            button = GTK_WIDGET(l->data);
            conv = g_object_get_data(G_OBJECT(button), "conv");

            gtkconv = GAIM_GTK_CONVERSATION(conv);

            button = gaim_gtkconv_button_new(GXR_STOCK_XMMS, "XMMS", "XMMS Control",
                                                             gtkconv->tooltips,
                                                             gxr_button_clicked_cb, (gpointer)conv);

            gtk_box_pack_end(GTK_BOX(gtkconv->bbox), button, TRUE, TRUE, 0);
            gtk_size_group_add_widget(gtkconv->sg, button);
            gtk_widget_show(button);
            g_object_set_data(G_OBJECT(button), "conv", conv);
            tmp = g_list_append(tmp, (gpointer)button);
      }
      g_list_free(buttons);
      buttons = tmp;
}

static void
gxr_popup_cb(GtkWidget *w, GtkMenu *menu, gpointer data) {
      GtkWidget *item, *submenu;

      gaim_separator(GTK_WIDGET(menu));

      item = gaim_new_item_from_stock(GTK_WIDGET(menu), "Gaim-XMMS-Remote",
                                                      GXR_STOCK_XMMS, NULL, NULL, 0, 0, NULL);

      submenu = gxr_make_menu((GaimConversation*)data);
      gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);

      gtk_widget_show(item);
}

void
gxr_disconnect_popup_cb(GaimConversation *conv) {
      GaimGtkConversation *gtkconv;
      gulong handle;

      if((gtkconv = GAIM_GTK_CONVERSATION(conv)) == NULL)
            return;

      handle = (gulong)gaim_conversation_get_data(conv, "gxr-popup-handle");
      if(handle == 0)
            return;

      g_signal_handler_disconnect(G_OBJECT(gtkconv->entry), handle);
}

static void
gxr_hook_popups() {
      GList *wins, *convs;
      GaimConvWindow *window;
      GaimConversation *conv;
      gulong handle;

      for(wins = gaim_get_windows(); wins; wins = wins->next) {
            window = (GaimConvWindow *)wins->data;

            for(convs = gaim_conv_window_get_conversations(window); convs;
                  convs = convs->next)
            {
                  GtkWidget *entry;

                  conv = (GaimConversation *)convs->data;
                  entry = GAIM_GTK_CONVERSATION(conv)->entry;

                  handle = g_signal_connect(G_OBJECT(entry), "populate-popup",
                                                        G_CALLBACK(gxr_popup_cb), conv);
                  gaim_conversation_set_data(conv, "gxr-popup-handle",
                                                         (gpointer)handle);
            }
      }
}

static void
gxr_conv_created_cb(GaimConversation *conv, gpointer data) {
      GaimGtkConversation *gtkconv;
      gulong handle;

      if((gtkconv = GAIM_GTK_CONVERSATION(conv)) == NULL)
            return;

      gxr_add_button(conv);

      handle = g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
                                            G_CALLBACK(gxr_popup_cb), (gpointer)conv);

      gaim_conversation_set_data(conv, "gxr-popup-handle", (gpointer)handle);
}

static void
gxr_conv_destroyed_cb(GaimConversation *conv, gpointer data) {
      GaimConversation *stored_conv;
      GtkWidget *button;
      GList *l, *l_next;

      for(l = buttons; l != NULL; l = l_next) {
            l_next = l->next;

            button = GTK_WIDGET(l->data);
            stored_conv = (GaimConversation *)g_object_get_data(G_OBJECT(button),
                                                                                          "conv");

            if(stored_conv == conv) {
                  gtk_widget_destroy(button);

                  buttons = g_list_remove(buttons, l->data);
                  break;
            }
      }
}

static GaimCmdRet
gxr_cmd_cb(GaimConversation *c, const gchar *cmd, gchar **args, gchar **error, void *data) {
      gchar *lower;
      gint session = GXR_SESSION;

      if(!xmms_remote_is_running(session)) {
            *error = g_strdup("XMMS is not running");
            return GAIM_CMD_RET_FAILED;
      }

      if(!*args && !args[0]) {
            *error = g_strdup("eek!");
            return GAIM_CMD_RET_FAILED;
      }

      lower = g_ascii_strdown(args[0], strlen(args[0]));

      if(strcmp(lower, "play") == 0) {
            xmms_remote_play(session);
      } else if(!strcmp(lower, "pause")) {
            xmms_remote_pause(session);
      } else if(!strcmp(lower, "stop")) {
            xmms_remote_stop(session);
      } else if(!strcmp(lower, "next")) {
            xmms_remote_playlist_next(session);
      } else if(!strcmp(lower, "prev")) {
            xmms_remote_playlist_prev(session);
      } else if(!strcmp(lower, "info")) {
            gxr_display_title(c);
      } else if(!strcmp(lower, "repeat")) {
            xmms_remote_toggle_repeat(session);
      } else if(!strcmp(lower, "shuffle")) {
            xmms_remote_toggle_shuffle(session);
      } else if(!strcmp(lower, "show")) {
            xmms_remote_main_win_toggle(session, TRUE);
      } else if(!strcmp(lower, "hide")) {
            xmms_remote_main_win_toggle(session, FALSE);
      } else {
            *error = g_strdup("unknown argument");
            return GAIM_CMD_RET_FAILED;
      }

      g_free(lower);

      return GAIM_CMD_RET_OK;
}

/*******************************************************************************
 * Prefs stuff
 ******************************************************************************/
static GtkWidget *
gxr_make_label(const gchar *text, GtkSizeGroup *sg) {
      GtkWidget *label;

      label = gtk_label_new_with_mnemonic(text);
      gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
      gtk_widget_show(label);

      if(sg)
            gtk_size_group_add_widget(sg, label);

      return label;
}

static GtkWidget *
gxr_get_config_frame(GaimPlugin *plugin) {
      GtkWidget *vbox, *hbox, *frame, *label;
      GtkSizeGroup *sg;

      vbox = gtk_vbox_new(FALSE, 6);
      gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);

      frame = gaim_gtk_make_frame(vbox, "Info");

      gaim_gtk_prefs_labeled_entry(frame, "Info Format:",
                                                 "/plugins/gtk/amc_grim/gaim-xmms-remote/format",
                                                 NULL);

      sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);

      hbox = gtk_hbox_new(FALSE, 6);
      gtk_box_pack_start(GTK_BOX(frame), hbox, FALSE, FALSE, 0);
      gtk_widget_show(hbox);

      label = gxr_make_label("%T: Song title", sg);
      gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

      label = gxr_make_label("%C: Number of channels", NULL);
      gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

      hbox = gtk_hbox_new(FALSE, 6);
      gtk_box_pack_start(GTK_BOX(frame), hbox, FALSE, FALSE, 0);
      gtk_widget_show(hbox);

      label = gxr_make_label("%P: Current song playlist number", sg);
      gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

      label = gxr_make_label("%L: Total songs in the playlist", NULL);
      gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

      hbox = gtk_hbox_new(FALSE, 6);
      gtk_box_pack_start(GTK_BOX(frame), hbox, FALSE, FALSE, 0);
      gtk_widget_show(hbox);

      label = gxr_make_label("%t: Total time", sg);
      gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

      label = gxr_make_label("%e: Elapsed time", sg);
      gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
      
      hbox = gtk_hbox_new(FALSE, 6);
      gtk_box_pack_start(GTK_BOX(frame), hbox, FALSE, FALSE, 0);
      gtk_widget_show(hbox);

      label = gxr_make_label("%r: Remaining time", sg);
      gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

      label = gxr_make_label("%V: Current volume", sg);
      gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

      hbox = gtk_hbox_new(FALSE, 6);
      gtk_box_pack_start(GTK_BOX(frame), hbox, FALSE, FALSE, 0);
      gtk_widget_show(hbox);
      
      label = gxr_make_label("%f: Frequency in Hz", sg);
      gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

      label = gxr_make_label("%F: Frequency in kHz", NULL);
      gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

      hbox = gtk_hbox_new(FALSE, 6);
      gtk_box_pack_start(GTK_BOX(frame), hbox, FALSE, FALSE, 0);
      gtk_widget_show(hbox);

      label = gxr_make_label("%b: Bitrate in bps", sg);
      gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

      label = gxr_make_label("%B: Bitrate in kBps", NULL);
      gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

      frame = gaim_gtk_make_frame(vbox, "Appearance");

      gaim_gtk_prefs_checkbox("Show playlist in the menu",
                                          "/plugins/gtk/amc_grim/gaim-xmms-remote/show_playlist",
                                          frame);

      gaim_gtk_prefs_checkbox("Show button in IMs",
                                          "/plugins/gtk/amc_grim/gaim-xmms-remote/im",
                                          frame);

      gaim_gtk_prefs_checkbox("Show button in Chats",
                                          "/plugins/gtk/amc_grim/gaim-xmms-remote/chat",
                                          frame);

      frame = gaim_gtk_make_frame(vbox, "Advanced");

      gaim_gtk_prefs_labeled_spin_button(frame, "XMMS instance to control",
                                                   "/plugins/gtk/amc_grim/gaim-xmms-remote/session",
                                                   0, 65535, NULL);

      gtk_widget_show_all(vbox);

      return vbox;
}

/*******************************************************************************
 * Stock stuff
 ******************************************************************************/
static gchar *
gxr_file_name(const gchar *file_name) {
      return g_build_filename(DATADIR, "pixmaps", "gaim", "gxr", file_name,
                                          NULL);
}

static void
gxr_add_to_stock(const gchar *file_name, const gchar *stock_name) {
      GtkIconSet *icon_set;
      GdkPixbuf *pixbuf;
      gchar *file = gxr_file_name(file_name);

      pixbuf = gdk_pixbuf_new_from_file(file, NULL);
      g_free(file);

      icon_set = gtk_icon_set_new_from_pixbuf(pixbuf);
      g_object_unref(G_OBJECT(pixbuf));

      gtk_icon_factory_add(icon_factory, stock_name, icon_set);
      gtk_icon_set_unref(icon_set);
}

static void
gxr_init_stock() {
      icon_factory = gtk_icon_factory_new();
      gtk_icon_factory_add_default(icon_factory);

      gxr_add_to_stock("next.png", GXR_STOCK_NEXT);
      gxr_add_to_stock("pause.png", GXR_STOCK_PAUSE);
      gxr_add_to_stock("play.png", GXR_STOCK_PLAY);
      gxr_add_to_stock("previous.png", GXR_STOCK_PREVIOUS);
      gxr_add_to_stock("stop.png", GXR_STOCK_STOP);
      gxr_add_to_stock("xmms.png", GXR_STOCK_XMMS);
}

/*******************************************************************************
 * Plugin stuff
 ******************************************************************************/
static gboolean
gxr_load(GaimPlugin *plugin) {
      void *conv_handle = gaim_conversations_get_handle();
      const gchar *help = "<pre>gxr &lt;[play][pause][stop][next][prev][repeat][shuffle][show][hide][info]&gt;\n"
                                    "Play     Starts playback\n"
                                    "Pause    Pauses playback\n"
                                    "Stop     Stops playback\n"
                                    "Next     Goes to the next song in the playlist\n"
                                    "Prev     Goes to the previous song in the playlist\n"
                                    "Repeat   Toggles repeat\n"
                                    "Shuffle  Toggles shuffling\n"
                                    "Show     Show the XMMS window\n"
                                    "Hide     Hide the XMMS window\n"
                                    "Info     Displays currently playing song in the conversation\n</pre>";

      /* init our stock */
      gxr_init_stock();

      /* connect to the signals we need.. */
      gaim_signal_connect(conv_handle, "conversation-created", plugin,
                                    GAIM_CALLBACK(gxr_conv_created_cb), NULL);

      gaim_signal_connect(conv_handle, "deleting-conversation", plugin,
                                    GAIM_CALLBACK(gxr_conv_destroyed_cb), NULL);

      button_type_cb_id = gaim_prefs_connect_callback(
                                          "/gaim/gtk/conversations/button_type",
                                          gxr_button_type_changed_cb, NULL);

      gaim_prefs_connect_callback("/plugins/gtk/amc_grim/gaim-xmms-remote/im",
                                                gxr_button_show_cb,
                                                GINT_TO_POINTER(GAIM_CONV_IM));

      gaim_prefs_connect_callback("/plugins/gtk/amc_grim/gaim-xmms-remote/chat",
                                                gxr_button_show_cb,
                                                GINT_TO_POINTER(GAIM_CONV_CHAT));

      if(gaim_prefs_get_bool("/plugins/gtk/amc_grim/gaim-xmms-remote/im"))
            gxr_show_buttons(GAIM_CONV_IM);

      if(gaim_prefs_get_bool("/plugins/gtk/amc_grim/gaim-xmms-remote/chat"))
            gxr_show_buttons(GAIM_CONV_CHAT);

      /* register our command */
      gxr_cmd = gaim_cmd_register("gxr", "w", GAIM_CMD_P_PLUGIN,
                                                GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_CHAT, NULL,
                                                gxr_cmd_cb, help, NULL);

      /* hijack the popup menus in the imhtmls */
      gxr_hook_popups();

      return TRUE;
}

static gboolean
gxr_unload(GaimPlugin *plugin) {
      gaim_prefs_disconnect_callback(button_type_cb_id);

      /* remove our buttons */
      gxr_hide_buttons(GAIM_CONV_IM);
      gxr_hide_buttons(GAIM_CONV_CHAT);

      g_list_free(buttons);
      buttons = NULL;

      /* remove our popup menu item */
      gaim_conversation_foreach(gxr_disconnect_popup_cb);
      /* remove our icons */
      gtk_icon_factory_remove_default(icon_factory);

      /* remove our command */
      gaim_cmd_unregister(gxr_cmd);

      return TRUE;
}

static void
init_plugin(GaimPlugin *plugin) {
      gaim_prefs_add_none("/plugins/gtk/amc_grim");
      gaim_prefs_add_none("/plugins/gtk/amc_grim/gaim-xmms-remote");
      gaim_prefs_add_string("/plugins/gtk/amc_grim/gaim-xmms-remote/format",
                                      "/me is listening to %T");
      gaim_prefs_add_int("/plugins/gtk/amc_grim/gaim-xmms-remote/session", 0);
      gaim_prefs_add_bool("/plugins/gtk/amc_grim/gaim-xmms-remote/show_playlist", TRUE);
      gaim_prefs_add_bool("/plugins/gtk/amc_grim/gaim-xmms-remote/im", TRUE);
      gaim_prefs_add_bool("/plugins/gtk/amc_grim/gaim-xmms-remote/chat", TRUE);
}

static GaimGtkPluginUiInfo ui_info = { gxr_get_config_frame };

static GaimPluginInfo gxr_info = {
      GAIM_PLUGIN_MAGIC,                                                      /* Don't                */
      GAIM_MAJOR_VERSION,                                                     /* fear the       */
      GAIM_MINOR_VERSION,                                                     /* reaper         */
      GAIM_PLUGIN_STANDARD,                                             /* type                 */
      GAIM_GTK_PLUGIN_TYPE,                                             /* ui requirement */
      0,                                                                            /* flags                */
      NULL,                                                                   /* dependencies   */
      GAIM_PRIORITY_DEFAULT,                                            /* priority       */

      "Gtk-amc_grim-Gaim-XMMS-Remote",                                  /* id             */
      "Gaim-XMMS-Remote",                                                     /* name                 */
      GXR_VERSION,                                                            /* version        */
      "Control XMMS from Gaim conversations",                           /* summary        */
      "A small plugin at adds a button to the\n"
      "gaim conversation windows, so that you\n"
      "can control XMMS from within gaim.",                             /* description    */

      "Gary Kramlich <amc_grim@users.sf.net>",                          /* author         */
      "http://guifications.sourceforge.net/Gaim-XMMS-Remote/",    /* homepage       */

      gxr_load,                                                               /* load                 */
      gxr_unload,                                                             /* unload         */
      NULL,                                                                   /* destroy        */

      &ui_info,                                                               /* ui info        */
      NULL,                                                                   /* extra info           */
      NULL                                                                    /* actions info   */
};

GAIM_INIT_PLUGIN(Gaim-XMMS-Remote, init_plugin, gxr_info)

Generated by  Doxygen 1.6.0   Back to index