pidgin/purple-plugin-pack

3bda18a8dfd6
propagate from branch 'org.guifications.plugins' (head bb8f2716df2e0f3881de6a7afbaa1ac4c39a23d0)
to branch 'org.guifications.plugins.smartear' (head de43ae536d0fbb968cf2d4c95d5d9e2adbc29cc4)
--- a/configure.ac Sun Aug 19 04:05:05 2007 -0400
+++ b/configure.ac Sun Aug 19 04:42:58 2007 -0400
@@ -336,6 +336,7 @@
simfix/Makefile
slashexec/Makefile
snpp/Makefile
+ smartear/Makefile
sslinfo/Makefile
stocker/Makefile
switchspell/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smartear/Makefile.am Sun Aug 19 04:42:58 2007 -0400
@@ -0,0 +1,36 @@
+EXTRA_DIST= \
+ .build \
+ .purple-plugin \
+ .pidgin-plugin \
+ .finch-plugin \
+ Makefile.mingw
+
+smarteardir = $(PIDGIN_LIBDIR)
+
+smartear_la_LDFLAGS = -module -avoid-version
+
+if HAVE_PURPLE
+smartear_LTLIBRARIES = smartear.la
+smartear_la_SOURCES = smartear.c
+smartear_la_LIBADD = $(PURPLE_LIBS)
+endif
+
+if HAVE_PIDGIN
+gtksmartear_LTLIBRARIES = gtksmartear.la
+gtksmartear_la_SOURCES = gtksmartear.c
+gtksmartear_la_LIBADD = $(PIDGIN_LIBS)
+endif
+
+if HAVE_FINCH
+gntsmartear_LTLIBRARIES = gntsmartear.la
+gntsmartear_la_SOURCES = gntsmartear.c
+gntsmartear_la_LIBADD = $(FINCH_LIBS)
+endif
+
+AM_CPPFLAGS = \
+ -DLIBDIR=\"$(PURPLE_LIBDIR)\" \
+ -DDATADIR=\"$(PURPLE_DATADIR)\" \
+ -DPIXMAPSDIR=\"$(PURPLE_PIXMAPSDIR)\" \
+ $(DEBUG_CFLAGS) \
+ $(PURPLE_CFLAGS)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smartear/interface.c Sun Aug 19 04:42:58 2007 -0400
@@ -0,0 +1,566 @@
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include "callbacks.h"
+#include "interface.h"
+#include "support.h"
+
+#define GLADE_HOOKUP_OBJECT(component,widget,name) \
+ g_object_set_data_full (G_OBJECT (component), name, \
+ gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref)
+
+#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \
+ g_object_set_data (G_OBJECT (component), name, widget)
+
+GtkWidget*
+create_config (void)
+{
+ GtkWidget *config;
+ GtkWidget *config_vbox;
+ GtkWidget *frame1;
+ GtkWidget *table1;
+ GtkWidget *label9;
+ GtkObject *delay_spin_adj;
+ GtkWidget *delay_spin;
+ GtkWidget *focus_but;
+ GtkWidget *timer_but;
+ GtkWidget *label8;
+ GtkWidget *frame2;
+ GtkWidget *table2;
+ GtkWidget *delete_but;
+ GtkWidget *new_but;
+ GtkWidget *scrolledwindow2;
+ GtkWidget *treeview;
+ GtkWidget *edit_but;
+ GtkWidget *label7;
+ GtkWidget *hbuttonbox1;
+ GtkWidget *revert_but;
+ GtkWidget *save_but;
+
+ config = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (config), "SmartEar Configuration");
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (config), TRUE);
+
+ config_vbox = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (config_vbox);
+ gtk_container_add (GTK_CONTAINER (config), config_vbox);
+ gtk_widget_set_size_request (config_vbox, -1, 640);
+
+ frame1 = gtk_frame_new (NULL);
+ gtk_widget_show (frame1);
+ gtk_box_pack_start (GTK_BOX (config_vbox), frame1, FALSE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (frame1), 5);
+
+ table1 = gtk_table_new (3, 2, FALSE);
+ gtk_widget_show (table1);
+ gtk_container_add (GTK_CONTAINER (frame1), table1);
+ gtk_container_set_border_width (GTK_CONTAINER (table1), 5);
+ gtk_table_set_row_spacings (GTK_TABLE (table1), 10);
+ gtk_table_set_col_spacings (GTK_TABLE (table1), 10);
+
+ label9 = gtk_label_new ("Time delay between playing sounds for a particular buddy:");
+ gtk_widget_show (label9);
+ gtk_table_attach (GTK_TABLE (table1), label9, 0, 1, 0, 1,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label9), 0, 0.5);
+
+ delay_spin_adj = gtk_adjustment_new (60, 0, 1000000, 1, 10, 10);
+ delay_spin = gtk_spin_button_new (GTK_ADJUSTMENT (delay_spin_adj), 1, 0);
+ gtk_widget_show (delay_spin);
+ gtk_table_attach (GTK_TABLE (table1), delay_spin, 1, 2, 0, 1,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (delay_spin), GTK_UPDATE_IF_VALID);
+
+ focus_but = gtk_check_button_new_with_mnemonic ("Don't play sounds for the conversation that has focus.");
+ gtk_widget_show (focus_but);
+ gtk_table_attach (GTK_TABLE (table1), focus_but, 0, 2, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ timer_but = gtk_check_button_new_with_mnemonic ("Also play sounds if you don't respond to a particular IM within a delay period.");
+ gtk_widget_show (timer_but);
+ gtk_table_attach (GTK_TABLE (table1), timer_but, 0, 2, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ label8 = gtk_label_new ("Options");
+ gtk_widget_show (label8);
+ gtk_frame_set_label_widget (GTK_FRAME (frame1), label8);
+
+ frame2 = gtk_frame_new (NULL);
+ gtk_widget_show (frame2);
+ gtk_box_pack_start (GTK_BOX (config_vbox), frame2, TRUE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (frame2), 5);
+
+ table2 = gtk_table_new (2, 3, FALSE);
+ gtk_widget_show (table2);
+ gtk_container_add (GTK_CONTAINER (frame2), table2);
+ gtk_container_set_border_width (GTK_CONTAINER (table2), 5);
+ gtk_table_set_row_spacings (GTK_TABLE (table2), 10);
+ gtk_table_set_col_spacings (GTK_TABLE (table2), 10);
+
+ delete_but = gtk_button_new_from_stock ("gtk-delete");
+ gtk_widget_show (delete_but);
+ gtk_table_attach (GTK_TABLE (table2), delete_but, 2, 3, 1, 2,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+ GTK_WIDGET_SET_FLAGS (delete_but, GTK_CAN_DEFAULT);
+
+ new_but = gtk_button_new_from_stock ("gtk-new");
+ gtk_widget_show (new_but);
+ gtk_table_attach (GTK_TABLE (table2), new_but, 0, 1, 1, 2,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+ GTK_WIDGET_SET_FLAGS (new_but, GTK_CAN_DEFAULT);
+
+ scrolledwindow2 = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_show (scrolledwindow2);
+ gtk_table_attach (GTK_TABLE (table2), scrolledwindow2, 0, 3, 0, 1,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow2), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+
+ treeview = gtk_tree_view_new ();
+ gtk_widget_show (treeview);
+ gtk_container_add (GTK_CONTAINER (scrolledwindow2), treeview);
+
+ edit_but = gtk_button_new_from_stock ("gtk-properties");
+ gtk_widget_show (edit_but);
+ gtk_table_attach (GTK_TABLE (table2), edit_but, 1, 2, 1, 2,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+
+ label7 = gtk_label_new ("Entries");
+ gtk_widget_show (label7);
+ gtk_frame_set_label_widget (GTK_FRAME (frame2), label7);
+
+ hbuttonbox1 = gtk_hbutton_box_new ();
+ gtk_widget_show (hbuttonbox1);
+ gtk_box_pack_start (GTK_BOX (config_vbox), hbuttonbox1, FALSE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (hbuttonbox1), 5);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox1), GTK_BUTTONBOX_SPREAD);
+
+ revert_but = gtk_button_new_from_stock ("gtk-revert-to-saved");
+ gtk_widget_show (revert_but);
+ gtk_container_add (GTK_CONTAINER (hbuttonbox1), revert_but);
+ GTK_WIDGET_SET_FLAGS (revert_but, GTK_CAN_DEFAULT);
+
+ save_but = gtk_button_new_from_stock ("gtk-save");
+ gtk_widget_show (save_but);
+ gtk_container_add (GTK_CONTAINER (hbuttonbox1), save_but);
+ GTK_WIDGET_SET_FLAGS (save_but, GTK_CAN_DEFAULT);
+
+ g_signal_connect ((gpointer) config_vbox, "destroy",
+ G_CALLBACK (on_config_destroy),
+ NULL);
+ g_signal_connect ((gpointer) delay_spin, "changed",
+ G_CALLBACK (on_delay_changed),
+ NULL);
+ g_signal_connect ((gpointer) focus_but, "toggled",
+ G_CALLBACK (on_focus_toggled),
+ NULL);
+ g_signal_connect ((gpointer) timer_but, "toggled",
+ G_CALLBACK (on_timer_toggled),
+ NULL);
+ g_signal_connect ((gpointer) delete_but, "clicked",
+ G_CALLBACK (on_delete_clicked),
+ NULL);
+ g_signal_connect ((gpointer) new_but, "clicked",
+ G_CALLBACK (on_new_clicked),
+ NULL);
+ g_signal_connect ((gpointer) edit_but, "clicked",
+ G_CALLBACK (on_edit_clicked),
+ NULL);
+ g_signal_connect ((gpointer) revert_but, "clicked",
+ G_CALLBACK (on_revert_clicked),
+ NULL);
+ g_signal_connect ((gpointer) save_but, "clicked",
+ G_CALLBACK (on_save_clicked),
+ NULL);
+
+ /* Store pointers to all widgets, for use by lookup_widget(). */
+ GLADE_HOOKUP_OBJECT_NO_REF (config, config, "config");
+ GLADE_HOOKUP_OBJECT (config, config_vbox, "config_vbox");
+ GLADE_HOOKUP_OBJECT (config, frame1, "frame1");
+ GLADE_HOOKUP_OBJECT (config, table1, "table1");
+ GLADE_HOOKUP_OBJECT (config, label9, "label9");
+ GLADE_HOOKUP_OBJECT (config, delay_spin, "delay_spin");
+ GLADE_HOOKUP_OBJECT (config, focus_but, "focus_but");
+ GLADE_HOOKUP_OBJECT (config, timer_but, "timer_but");
+ GLADE_HOOKUP_OBJECT (config, label8, "label8");
+ GLADE_HOOKUP_OBJECT (config, frame2, "frame2");
+ GLADE_HOOKUP_OBJECT (config, table2, "table2");
+ GLADE_HOOKUP_OBJECT (config, delete_but, "delete_but");
+ GLADE_HOOKUP_OBJECT (config, new_but, "new_but");
+ GLADE_HOOKUP_OBJECT (config, scrolledwindow2, "scrolledwindow2");
+ GLADE_HOOKUP_OBJECT (config, treeview, "treeview");
+ GLADE_HOOKUP_OBJECT (config, edit_but, "edit_but");
+ GLADE_HOOKUP_OBJECT (config, label7, "label7");
+ GLADE_HOOKUP_OBJECT (config, hbuttonbox1, "hbuttonbox1");
+ GLADE_HOOKUP_OBJECT (config, revert_but, "revert_but");
+ GLADE_HOOKUP_OBJECT (config, save_but, "save_but");
+
+ return config;
+}
+
+GtkWidget*
+create_file_browse (void)
+{
+ GtkWidget *file_browse;
+ GtkWidget *ok_button1;
+ GtkWidget *cancel_button1;
+
+ file_browse = gtk_file_selection_new ("Select Sound");
+ gtk_container_set_border_width (GTK_CONTAINER (file_browse), 10);
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (file_browse), TRUE);
+ gtk_window_set_type_hint (GTK_WINDOW (file_browse), GDK_WINDOW_TYPE_HINT_DIALOG);
+
+ ok_button1 = GTK_FILE_SELECTION (file_browse)->ok_button;
+ gtk_widget_show (ok_button1);
+ GTK_WIDGET_SET_FLAGS (ok_button1, GTK_CAN_DEFAULT);
+
+ cancel_button1 = GTK_FILE_SELECTION (file_browse)->cancel_button;
+ gtk_widget_show (cancel_button1);
+ GTK_WIDGET_SET_FLAGS (cancel_button1, GTK_CAN_DEFAULT);
+
+ g_signal_connect ((gpointer) file_browse, "destroy",
+ G_CALLBACK (on_file_browse_destroy),
+ NULL);
+ g_signal_connect ((gpointer) ok_button1, "clicked",
+ G_CALLBACK (on_browse_ok_clicked),
+ NULL);
+ g_signal_connect_swapped ((gpointer) ok_button1, "clicked",
+ G_CALLBACK (gtk_widget_destroy),
+ GTK_OBJECT (file_browse));
+ g_signal_connect_swapped ((gpointer) cancel_button1, "clicked",
+ G_CALLBACK (gtk_widget_destroy),
+ GTK_OBJECT (file_browse));
+
+ /* Store pointers to all widgets, for use by lookup_widget(). */
+ GLADE_HOOKUP_OBJECT_NO_REF (file_browse, file_browse, "file_browse");
+ GLADE_HOOKUP_OBJECT_NO_REF (file_browse, ok_button1, "ok_button1");
+ GLADE_HOOKUP_OBJECT_NO_REF (file_browse, cancel_button1, "cancel_button1");
+
+ return file_browse;
+}
+
+GtkWidget*
+create_edit_win (void)
+{
+ GtkWidget *edit_win;
+ GtkWidget *vbox1;
+ GtkWidget *hbox1;
+ GtkWidget *label29;
+ GtkWidget *name_entry;
+ GtkWidget *label30;
+ GtkWidget *type_option;
+ GtkWidget *menu1;
+ GtkWidget *item_buddy;
+ GtkWidget *item_group;
+ GtkWidget *hbuttonbox2;
+ GtkWidget *applysave_but;
+ GtkWidget *apply_but;
+ GtkWidget *cancel_but;
+ GtkWidget *frame3;
+ GtkWidget *table5;
+ GtkWidget *label31;
+ GtkWidget *label34;
+ GtkWidget *label33;
+ GtkWidget *label32;
+ GtkWidget *unaway_sound_entry;
+ GtkWidget *unidle_sound_entry;
+ GtkWidget *signon_sound_entry;
+ GtkWidget *unaway_test_but;
+ GtkWidget *unidle_test_but;
+ GtkWidget *signon_test_but;
+ GtkWidget *unaway_browse_but;
+ GtkWidget *unidle_browse_but;
+ GtkWidget *signon_browse_but;
+ GtkWidget *im_browse_but;
+ GtkWidget *im_sound_entry;
+ GtkWidget *im_test_but;
+ GtkWidget *label24;
+
+ edit_win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_size_request (edit_win, 600, 300);
+ gtk_window_set_title (GTK_WINDOW (edit_win), "Edit Entry");
+ gtk_window_set_default_size (GTK_WINDOW (edit_win), 600, 300);
+
+ vbox1 = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (vbox1);
+ gtk_container_add (GTK_CONTAINER (edit_win), vbox1);
+
+ hbox1 = gtk_hbox_new (FALSE, 5);
+ gtk_widget_show (hbox1);
+ gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, TRUE, 10);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox1), 5);
+
+ label29 = gtk_label_new ("Name:");
+ gtk_widget_show (label29);
+ gtk_box_pack_start (GTK_BOX (hbox1), label29, FALSE, FALSE, 0);
+ gtk_misc_set_alignment (GTK_MISC (label29), 1, 0.5);
+
+ name_entry = gtk_entry_new ();
+ gtk_widget_show (name_entry);
+ gtk_box_pack_start (GTK_BOX (hbox1), name_entry, TRUE, TRUE, 0);
+
+ label30 = gtk_label_new ("Type:");
+ gtk_widget_show (label30);
+ gtk_box_pack_start (GTK_BOX (hbox1), label30, FALSE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC (label30), 1, 0.5);
+
+ type_option = gtk_option_menu_new ();
+ gtk_widget_show (type_option);
+ gtk_box_pack_start (GTK_BOX (hbox1), type_option, FALSE, FALSE, 0);
+
+ menu1 = gtk_menu_new ();
+
+ item_buddy = gtk_menu_item_new_with_mnemonic ("Buddy");
+ gtk_widget_show (item_buddy);
+ gtk_container_add (GTK_CONTAINER (menu1), item_buddy);
+
+ item_group = gtk_menu_item_new_with_mnemonic ("Group");
+ gtk_widget_show (item_group);
+ gtk_container_add (GTK_CONTAINER (menu1), item_group);
+
+ gtk_option_menu_set_menu (GTK_OPTION_MENU (type_option), menu1);
+
+ hbuttonbox2 = gtk_hbutton_box_new ();
+ gtk_widget_show (hbuttonbox2);
+ gtk_box_pack_end (GTK_BOX (vbox1), hbuttonbox2, FALSE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (hbuttonbox2), 5);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox2), GTK_BUTTONBOX_SPREAD);
+
+ applysave_but = gtk_button_new_with_mnemonic ("Apply and Save");
+ gtk_widget_show (applysave_but);
+ gtk_container_add (GTK_CONTAINER (hbuttonbox2), applysave_but);
+ GTK_WIDGET_SET_FLAGS (applysave_but, GTK_CAN_DEFAULT);
+
+ apply_but = gtk_button_new_from_stock ("gtk-apply");
+ gtk_widget_show (apply_but);
+ gtk_container_add (GTK_CONTAINER (hbuttonbox2), apply_but);
+ GTK_WIDGET_SET_FLAGS (apply_but, GTK_CAN_DEFAULT);
+
+ cancel_but = gtk_button_new_from_stock ("gtk-cancel");
+ gtk_widget_show (cancel_but);
+ gtk_container_add (GTK_CONTAINER (hbuttonbox2), cancel_but);
+ GTK_WIDGET_SET_FLAGS (cancel_but, GTK_CAN_DEFAULT);
+
+ frame3 = gtk_frame_new (NULL);
+ gtk_widget_show (frame3);
+ gtk_box_pack_start (GTK_BOX (vbox1), frame3, FALSE, FALSE, 0);
+ gtk_widget_set_size_request (frame3, -1, 200);
+ gtk_container_set_border_width (GTK_CONTAINER (frame3), 5);
+
+ table5 = gtk_table_new (4, 5, FALSE);
+ gtk_widget_show (table5);
+ gtk_container_add (GTK_CONTAINER (frame3), table5);
+ gtk_widget_set_size_request (table5, 600, 400);
+ gtk_container_set_border_width (GTK_CONTAINER (table5), 5);
+ gtk_table_set_row_spacings (GTK_TABLE (table5), 10);
+ gtk_table_set_col_spacings (GTK_TABLE (table5), 10);
+
+ label31 = gtk_label_new ("Play On IM:");
+ gtk_widget_show (label31);
+ gtk_table_attach (GTK_TABLE (table5), label31, 0, 1, 0, 1,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label31), 0, 0.5);
+
+ label34 = gtk_label_new ("Play On Unaway:");
+ gtk_widget_show (label34);
+ gtk_table_attach (GTK_TABLE (table5), label34, 0, 1, 3, 4,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label34), 0, 0.5);
+
+ label33 = gtk_label_new ("Play On Unidle:");
+ gtk_widget_show (label33);
+ gtk_table_attach (GTK_TABLE (table5), label33, 0, 1, 2, 3,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label33), 0, 0.5);
+
+ label32 = gtk_label_new ("Play On Signon:");
+ gtk_widget_show (label32);
+ gtk_table_attach (GTK_TABLE (table5), label32, 0, 1, 1, 2,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label32), 0, 0.5);
+
+ unaway_sound_entry = gtk_entry_new ();
+ gtk_widget_show (unaway_sound_entry);
+ gtk_table_attach (GTK_TABLE (table5), unaway_sound_entry, 1, 3, 3, 4,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ unidle_sound_entry = gtk_entry_new ();
+ gtk_widget_show (unidle_sound_entry);
+ gtk_table_attach (GTK_TABLE (table5), unidle_sound_entry, 1, 3, 2, 3,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ signon_sound_entry = gtk_entry_new ();
+ gtk_widget_show (signon_sound_entry);
+ gtk_table_attach (GTK_TABLE (table5), signon_sound_entry, 1, 3, 1, 2,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ unaway_test_but = gtk_button_new_with_mnemonic ("Test");
+ gtk_widget_show (unaway_test_but);
+ gtk_table_attach (GTK_TABLE (table5), unaway_test_but, 4, 5, 3, 4,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+
+ unidle_test_but = gtk_button_new_with_mnemonic ("Test");
+ gtk_widget_show (unidle_test_but);
+ gtk_table_attach (GTK_TABLE (table5), unidle_test_but, 4, 5, 2, 3,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+
+ signon_test_but = gtk_button_new_with_mnemonic ("Test");
+ gtk_widget_show (signon_test_but);
+ gtk_table_attach (GTK_TABLE (table5), signon_test_but, 4, 5, 1, 2,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+
+ unaway_browse_but = gtk_button_new_from_stock ("gtk-open");
+ gtk_widget_show (unaway_browse_but);
+ gtk_table_attach (GTK_TABLE (table5), unaway_browse_but, 3, 4, 3, 4,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+
+ unidle_browse_but = gtk_button_new_from_stock ("gtk-open");
+ gtk_widget_show (unidle_browse_but);
+ gtk_table_attach (GTK_TABLE (table5), unidle_browse_but, 3, 4, 2, 3,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+
+ signon_browse_but = gtk_button_new_from_stock ("gtk-open");
+ gtk_widget_show (signon_browse_but);
+ gtk_table_attach (GTK_TABLE (table5), signon_browse_but, 3, 4, 1, 2,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+
+ im_browse_but = gtk_button_new_from_stock ("gtk-open");
+ gtk_widget_show (im_browse_but);
+ gtk_table_attach (GTK_TABLE (table5), im_browse_but, 3, 4, 0, 1,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+
+ im_sound_entry = gtk_entry_new ();
+ gtk_widget_show (im_sound_entry);
+ gtk_table_attach (GTK_TABLE (table5), im_sound_entry, 1, 3, 0, 1,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ im_test_but = gtk_button_new_with_mnemonic ("Test");
+ gtk_widget_show (im_test_but);
+ gtk_table_attach (GTK_TABLE (table5), im_test_but, 4, 5, 0, 1,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+
+ label24 = gtk_label_new ("Sound Events");
+ gtk_widget_show (label24);
+ gtk_frame_set_label_widget (GTK_FRAME (frame3), label24);
+
+ g_signal_connect ((gpointer) edit_win, "destroy",
+ G_CALLBACK (on_edit_win_destroy),
+ NULL);
+ g_signal_connect ((gpointer) applysave_but, "clicked",
+ G_CALLBACK (on_apply_clicked),
+ NULL);
+ g_signal_connect ((gpointer) applysave_but, "clicked",
+ G_CALLBACK (on_save_clicked),
+ NULL);
+ g_signal_connect_swapped ((gpointer) applysave_but, "clicked",
+ G_CALLBACK (gtk_widget_destroy),
+ GTK_OBJECT (edit_win));
+ g_signal_connect ((gpointer) apply_but, "clicked",
+ G_CALLBACK (on_apply_clicked),
+ NULL);
+ g_signal_connect_swapped ((gpointer) apply_but, "clicked",
+ G_CALLBACK (gtk_widget_destroy),
+ GTK_OBJECT (edit_win));
+ g_signal_connect_swapped ((gpointer) cancel_but, "clicked",
+ G_CALLBACK (gtk_widget_destroy),
+ GTK_OBJECT (edit_win));
+ g_signal_connect ((gpointer) unaway_test_but, "clicked",
+ G_CALLBACK (on_unaway_test_clicked),
+ NULL);
+ g_signal_connect ((gpointer) unidle_test_but, "clicked",
+ G_CALLBACK (on_unidle_test_clicked),
+ NULL);
+ g_signal_connect ((gpointer) signon_test_but, "clicked",
+ G_CALLBACK (on_signon_test_clicked),
+ NULL);
+ g_signal_connect ((gpointer) unaway_browse_but, "clicked",
+ G_CALLBACK (on_unaway_browse_clicked),
+ NULL);
+ g_signal_connect ((gpointer) unidle_browse_but, "clicked",
+ G_CALLBACK (on_unidle_browse_clicked),
+ NULL);
+ g_signal_connect ((gpointer) signon_browse_but, "clicked",
+ G_CALLBACK (on_signon_browse_clicked),
+ NULL);
+ g_signal_connect ((gpointer) im_browse_but, "clicked",
+ G_CALLBACK (on_im_browse_clicked),
+ NULL);
+ g_signal_connect ((gpointer) im_test_but, "clicked",
+ G_CALLBACK (on_im_test_clicked),
+ NULL);
+
+ /* Store pointers to all widgets, for use by lookup_widget(). */
+ GLADE_HOOKUP_OBJECT_NO_REF (edit_win, edit_win, "edit_win");
+ GLADE_HOOKUP_OBJECT (edit_win, vbox1, "vbox1");
+ GLADE_HOOKUP_OBJECT (edit_win, hbox1, "hbox1");
+ GLADE_HOOKUP_OBJECT (edit_win, label29, "label29");
+ GLADE_HOOKUP_OBJECT (edit_win, name_entry, "name_entry");
+ GLADE_HOOKUP_OBJECT (edit_win, label30, "label30");
+ GLADE_HOOKUP_OBJECT (edit_win, type_option, "type_option");
+ GLADE_HOOKUP_OBJECT (edit_win, menu1, "menu1");
+ GLADE_HOOKUP_OBJECT (edit_win, item_buddy, "item_buddy");
+ GLADE_HOOKUP_OBJECT (edit_win, item_group, "item_group");
+ GLADE_HOOKUP_OBJECT (edit_win, hbuttonbox2, "hbuttonbox2");
+ GLADE_HOOKUP_OBJECT (edit_win, applysave_but, "applysave_but");
+ GLADE_HOOKUP_OBJECT (edit_win, apply_but, "apply_but");
+ GLADE_HOOKUP_OBJECT (edit_win, cancel_but, "cancel_but");
+ GLADE_HOOKUP_OBJECT (edit_win, frame3, "frame3");
+ GLADE_HOOKUP_OBJECT (edit_win, table5, "table5");
+ GLADE_HOOKUP_OBJECT (edit_win, label31, "label31");
+ GLADE_HOOKUP_OBJECT (edit_win, label34, "label34");
+ GLADE_HOOKUP_OBJECT (edit_win, label33, "label33");
+ GLADE_HOOKUP_OBJECT (edit_win, label32, "label32");
+ GLADE_HOOKUP_OBJECT (edit_win, unaway_sound_entry, "unaway_sound_entry");
+ GLADE_HOOKUP_OBJECT (edit_win, unidle_sound_entry, "unidle_sound_entry");
+ GLADE_HOOKUP_OBJECT (edit_win, signon_sound_entry, "signon_sound_entry");
+ GLADE_HOOKUP_OBJECT (edit_win, unaway_test_but, "unaway_test_but");
+ GLADE_HOOKUP_OBJECT (edit_win, unidle_test_but, "unidle_test_but");
+ GLADE_HOOKUP_OBJECT (edit_win, signon_test_but, "signon_test_but");
+ GLADE_HOOKUP_OBJECT (edit_win, unaway_browse_but, "unaway_browse_but");
+ GLADE_HOOKUP_OBJECT (edit_win, unidle_browse_but, "unidle_browse_but");
+ GLADE_HOOKUP_OBJECT (edit_win, signon_browse_but, "signon_browse_but");
+ GLADE_HOOKUP_OBJECT (edit_win, im_browse_but, "im_browse_but");
+ GLADE_HOOKUP_OBJECT (edit_win, im_sound_entry, "im_sound_entry");
+ GLADE_HOOKUP_OBJECT (edit_win, im_test_but, "im_test_but");
+ GLADE_HOOKUP_OBJECT (edit_win, label24, "label24");
+
+ return edit_win;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smartear/make-interface.sh Sun Aug 19 04:42:58 2007 -0400
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# This is a script for converting the glade-generated interface.c file to a
+# smartear-interface.c which will be friendly with pidgin's plugin interface.
+
+IN=interface.c
+OUT=smartear-interface.c
+
+cat $IN | \
+sed -e '
+# hookup to config_vbox instead of config
+ s/GLADE_HOOKUP\([^c]*\)config/GLADE_HOOKUP\1config_vbox/
+# return config_vbox instead of config
+ s/return.*config;/return config_vbox;/
+# hookup objects without referencing them (only in create_config())
+ /create_config/,/return/ {
+ s/GLADE_HOOKUP_OBJECT /GLADE_HOOKUP_OBJECT_NO_REF /
+ }
+# remove all references to "config"
+ /\<config\>/d
+# dont show config_vbox
+ /gtk_widget_show.*config_vbox/d
+# remove #include lines
+ /^#include/d' \
+> $OUT
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smartear/old-smartear-interface.c Sun Aug 19 04:42:58 2007 -0400
@@ -0,0 +1,546 @@
+/* GPL Header */
+
+#ifdef HAVE_CONFIG_H
+# include "../pp_config.h"
+#endif
+
+#include <gtk/gtk.h>
+
+#define GLADE_HOOKUP_OBJECT(component,widget,name) \
+ g_object_set_data_full (G_OBJECT (component), name, \
+ gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref)
+
+#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \
+ g_object_set_data (G_OBJECT (component), name, widget)
+
+GtkWidget*
+create_config (void)
+{
+ GtkWidget *config_vbox;
+ GtkWidget *frame1;
+ GtkWidget *table1;
+ GtkWidget *label9;
+ GtkObject *delay_spin_adj;
+ GtkWidget *delay_spin;
+ GtkWidget *focus_but;
+ GtkWidget *timer_but;
+ GtkWidget *label8;
+ GtkWidget *frame2;
+ GtkWidget *table2;
+ GtkWidget *delete_but;
+ GtkWidget *new_but;
+ GtkWidget *scrolledwindow2;
+ GtkWidget *treeview;
+ GtkWidget *edit_but;
+ GtkWidget *label7;
+ GtkWidget *hbuttonbox1;
+ GtkWidget *revert_but;
+ GtkWidget *save_but;
+
+
+ config_vbox = gtk_vbox_new (FALSE, 0);
+ gtk_widget_set_size_request (config_vbox, -1, 640);
+
+ frame1 = gtk_frame_new (NULL);
+ gtk_widget_show (frame1);
+ gtk_box_pack_start (GTK_BOX (config_vbox), frame1, FALSE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (frame1), 5);
+
+ table1 = gtk_table_new (3, 2, FALSE);
+ gtk_widget_show (table1);
+ gtk_container_add (GTK_CONTAINER (frame1), table1);
+ gtk_container_set_border_width (GTK_CONTAINER (table1), 5);
+ gtk_table_set_row_spacings (GTK_TABLE (table1), 10);
+ gtk_table_set_col_spacings (GTK_TABLE (table1), 10);
+
+ label9 = gtk_label_new ("Time delay between playing sounds for a particular buddy:");
+ gtk_widget_show (label9);
+ gtk_table_attach (GTK_TABLE (table1), label9, 0, 1, 0, 1,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label9), 0, 0.5);
+
+ delay_spin_adj = gtk_adjustment_new (60, 0, 1000000, 1, 10, 10);
+ delay_spin = gtk_spin_button_new (GTK_ADJUSTMENT (delay_spin_adj), 1, 0);
+ gtk_widget_show (delay_spin);
+ gtk_table_attach (GTK_TABLE (table1), delay_spin, 1, 2, 0, 1,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (delay_spin), GTK_UPDATE_IF_VALID);
+
+ focus_but = gtk_check_button_new_with_mnemonic ("Don't play sounds for the conversation that has focus.");
+ gtk_widget_show (focus_but);
+ gtk_table_attach (GTK_TABLE (table1), focus_but, 0, 2, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ timer_but = gtk_check_button_new_with_mnemonic ("Also play sounds if you don't respond to a particular IM within a delay period.");
+ gtk_widget_show (timer_but);
+ gtk_table_attach (GTK_TABLE (table1), timer_but, 0, 2, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ label8 = gtk_label_new ("Options");
+ gtk_widget_show (label8);
+ gtk_frame_set_label_widget (GTK_FRAME (frame1), label8);
+
+ frame2 = gtk_frame_new (NULL);
+ gtk_widget_show (frame2);
+ gtk_box_pack_start (GTK_BOX (config_vbox), frame2, TRUE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (frame2), 5);
+
+ table2 = gtk_table_new (2, 3, FALSE);
+ gtk_widget_show (table2);
+ gtk_container_add (GTK_CONTAINER (frame2), table2);
+ gtk_container_set_border_width (GTK_CONTAINER (table2), 5);
+ gtk_table_set_row_spacings (GTK_TABLE (table2), 10);
+ gtk_table_set_col_spacings (GTK_TABLE (table2), 10);
+
+ delete_but = gtk_button_new_from_stock ("gtk-delete");
+ gtk_widget_show (delete_but);
+ gtk_table_attach (GTK_TABLE (table2), delete_but, 2, 3, 1, 2,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+ GTK_WIDGET_SET_FLAGS (delete_but, GTK_CAN_DEFAULT);
+
+ new_but = gtk_button_new_from_stock ("gtk-new");
+ gtk_widget_show (new_but);
+ gtk_table_attach (GTK_TABLE (table2), new_but, 0, 1, 1, 2,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+ GTK_WIDGET_SET_FLAGS (new_but, GTK_CAN_DEFAULT);
+
+ scrolledwindow2 = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_show (scrolledwindow2);
+ gtk_table_attach (GTK_TABLE (table2), scrolledwindow2, 0, 3, 0, 1,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow2), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+
+ treeview = gtk_tree_view_new ();
+ gtk_widget_show (treeview);
+ gtk_container_add (GTK_CONTAINER (scrolledwindow2), treeview);
+
+ edit_but = gtk_button_new_from_stock ("gtk-properties");
+ gtk_widget_show (edit_but);
+ gtk_table_attach (GTK_TABLE (table2), edit_but, 1, 2, 1, 2,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+
+ label7 = gtk_label_new ("Entries");
+ gtk_widget_show (label7);
+ gtk_frame_set_label_widget (GTK_FRAME (frame2), label7);
+
+ hbuttonbox1 = gtk_hbutton_box_new ();
+ gtk_widget_show (hbuttonbox1);
+ gtk_box_pack_start (GTK_BOX (config_vbox), hbuttonbox1, FALSE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (hbuttonbox1), 5);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox1), GTK_BUTTONBOX_SPREAD);
+
+ revert_but = gtk_button_new_from_stock ("gtk-revert-to-saved");
+ gtk_widget_show (revert_but);
+ gtk_container_add (GTK_CONTAINER (hbuttonbox1), revert_but);
+ GTK_WIDGET_SET_FLAGS (revert_but, GTK_CAN_DEFAULT);
+
+ save_but = gtk_button_new_from_stock ("gtk-save");
+ gtk_widget_show (save_but);
+ gtk_container_add (GTK_CONTAINER (hbuttonbox1), save_but);
+ GTK_WIDGET_SET_FLAGS (save_but, GTK_CAN_DEFAULT);
+
+ g_signal_connect ((gpointer) config_vbox, "destroy",
+ G_CALLBACK (on_config_destroy),
+ NULL);
+ g_signal_connect ((gpointer) delay_spin, "changed",
+ G_CALLBACK (on_delay_changed),
+ NULL);
+ g_signal_connect ((gpointer) focus_but, "toggled",
+ G_CALLBACK (on_focus_toggled),
+ NULL);
+ g_signal_connect ((gpointer) timer_but, "toggled",
+ G_CALLBACK (on_timer_toggled),
+ NULL);
+ g_signal_connect ((gpointer) delete_but, "clicked",
+ G_CALLBACK (on_delete_clicked),
+ NULL);
+ g_signal_connect ((gpointer) new_but, "clicked",
+ G_CALLBACK (on_new_clicked),
+ NULL);
+ g_signal_connect ((gpointer) edit_but, "clicked",
+ G_CALLBACK (on_edit_clicked),
+ NULL);
+ g_signal_connect ((gpointer) revert_but, "clicked",
+ G_CALLBACK (on_revert_clicked),
+ NULL);
+ g_signal_connect ((gpointer) save_but, "clicked",
+ G_CALLBACK (on_save_clicked),
+ NULL);
+
+ /* Store pointers to all widgets, for use by lookup_widget(). */
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, config_vbox, "config_vbox");
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, frame1, "frame1");
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, table1, "table1");
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, label9, "label9");
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, delay_spin, "delay_spin");
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, focus_but, "focus_but");
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, timer_but, "timer_but");
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, label8, "label8");
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, frame2, "frame2");
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, table2, "table2");
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, delete_but, "delete_but");
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, new_but, "new_but");
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, scrolledwindow2, "scrolledwindow2");
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, treeview, "treeview");
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, edit_but, "edit_but");
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, label7, "label7");
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, hbuttonbox1, "hbuttonbox1");
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, revert_but, "revert_but");
+ GLADE_HOOKUP_OBJECT_NO_REF (config_vbox, save_but, "save_but");
+
+ return config_vbox;
+}
+
+GtkWidget*
+create_file_browse (void)
+{
+ GtkWidget *file_browse;
+ GtkWidget *ok_button1;
+ GtkWidget *cancel_button1;
+
+ file_browse = gtk_file_selection_new ("Select Sound");
+ gtk_container_set_border_width (GTK_CONTAINER (file_browse), 10);
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (file_browse), TRUE);
+ gtk_window_set_type_hint (GTK_WINDOW (file_browse), GDK_WINDOW_TYPE_HINT_DIALOG);
+
+ ok_button1 = GTK_FILE_SELECTION (file_browse)->ok_button;
+ gtk_widget_show (ok_button1);
+ GTK_WIDGET_SET_FLAGS (ok_button1, GTK_CAN_DEFAULT);
+
+ cancel_button1 = GTK_FILE_SELECTION (file_browse)->cancel_button;
+ gtk_widget_show (cancel_button1);
+ GTK_WIDGET_SET_FLAGS (cancel_button1, GTK_CAN_DEFAULT);
+
+ g_signal_connect ((gpointer) file_browse, "destroy",
+ G_CALLBACK (on_file_browse_destroy),
+ NULL);
+ g_signal_connect ((gpointer) ok_button1, "clicked",
+ G_CALLBACK (on_browse_ok_clicked),
+ NULL);
+ g_signal_connect_swapped ((gpointer) ok_button1, "clicked",
+ G_CALLBACK (gtk_widget_destroy),
+ GTK_OBJECT (file_browse));
+ g_signal_connect_swapped ((gpointer) cancel_button1, "clicked",
+ G_CALLBACK (gtk_widget_destroy),
+ GTK_OBJECT (file_browse));
+
+ /* Store pointers to all widgets, for use by lookup_widget(). */
+ GLADE_HOOKUP_OBJECT_NO_REF (file_browse, file_browse, "file_browse");
+ GLADE_HOOKUP_OBJECT_NO_REF (file_browse, ok_button1, "ok_button1");
+ GLADE_HOOKUP_OBJECT_NO_REF (file_browse, cancel_button1, "cancel_button1");
+
+ return file_browse;
+}
+
+GtkWidget*
+create_edit_win (void)
+{
+ GtkWidget *edit_win;
+ GtkWidget *vbox1;
+ GtkWidget *hbox1;
+ GtkWidget *label29;
+ GtkWidget *name_entry;
+ GtkWidget *label30;
+ GtkWidget *type_option;
+ GtkWidget *menu1;
+ GtkWidget *item_buddy;
+ GtkWidget *item_group;
+ GtkWidget *hbuttonbox2;
+ GtkWidget *applysave_but;
+ GtkWidget *apply_but;
+ GtkWidget *cancel_but;
+ GtkWidget *frame3;
+ GtkWidget *table5;
+ GtkWidget *label31;
+ GtkWidget *label34;
+ GtkWidget *label33;
+ GtkWidget *label32;
+ GtkWidget *unaway_sound_entry;
+ GtkWidget *unidle_sound_entry;
+ GtkWidget *signon_sound_entry;
+ GtkWidget *unaway_test_but;
+ GtkWidget *unidle_test_but;
+ GtkWidget *signon_test_but;
+ GtkWidget *unaway_browse_but;
+ GtkWidget *unidle_browse_but;
+ GtkWidget *signon_browse_but;
+ GtkWidget *im_browse_but;
+ GtkWidget *im_sound_entry;
+ GtkWidget *im_test_but;
+ GtkWidget *label24;
+
+ edit_win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_size_request (edit_win, 600, 300);
+ gtk_window_set_title (GTK_WINDOW (edit_win), "Edit Entry");
+ gtk_window_set_default_size (GTK_WINDOW (edit_win), 600, 300);
+
+ vbox1 = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (vbox1);
+ gtk_container_add (GTK_CONTAINER (edit_win), vbox1);
+
+ hbox1 = gtk_hbox_new (FALSE, 5);
+ gtk_widget_show (hbox1);
+ gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, TRUE, 10);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox1), 5);
+
+ label29 = gtk_label_new ("Name:");
+ gtk_widget_show (label29);
+ gtk_box_pack_start (GTK_BOX (hbox1), label29, FALSE, FALSE, 0);
+ gtk_misc_set_alignment (GTK_MISC (label29), 1, 0.5);
+
+ name_entry = gtk_entry_new ();
+ gtk_widget_show (name_entry);
+ gtk_box_pack_start (GTK_BOX (hbox1), name_entry, TRUE, TRUE, 0);
+
+ label30 = gtk_label_new ("Type:");
+ gtk_widget_show (label30);
+ gtk_box_pack_start (GTK_BOX (hbox1), label30, FALSE, TRUE, 0);
+ gtk_misc_set_alignment (GTK_MISC (label30), 1, 0.5);
+
+ type_option = gtk_option_menu_new ();
+ gtk_widget_show (type_option);
+ gtk_box_pack_start (GTK_BOX (hbox1), type_option, FALSE, FALSE, 0);
+
+ menu1 = gtk_menu_new ();
+
+ item_buddy = gtk_menu_item_new_with_mnemonic ("Buddy");
+ gtk_widget_show (item_buddy);
+ gtk_container_add (GTK_CONTAINER (menu1), item_buddy);
+
+ item_group = gtk_menu_item_new_with_mnemonic ("Group");
+ gtk_widget_show (item_group);
+ gtk_container_add (GTK_CONTAINER (menu1), item_group);
+
+ gtk_option_menu_set_menu (GTK_OPTION_MENU (type_option), menu1);
+
+ hbuttonbox2 = gtk_hbutton_box_new ();
+ gtk_widget_show (hbuttonbox2);
+ gtk_box_pack_end (GTK_BOX (vbox1), hbuttonbox2, FALSE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (hbuttonbox2), 5);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox2), GTK_BUTTONBOX_SPREAD);
+
+ applysave_but = gtk_button_new_with_mnemonic ("Apply and Save");
+ gtk_widget_show (applysave_but);
+ gtk_container_add (GTK_CONTAINER (hbuttonbox2), applysave_but);
+ GTK_WIDGET_SET_FLAGS (applysave_but, GTK_CAN_DEFAULT);
+
+ apply_but = gtk_button_new_from_stock ("gtk-apply");
+ gtk_widget_show (apply_but);
+ gtk_container_add (GTK_CONTAINER (hbuttonbox2), apply_but);
+ GTK_WIDGET_SET_FLAGS (apply_but, GTK_CAN_DEFAULT);
+
+ cancel_but = gtk_button_new_from_stock ("gtk-cancel");
+ gtk_widget_show (cancel_but);
+ gtk_container_add (GTK_CONTAINER (hbuttonbox2), cancel_but);
+ GTK_WIDGET_SET_FLAGS (cancel_but, GTK_CAN_DEFAULT);
+
+ frame3 = gtk_frame_new (NULL);
+ gtk_widget_show (frame3);
+ gtk_box_pack_start (GTK_BOX (vbox1), frame3, FALSE, FALSE, 0);
+ gtk_widget_set_size_request (frame3, -1, 200);
+ gtk_container_set_border_width (GTK_CONTAINER (frame3), 5);
+
+ table5 = gtk_table_new (4, 5, FALSE);
+ gtk_widget_show (table5);
+ gtk_container_add (GTK_CONTAINER (frame3), table5);
+ gtk_widget_set_size_request (table5, 600, 400);
+ gtk_container_set_border_width (GTK_CONTAINER (table5), 5);
+ gtk_table_set_row_spacings (GTK_TABLE (table5), 10);
+ gtk_table_set_col_spacings (GTK_TABLE (table5), 10);
+
+ label31 = gtk_label_new ("Play On IM:");
+ gtk_widget_show (label31);
+ gtk_table_attach (GTK_TABLE (table5), label31, 0, 1, 0, 1,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label31), 0, 0.5);
+
+ label34 = gtk_label_new ("Play On Unaway:");
+ gtk_widget_show (label34);
+ gtk_table_attach (GTK_TABLE (table5), label34, 0, 1, 3, 4,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label34), 0, 0.5);
+
+ label33 = gtk_label_new ("Play On Unidle:");
+ gtk_widget_show (label33);
+ gtk_table_attach (GTK_TABLE (table5), label33, 0, 1, 2, 3,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label33), 0, 0.5);
+
+ label32 = gtk_label_new ("Play On Signon:");
+ gtk_widget_show (label32);
+ gtk_table_attach (GTK_TABLE (table5), label32, 0, 1, 1, 2,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label32), 0, 0.5);
+
+ unaway_sound_entry = gtk_entry_new ();
+ gtk_widget_show (unaway_sound_entry);
+ gtk_table_attach (GTK_TABLE (table5), unaway_sound_entry, 1, 3, 3, 4,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ unidle_sound_entry = gtk_entry_new ();
+ gtk_widget_show (unidle_sound_entry);
+ gtk_table_attach (GTK_TABLE (table5), unidle_sound_entry, 1, 3, 2, 3,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ signon_sound_entry = gtk_entry_new ();
+ gtk_widget_show (signon_sound_entry);
+ gtk_table_attach (GTK_TABLE (table5), signon_sound_entry, 1, 3, 1, 2,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ unaway_test_but = gtk_button_new_with_mnemonic ("Test");
+ gtk_widget_show (unaway_test_but);
+ gtk_table_attach (GTK_TABLE (table5), unaway_test_but, 4, 5, 3, 4,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+
+ unidle_test_but = gtk_button_new_with_mnemonic ("Test");
+ gtk_widget_show (unidle_test_but);
+ gtk_table_attach (GTK_TABLE (table5), unidle_test_but, 4, 5, 2, 3,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+
+ signon_test_but = gtk_button_new_with_mnemonic ("Test");
+ gtk_widget_show (signon_test_but);
+ gtk_table_attach (GTK_TABLE (table5), signon_test_but, 4, 5, 1, 2,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+
+ unaway_browse_but = gtk_button_new_from_stock ("gtk-open");
+ gtk_widget_show (unaway_browse_but);
+ gtk_table_attach (GTK_TABLE (table5), unaway_browse_but, 3, 4, 3, 4,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+
+ unidle_browse_but = gtk_button_new_from_stock ("gtk-open");
+ gtk_widget_show (unidle_browse_but);
+ gtk_table_attach (GTK_TABLE (table5), unidle_browse_but, 3, 4, 2, 3,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+
+ signon_browse_but = gtk_button_new_from_stock ("gtk-open");
+ gtk_widget_show (signon_browse_but);
+ gtk_table_attach (GTK_TABLE (table5), signon_browse_but, 3, 4, 1, 2,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+
+ im_browse_but = gtk_button_new_from_stock ("gtk-open");
+ gtk_widget_show (im_browse_but);
+ gtk_table_attach (GTK_TABLE (table5), im_browse_but, 3, 4, 0, 1,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+
+ im_sound_entry = gtk_entry_new ();
+ gtk_widget_show (im_sound_entry);
+ gtk_table_attach (GTK_TABLE (table5), im_sound_entry, 1, 3, 0, 1,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ im_test_but = gtk_button_new_with_mnemonic ("Test");
+ gtk_widget_show (im_test_but);
+ gtk_table_attach (GTK_TABLE (table5), im_test_but, 4, 5, 0, 1,
+ (GtkAttachOptions) (0),
+ (GtkAttachOptions) (0), 0, 0);
+
+ label24 = gtk_label_new ("Sound Events");
+ gtk_widget_show (label24);
+ gtk_frame_set_label_widget (GTK_FRAME (frame3), label24);
+
+ g_signal_connect ((gpointer) edit_win, "destroy",
+ G_CALLBACK (on_edit_win_destroy),
+ NULL);
+ g_signal_connect ((gpointer) applysave_but, "clicked",
+ G_CALLBACK (on_apply_clicked),
+ NULL);
+ g_signal_connect ((gpointer) applysave_but, "clicked",
+ G_CALLBACK (on_save_clicked),
+ NULL);
+ g_signal_connect_swapped ((gpointer) applysave_but, "clicked",
+ G_CALLBACK (gtk_widget_destroy),
+ GTK_OBJECT (edit_win));
+ g_signal_connect ((gpointer) apply_but, "clicked",
+ G_CALLBACK (on_apply_clicked),
+ NULL);
+ g_signal_connect_swapped ((gpointer) apply_but, "clicked",
+ G_CALLBACK (gtk_widget_destroy),
+ GTK_OBJECT (edit_win));
+ g_signal_connect_swapped ((gpointer) cancel_but, "clicked",
+ G_CALLBACK (gtk_widget_destroy),
+ GTK_OBJECT (edit_win));
+ g_signal_connect ((gpointer) unaway_test_but, "clicked",
+ G_CALLBACK (on_unaway_test_clicked),
+ NULL);
+ g_signal_connect ((gpointer) unidle_test_but, "clicked",
+ G_CALLBACK (on_unidle_test_clicked),
+ NULL);
+ g_signal_connect ((gpointer) signon_test_but, "clicked",
+ G_CALLBACK (on_signon_test_clicked),
+ NULL);
+ g_signal_connect ((gpointer) unaway_browse_but, "clicked",
+ G_CALLBACK (on_unaway_browse_clicked),
+ NULL);
+ g_signal_connect ((gpointer) unidle_browse_but, "clicked",
+ G_CALLBACK (on_unidle_browse_clicked),
+ NULL);
+ g_signal_connect ((gpointer) signon_browse_but, "clicked",
+ G_CALLBACK (on_signon_browse_clicked),
+ NULL);
+ g_signal_connect ((gpointer) im_browse_but, "clicked",
+ G_CALLBACK (on_im_browse_clicked),
+ NULL);
+ g_signal_connect ((gpointer) im_test_but, "clicked",
+ G_CALLBACK (on_im_test_clicked),
+ NULL);
+
+ /* Store pointers to all widgets, for use by lookup_widget(). */
+ GLADE_HOOKUP_OBJECT_NO_REF (edit_win, edit_win, "edit_win");
+ GLADE_HOOKUP_OBJECT (edit_win, vbox1, "vbox1");
+ GLADE_HOOKUP_OBJECT (edit_win, hbox1, "hbox1");
+ GLADE_HOOKUP_OBJECT (edit_win, label29, "label29");
+ GLADE_HOOKUP_OBJECT (edit_win, name_entry, "name_entry");
+ GLADE_HOOKUP_OBJECT (edit_win, label30, "label30");
+ GLADE_HOOKUP_OBJECT (edit_win, type_option, "type_option");
+ GLADE_HOOKUP_OBJECT (edit_win, menu1, "menu1");
+ GLADE_HOOKUP_OBJECT (edit_win, item_buddy, "item_buddy");
+ GLADE_HOOKUP_OBJECT (edit_win, item_group, "item_group");
+ GLADE_HOOKUP_OBJECT (edit_win, hbuttonbox2, "hbuttonbox2");
+ GLADE_HOOKUP_OBJECT (edit_win, applysave_but, "applysave_but");
+ GLADE_HOOKUP_OBJECT (edit_win, apply_but, "apply_but");
+ GLADE_HOOKUP_OBJECT (edit_win, cancel_but, "cancel_but");
+ GLADE_HOOKUP_OBJECT (edit_win, frame3, "frame3");
+ GLADE_HOOKUP_OBJECT (edit_win, table5, "table5");
+ GLADE_HOOKUP_OBJECT (edit_win, label31, "label31");
+ GLADE_HOOKUP_OBJECT (edit_win, label34, "label34");
+ GLADE_HOOKUP_OBJECT (edit_win, label33, "label33");
+ GLADE_HOOKUP_OBJECT (edit_win, label32, "label32");
+ GLADE_HOOKUP_OBJECT (edit_win, unaway_sound_entry, "unaway_sound_entry");
+ GLADE_HOOKUP_OBJECT (edit_win, unidle_sound_entry, "unidle_sound_entry");
+ GLADE_HOOKUP_OBJECT (edit_win, signon_sound_entry, "signon_sound_entry");
+ GLADE_HOOKUP_OBJECT (edit_win, unaway_test_but, "unaway_test_but");
+ GLADE_HOOKUP_OBJECT (edit_win, unidle_test_but, "unidle_test_but");
+ GLADE_HOOKUP_OBJECT (edit_win, signon_test_but, "signon_test_but");
+ GLADE_HOOKUP_OBJECT (edit_win, unaway_browse_but, "unaway_browse_but");
+ GLADE_HOOKUP_OBJECT (edit_win, unidle_browse_but, "unidle_browse_but");
+ GLADE_HOOKUP_OBJECT (edit_win, signon_browse_but, "signon_browse_but");
+ GLADE_HOOKUP_OBJECT (edit_win, im_browse_but, "im_browse_but");
+ GLADE_HOOKUP_OBJECT (edit_win, im_sound_entry, "im_sound_entry");
+ GLADE_HOOKUP_OBJECT (edit_win, im_test_but, "im_test_but");
+ GLADE_HOOKUP_OBJECT (edit_win, label24, "label24");
+
+ return edit_win;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smartear/old-smartear.c Sun Aug 19 04:42:58 2007 -0400
@@ -0,0 +1,1280 @@
+/* SmartEar by Matt Perry
+ * Works for purple 2.0.0
+ * Plugin to assign different sounds to different buddies and groups.
+ * TODO: figure out contact support
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "../pp_config.h"
+#endif
+#include "../common/i18n.h"
+
+#include "pidgin.h"
+
+#include "gtkplugin.h"
+#include "gtkutils.h"
+#include "version.h"
+
+#include "debug.h"
+#include "util.h"
+#include "sound.h"
+#include "gtkprefs.h"
+#include "gtkblist.h"
+#include "signals.h"
+
+#ifndef PURPLE_PLUGINS
+#define PURPLE_PLUGINS
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <time.h>
+
+#ifdef _WIN32
+#include "win32dep.h"
+#endif
+
+#define BUF_LEN 2048 /* lifted from libpurple's internal.h */
+
+#define RCFILE_VERSION 2
+#define RC_EMPTY_SOUND " " /* must be at least 1 char long for sscanf */
+
+#define SMARTEAR_PLUGIN_ID "smartear"
+#define SMARTEAR_VERSION VERSION ".1"
+
+#define FIND(s) lookup_widget(config, s)
+#define EFIND(s) lookup_widget(edit_win, s)
+
+/* an entry in the prefs file to indicate what to play for who and when. */
+struct smartear_entry {
+ char type; /* B,G */
+ char *name;
+#define EVENT_M 0
+#define EVENT_S 1
+#define EVENT_I 2
+#define EVENT_A 3
+#define EVENT_NUM 4
+ char *sound[EVENT_NUM];
+};
+
+struct timer_data {
+ int event;
+ guint id;
+};
+
+struct message_data {
+ PurpleAccount *account;
+ char *buddy;
+ time_t last_active;
+ time_t last_sent;
+ struct timer_data *timer;
+};
+
+enum { /* Treeview columns */
+ DATA_COL = 0,
+ TYPE_COL = 0,
+ NAME_COL,
+ ON_MESSAGE_COL,
+ ON_SIGNON_COL,
+ ON_UNIDLE_COL,
+ ON_UNAWAY_COL,
+ NUM_COLS
+};
+
+#define DEFAULT_NAME "(Default)"
+#define IS_DEFAULT(entry) (strcmp(entry->name, DEFAULT_NAME)==0)
+#define IS_EMPTY(str) (!str || !str[0])
+struct smartear_entry default_entry = {'B', DEFAULT_NAME, {"", "", "", ""}};
+
+int message_delay = 60;
+int focused_quiet = TRUE;
+int smartear_timers = FALSE;
+
+GtkWidget *config = NULL;
+GtkWidget *edit_win = NULL;
+GtkWidget *file_browse = NULL;
+GtkWidget *file_browse_entry = NULL;
+GtkTreeView *treeview = NULL;
+GtkTreeSelection *treeselect = NULL;
+GtkTreeModel *treemodel = NULL;
+
+struct smartear_entry *selected_entry = NULL;
+GtkTreeIter selected_iter;
+
+GSList *sounds_list = NULL;
+GSList *messages_list = NULL;
+
+GtkWidget *create_file_browse(void);
+GtkWidget *create_edit_win(void);
+GtkWidget *create_config(void);
+
+static void new_entry(struct smartear_entry *entry);
+static gboolean get_selection(void);
+static void clear_selection(void);
+static void populate_edit_win(struct smartear_entry *entry);
+static void update_list(void);
+static void populate_list(GtkListStore *store);
+static void list_set(GtkListStore *store, GtkTreeIter *iter, struct smartear_entry *entry);
+static void set_option_entries(void);
+
+static gint sound_cmp(gconstpointer p1, gconstpointer p2);
+static struct smartear_entry *sound_new_with_name(gchar *name);
+static struct smartear_entry *sound_dup(struct smartear_entry *entry);
+static void sound_free(struct smartear_entry *entry, int free_entry);
+static void soundlist_free(void);
+
+static gchar *get_basename(gchar *path);
+
+static void on_treeselect_changed(GtkTreeSelection *selection, gpointer data);
+
+static void smartear_save(void);
+static void smartear_load(void);
+
+static void play_sound_alias(char *sound, PurpleAccount* account);
+
+/*** Glade's Support Function ***/
+
+GtkWidget* lookup_widget (GtkWidget *widget, const gchar *widget_name)
+{
+ GtkWidget *found_widget;
+ found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget),
+ widget_name);
+ if (!found_widget)
+ g_warning ("smartear: Widget not found: %s", widget_name);
+ return found_widget;
+}
+
+/*** GTK Callbacks ***/
+
+/* Options Frame */
+
+void on_delay_changed (GtkEditable *editable, gpointer user_data)
+{
+ gchar *text = gtk_editable_get_chars(editable, 0, -1);
+ message_delay = atoi(text);
+ g_free(text);
+}
+
+void on_focus_toggled (GtkToggleButton *togglebutton, gpointer user_data)
+{
+ focused_quiet = gtk_toggle_button_get_active(togglebutton);
+}
+
+void on_timer_toggled (GtkToggleButton *togglebutton, gpointer user_data)
+{
+ smartear_timers = gtk_toggle_button_get_active(togglebutton);
+}
+
+/* Entries Frame */
+
+void on_cell_edited(GtkCellRendererText *cell, gchar *path, gchar *text, gpointer data)
+{
+ GtkTreeIter iter;
+ gint col = GPOINTER_TO_INT(data);
+ struct smartear_entry *entry;
+
+ if (!gtk_tree_model_get_iter_from_string(treemodel, &iter, path))
+ return;
+
+ gtk_tree_model_get(treemodel, &iter, DATA_COL, &entry, -1);
+ switch (col) {
+ case NAME_COL:
+ if (IS_DEFAULT(entry))
+ return;
+ g_free(entry->name);
+ entry->name = g_strdup(text);
+ update_list();
+ break;
+ }
+}
+
+void on_treeselect_changed(GtkTreeSelection *selection, gpointer data)
+{
+ get_selection();
+ update_list();
+}
+
+
+void on_new_clicked (GtkButton *button, gpointer user_data)
+{
+ if (edit_win)
+ return;
+
+ new_entry(sound_new_with_name(""));
+}
+
+void on_delete_clicked (GtkButton *button, gpointer user_data)
+{
+ GtkTreeIter iter;
+
+ if (edit_win)
+ return;
+
+ if (!get_selection())
+ return;
+
+ if (IS_DEFAULT(selected_entry))
+ return;
+
+ iter = selected_iter;
+
+ sounds_list = g_slist_remove(sounds_list, selected_entry);
+ sound_free(selected_entry, TRUE);
+
+ if (!gtk_tree_model_iter_next(treemodel, &iter)) {
+ GtkTreePath *path = gtk_tree_model_get_path(treemodel, &selected_iter);
+ gtk_tree_path_prev(path);
+ gtk_tree_model_get_iter(treemodel, &iter, path);
+ gtk_tree_path_free(path);
+ }
+ g_signal_handlers_block_by_func(G_OBJECT(treeselect), on_treeselect_changed, 0);
+ gtk_list_store_remove(GTK_LIST_STORE(treemodel), &selected_iter);
+ gtk_tree_selection_select_iter(treeselect, &iter);
+ g_signal_handlers_unblock_by_func(G_OBJECT(treeselect), on_treeselect_changed, 0);
+
+ get_selection();
+ update_list();
+}
+
+void on_edit_clicked (GtkButton *button, gpointer user_data)
+{
+ if (!get_selection())
+ return;
+
+ if (edit_win)
+ return;
+
+ edit_win = create_edit_win();
+ gtk_widget_show_all(edit_win);
+
+ populate_edit_win(selected_entry);
+}
+
+void on_save_clicked (GtkButton *button, gpointer user_data)
+{
+ smartear_save();
+}
+
+void on_revert_clicked (GtkButton *button, gpointer user_data)
+{
+ selected_entry = NULL;
+ if (edit_win) {
+ gtk_widget_destroy(edit_win);
+ edit_win = NULL;
+ }
+
+ soundlist_free();
+ smartear_load();
+ gtk_list_store_clear(GTK_LIST_STORE(treemodel));
+ populate_list(GTK_LIST_STORE(treemodel));
+ update_list();
+ set_option_entries();
+}
+
+/* Edit Window */
+
+void on_browse_ok_clicked (GtkButton *button, gpointer user_data)
+{
+ gtk_entry_set_text(GTK_ENTRY(file_browse_entry),
+ gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_browse)));
+}
+
+void on_file_browse_destroy (GtkObject *object, gpointer user_data)
+{
+ file_browse = NULL;
+ file_browse_entry = NULL;
+}
+
+void on_browse_clicked (GtkButton *button, gchar *user_data)
+{
+ gchar *text;
+ if (file_browse)
+ return;
+
+ file_browse = create_file_browse();
+ gtk_widget_show(file_browse);
+
+ file_browse_entry = EFIND(user_data);
+ text = gtk_editable_get_chars(GTK_EDITABLE(file_browse_entry), 0, -1);
+ gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_browse), text);
+ g_free(text);
+}
+
+void on_im_browse_clicked (GtkButton *button, gpointer user_data)
+{
+ on_browse_clicked(button, "im_sound_entry");
+}
+
+void on_signon_browse_clicked (GtkButton *button, gpointer user_data)
+{
+ on_browse_clicked(button, "signon_sound_entry");
+}
+
+void on_unidle_browse_clicked (GtkButton *button, gpointer user_data)
+{
+ on_browse_clicked(button, "unidle_sound_entry");
+}
+
+void on_unaway_browse_clicked (GtkButton *button, gpointer user_data)
+{
+ on_browse_clicked(button, "unaway_sound_entry");
+}
+
+void on_test_clicked (GtkButton *button, gchar *user_data)
+{
+ gchar *text =
+ gtk_editable_get_chars(GTK_EDITABLE(EFIND(user_data)), 0, -1);
+ play_sound_alias(text, NULL);
+ g_free(text);
+}
+
+void on_im_test_clicked (GtkButton *button, gpointer user_data)
+{
+ on_test_clicked(button, "im_sound_entry");
+}
+
+void on_signon_test_clicked (GtkButton *button, gpointer user_data)
+{
+ on_test_clicked(button, "signon_sound_entry");
+}
+
+void on_unidle_test_clicked (GtkButton *button, gpointer user_data)
+{
+ on_test_clicked(button, "unidle_sound_entry");
+}
+
+void on_unaway_test_clicked (GtkButton *button, gpointer user_data)
+{
+ on_test_clicked(button, "unaway_sound_entry");
+}
+
+void on_apply_clicked (GtkButton *button, gpointer user_data)
+{
+ struct smartear_entry *entry, tmp;
+
+ if (get_selection()) {
+ entry = selected_entry;
+
+ g_free(entry->name);
+ g_free(entry->sound[0]);
+ g_free(entry->sound[1]);
+ g_free(entry->sound[2]);
+ g_free(entry->sound[3]);
+ }
+ else {
+ entry = &tmp;
+ }
+
+ entry->name =
+ gtk_editable_get_chars(GTK_EDITABLE(EFIND("name_entry")), 0, -1);
+ entry->type =
+ gtk_option_menu_get_history(GTK_OPTION_MENU(EFIND("type_option"))) == 0
+ ? 'B' : 'G';
+ entry->sound[EVENT_M] =
+ gtk_editable_get_chars(GTK_EDITABLE(EFIND("im_sound_entry")), 0, -1);
+ entry->sound[EVENT_S] =
+ gtk_editable_get_chars(GTK_EDITABLE(EFIND("signon_sound_entry")), 0, -1);
+ entry->sound[EVENT_I] =
+ gtk_editable_get_chars(GTK_EDITABLE(EFIND("unidle_sound_entry")), 0, -1);
+ entry->sound[EVENT_A] =
+ gtk_editable_get_chars(GTK_EDITABLE(EFIND("unaway_sound_entry")), 0, -1);
+
+ if (!selected_entry) {
+ GSList *lp;
+ if ((lp = g_slist_find_custom(sounds_list, entry, (GCompareFunc)sound_cmp))) {
+ sound_free((struct smartear_entry*)lp->data, FALSE);
+ *(struct smartear_entry*)lp->data = *entry;
+ }
+ else {
+ struct smartear_entry *copy = g_new(struct smartear_entry, 1);
+ *copy = *entry;
+ new_entry(copy);
+ }
+ }
+
+ update_list();
+}
+
+void on_edit_win_destroy (GtkObject *object, gpointer user_data)
+{
+ edit_win = NULL;
+
+ if (config) {
+ gtk_widget_set_sensitive(GTK_WIDGET(treeview), TRUE);
+ }
+}
+
+void on_config_destroy (GtkObject *object, gpointer user_data)
+{
+ config = NULL;
+}
+
+/*** Util Functions ***/
+
+static void new_entry(struct smartear_entry *entry)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ GtkTreeViewColumn *name_column;
+
+ sounds_list = g_slist_append(sounds_list, entry);
+
+ if (!config)
+ return;
+
+ if (get_selection())
+ gtk_list_store_insert_after(GTK_LIST_STORE(treemodel), &iter, &selected_iter);
+ else
+ gtk_list_store_append(GTK_LIST_STORE(treemodel), &iter);
+
+ path = gtk_tree_model_get_path(treemodel, &iter);
+ list_set(GTK_LIST_STORE(treemodel), &iter, entry);
+
+ g_signal_handlers_block_by_func(G_OBJECT(treeselect), on_treeselect_changed, 0);
+ path = gtk_tree_model_get_path(treemodel, &iter);
+ name_column = gtk_tree_view_get_column(treeview, NAME_COL);
+ if (entry->name && entry->name[0])
+ gtk_tree_view_set_cursor(treeview, path, 0, FALSE);
+ else {
+ gtk_tree_view_set_cursor(treeview, path, name_column, TRUE);
+ }
+ gtk_tree_path_free(path);
+ g_signal_handlers_unblock_by_func(G_OBJECT(treeselect), on_treeselect_changed, 0);
+
+ get_selection();
+}
+
+static gboolean get_selection(void)
+{
+ selected_entry = NULL;
+
+ if (!config)
+ return FALSE;
+
+ if (!gtk_tree_selection_get_selected(treeselect, &treemodel, &selected_iter))
+ return FALSE;
+
+ gtk_tree_model_get(treemodel, &selected_iter, DATA_COL, &selected_entry, -1);
+ return TRUE;
+}
+
+void clear_selection(void)
+{
+ selected_entry = NULL;
+
+ if (!config)
+ return;
+
+ if (gtk_tree_selection_get_selected(treeselect, &treemodel, &selected_iter)) {
+ gtk_tree_selection_unselect_iter(treeselect, &selected_iter);
+ }
+}
+
+static void list_set(GtkListStore *store, GtkTreeIter *iter, struct smartear_entry *entry)
+{
+ gtk_list_store_set(store, iter, DATA_COL, entry, -1);
+}
+
+static char *my_normalize(const char *input)
+{
+ static char buf[BUF_LEN];
+ char *str, *beg;
+ int i=0;
+
+ g_return_val_if_fail((input != NULL), NULL);
+
+ beg = str = g_strdup(input);
+
+ while (*str && i <= BUF_LEN) {
+ if (*str != ' ')
+ buf[i++] = *str;
+ str++;
+ }
+ buf[i] = '\0';
+ g_free(beg);
+
+ return buf;
+
+}
+
+static struct smartear_entry *sound_new_with_name(gchar *name)
+{
+ struct smartear_entry tmp = default_entry;
+ tmp.name = name;
+ return sound_dup(&tmp);
+}
+
+static struct smartear_entry *sound_dup(struct smartear_entry *entry)
+{
+ struct smartear_entry *edup = g_new(struct smartear_entry, 1);
+ int i;
+
+ edup->type = entry->type;
+ edup->name = g_strdup(my_normalize(entry->name));
+ for (i = 0; i < EVENT_NUM; i++) {
+ edup->sound[i] = g_strdup(entry->sound[i]);
+ }
+
+ return edup;
+}
+
+static void sound_free(struct smartear_entry *entry, int free_entry)
+{
+ g_free(entry->name);
+ g_free(entry->sound[0]);
+ g_free(entry->sound[1]);
+ g_free(entry->sound[2]);
+ g_free(entry->sound[3]);
+ if (free_entry) {
+ g_free(entry);
+ }
+}
+
+static void soundlist_free(void)
+{
+ GSList *lp;
+ for (lp = sounds_list; lp; lp = g_slist_next(lp))
+ sound_free((struct smartear_entry*)lp->data, TRUE);
+ if (sounds_list) {
+ g_slist_free(sounds_list);
+ sounds_list = 0;
+ }
+}
+
+static gint sound_cmp(gconstpointer p1, gconstpointer p2)
+{
+ struct smartear_entry *entry1 = (struct smartear_entry*)p1;
+ struct smartear_entry *entry2 = (struct smartear_entry*)p2;
+
+ if (!entry1 || IS_DEFAULT(entry1))
+ return -1;
+ if (!entry2 || IS_DEFAULT(entry2))
+ return 1;
+
+ /* only compare types if both are nonzero */
+ if (entry1->type != entry2->type &&
+ entry1->type != 0 && entry2->type != 0)
+ return (entry1->type - entry2->type);
+ return (g_strcasecmp(entry1->name, entry2->name));
+}
+
+static void populate_edit_win(struct smartear_entry *entry)
+{
+ gtk_entry_set_text(GTK_ENTRY(EFIND("name_entry")), entry->name);
+ gtk_entry_set_text(GTK_ENTRY(EFIND("im_sound_entry")),
+ entry->sound[EVENT_M]);
+ gtk_entry_set_text(GTK_ENTRY(EFIND("signon_sound_entry")),
+ entry->sound[EVENT_S]);
+ gtk_entry_set_text(GTK_ENTRY(EFIND("unidle_sound_entry")),
+ entry->sound[EVENT_I]);
+ gtk_entry_set_text(GTK_ENTRY(EFIND("unaway_sound_entry")),
+ entry->sound[EVENT_A]);
+ gtk_option_menu_set_history(GTK_OPTION_MENU(EFIND("type_option")),
+ (entry->type == 'B' ? 0 : 1));
+
+ if (IS_DEFAULT(entry)) {
+ gtk_widget_set_sensitive(EFIND("name_entry"), FALSE);
+ gtk_widget_set_sensitive(EFIND("type_menu"), FALSE);
+ }
+
+ if (config) {
+ gtk_widget_set_sensitive(GTK_WIDGET(treeview), FALSE);
+ }
+}
+
+static void set_option_entries(void)
+{
+ GtkSpinButton *delay_spin = GTK_SPIN_BUTTON(FIND("delay_spin"));
+ GtkToggleButton *focus_but = GTK_TOGGLE_BUTTON(FIND("focus_but"));
+ GtkToggleButton *timer_but = GTK_TOGGLE_BUTTON(FIND("timer_but"));
+
+ g_signal_handlers_block_by_func(G_OBJECT(delay_spin), on_delay_changed, 0);
+ g_signal_handlers_block_by_func(G_OBJECT(focus_but), on_focus_toggled, 0);
+ g_signal_handlers_block_by_func(G_OBJECT(timer_but), on_timer_toggled, 0);
+
+ gtk_spin_button_set_value(delay_spin, (gdouble)message_delay);
+ gtk_toggle_button_set_active(focus_but, focused_quiet);
+ gtk_toggle_button_set_active(timer_but, smartear_timers);
+
+ g_signal_handlers_unblock_by_func(G_OBJECT(delay_spin), on_delay_changed, 0);
+ g_signal_handlers_unblock_by_func(G_OBJECT(focus_but), on_focus_toggled, 0);
+ g_signal_handlers_unblock_by_func(G_OBJECT(timer_but), on_timer_toggled, 0);
+}
+
+static void update_list(void)
+{
+ if (selected_entry)
+ list_set(GTK_LIST_STORE(treemodel), &selected_iter, selected_entry);
+}
+
+static gchar* get_basename(gchar *path)
+{
+ static gchar base[BUF_LEN];
+ gchar *p;
+
+ if (!path || !path[0]) {
+ return "";
+ }
+
+ if ((p = strrchr(path, '/'))) {
+ p++;
+ }
+ else {
+ p = path;
+ }
+
+ strncpy(base, p, sizeof(base));
+
+ return base;
+}
+
+/*** Init Functions ***/
+
+static void populate_list(GtkListStore *store)
+{
+ GtkTreeIter iter;
+ GSList *lp;
+
+ sounds_list = g_slist_sort(sounds_list, (GCompareFunc)sound_cmp);
+
+ for (lp = sounds_list; lp; lp = g_slist_next(lp)) {
+ struct smartear_entry *entry = (struct smartear_entry*)lp->data;
+ gtk_list_store_append(store, &iter);
+ list_set(store, &iter, entry);
+ if (entry == selected_entry)
+ selected_iter = iter;
+ }
+}
+
+static void render_type(GtkTreeViewColumn *column, GtkCellRenderer *cell,
+ GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
+{
+ struct smartear_entry *entry;
+ gtk_tree_model_get(model, iter, DATA_COL, &entry, -1);
+ if (IS_DEFAULT(entry))
+ g_object_set(cell, "text", "", NULL);
+ else
+ g_object_set(cell, "text", entry->type == 'B' ? "Buddy" : "Group", NULL);
+}
+
+static void render_name(GtkTreeViewColumn *column, GtkCellRenderer *cell,
+ GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
+{
+ struct smartear_entry *entry;
+ gtk_tree_model_get(model, iter, DATA_COL, &entry, -1);
+ g_object_set(cell, "text", entry->name, NULL);
+}
+
+static void render_when(GtkTreeViewColumn *column, GtkCellRenderer *cell,
+ GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
+{
+ struct smartear_entry *entry;
+ gint which = GPOINTER_TO_INT(data);
+ gtk_tree_model_get(model, iter, DATA_COL, &entry, -1);
+ g_object_set(cell, "text", get_basename(entry->sound[which]), NULL);
+}
+
+static gint list_cmp(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer d)
+{
+ struct smartear_entry *entry1, *entry2;
+
+ gtk_tree_model_get(model, a, DATA_COL, &entry1, -1);
+ gtk_tree_model_get(model, b, DATA_COL, &entry2, -1);
+
+ return sound_cmp(entry1, entry2);
+}
+
+static void setup_list(void)
+{
+ GtkListStore *store;
+ GtkCellRenderer *cell;
+
+ treeview = GTK_TREE_VIEW(FIND("treeview"));
+
+ store = gtk_list_store_new(1, G_TYPE_POINTER);
+ populate_list(store);
+
+ gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(store));
+ g_object_unref(G_OBJECT(store)); // treeview has it's own copy.
+ treemodel = gtk_tree_view_get_model(treeview);
+ gtk_tree_sortable_set_default_sort_func(GTK_TREE_SORTABLE(treemodel),
+ (GtkTreeIterCompareFunc)&list_cmp, 0, 0);
+ gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(treemodel),
+ GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING);
+
+ treeselect = gtk_tree_view_get_selection(treeview);
+ gtk_tree_selection_set_mode(treeselect, GTK_SELECTION_SINGLE);
+ g_signal_connect(G_OBJECT(treeselect), "changed",
+ G_CALLBACK(on_treeselect_changed), NULL);
+
+ /* Type column */
+ cell = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_data_func(treeview, -1, "Type",
+ cell, render_type, 0, 0);
+
+ /* Name column */
+ cell = gtk_cell_renderer_text_new();
+ g_signal_connect(G_OBJECT(cell), "edited",
+ G_CALLBACK(on_cell_edited), GINT_TO_POINTER(NAME_COL));
+ g_object_set(G_OBJECT(cell), "editable", TRUE, NULL);
+ gtk_tree_view_insert_column_with_data_func(treeview, -1, "Name",
+ cell, render_name, 0, 0);
+
+ cell = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_data_func(treeview, -1, "On Message",
+ cell, render_when, GINT_TO_POINTER(EVENT_M), 0);
+
+ cell = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_data_func(treeview, -1, "On Signon",
+ cell, render_when, GINT_TO_POINTER(EVENT_S), 0);
+
+ cell = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_data_func(treeview, -1, "On Unidle",
+ cell, render_when, GINT_TO_POINTER(EVENT_I), 0);
+
+ cell = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_data_func(treeview, -1, "On Unaway",
+ cell, render_when, GINT_TO_POINTER(EVENT_A), 0);
+}
+
+static void smartear_save(void)
+{
+ char file[BUF_LEN] = "smartear.rc - you have no home dir";
+ FILE *fp = NULL;
+ GSList *lp;
+ struct smartear_entry *entry;
+
+ if (purple_user_dir()) {
+ g_snprintf(file, sizeof(file), "%s/smartear.rc", purple_user_dir());
+ fp = fopen(file, "w");
+ }
+
+ if (fp == NULL) {
+ g_warning("couldn't open %s\n", file);
+ return;
+ }
+
+ fprintf(fp, "version %d\n", RCFILE_VERSION);
+ fprintf(fp, "smartear_timers %d\n", smartear_timers);
+ fprintf(fp, "delay %d\n", message_delay);
+ fprintf(fp, "focused_quiet %d\n", focused_quiet);
+
+ /* save empties as a single space so scanf doesn't get confused */
+#define SAVE_STR(str) (IS_EMPTY(str) ? RC_EMPTY_SOUND : str)
+ for (lp = sounds_list; lp; lp = g_slist_next(lp)) {
+ entry = (struct smartear_entry*)lp->data;
+ fprintf(fp, "%c {%s} {%s} {%s} {%s} {%s}\n",
+ entry->type, entry->name,
+ SAVE_STR(entry->sound[EVENT_M]),
+ SAVE_STR(entry->sound[EVENT_S]),
+ SAVE_STR(entry->sound[EVENT_I]),
+ SAVE_STR(entry->sound[EVENT_A]));
+ }
+
+ fclose(fp);
+}
+
+static void smartear_load(void)
+{
+ char file[BUF_LEN] = "smartear.rc - you have no home dir";
+ FILE *fp = NULL;
+ struct smartear_entry *entry;
+ char buf[BUF_LEN];
+ gboolean has_default = FALSE;
+ int rcfile_version = 1;
+
+ if (purple_user_dir()) {
+ g_snprintf(file, sizeof(file), "%s/smartear.rc", purple_user_dir());
+ fp = fopen(file, "r");
+ }
+
+ if (fp == NULL) {
+ g_warning("smartear: couldn't open %s\n", file);
+ sounds_list = g_slist_append(sounds_list, sound_dup(&default_entry));
+ return;
+ }
+
+ while ((fgets(buf, sizeof(buf), fp))) {
+ int tmp;
+ if (sscanf(buf, "version %d", &tmp) == 1)
+ rcfile_version = tmp;
+ else if (sscanf(buf, "smarterear_timers %d", &tmp) == 1)
+ smartear_timers = tmp;
+ else if (sscanf(buf, "smartear_timers %d", &tmp) == 1)
+ smartear_timers = tmp;
+ else if (sscanf(buf, "delay %d", &tmp) == 1)
+ message_delay = tmp;
+ else if (sscanf(buf, "focused_quiet %d", &tmp) == 1)
+ focused_quiet = tmp;
+ else if (rcfile_version == 1) {
+ char name[BUF_LEN];
+ char flags[BUF_LEN];
+ char sound[BUF_LEN];
+ char type;
+
+ if (sscanf(buf, "%c {%[^}]} {%[^}]} {%[^}]}",
+ &type, name, flags, sound) == 4) {
+ if (type != 'G' && type != 'B') {
+ g_warning("smartear: rc no such type: %c", type);
+ continue;
+ }
+
+ entry = g_new(struct smartear_entry, 1);
+ entry->type = type;
+ entry->name = g_strdup(my_normalize(name));
+ if (strchr(flags, 'M')) entry->sound[EVENT_M] = g_strdup(sound);
+ else entry->sound[EVENT_M] = g_strdup("");
+ if (strchr(flags, 'S')) entry->sound[EVENT_S] = g_strdup(sound);
+ else entry->sound[EVENT_S] = g_strdup("");
+ if (strchr(flags, 'I')) entry->sound[EVENT_I] = g_strdup(sound);
+ else entry->sound[EVENT_I] = g_strdup("");
+ if (strchr(flags, 'A')) entry->sound[EVENT_A] = g_strdup(sound);
+ else entry->sound[EVENT_A] = g_strdup("");
+
+ sounds_list = g_slist_append(sounds_list, entry);
+
+ if (IS_DEFAULT(entry)) {
+ default_entry = *entry;
+ has_default = TRUE;
+ }
+ }
+ else
+ g_warning("smartear: rc1 syntax error: %s", buf);
+ }
+ else if (rcfile_version == 2) {
+ char name[BUF_LEN];
+ char sound[EVENT_NUM][BUF_LEN];
+ char type;
+ int i;
+
+ if (sscanf(buf, "%c {%[^}]} {%[^}]} {%[^}]} {%[^}]} {%[^}]}",
+ &type, name, sound[EVENT_M], sound[EVENT_S],
+ sound[EVENT_I], sound[EVENT_A]) == 6) {
+ if (type != 'G' && type != 'B') {
+ g_warning("smartear: rc no such type: %c", type);
+ continue;
+ }
+
+ for (i = 0; i < EVENT_NUM; i++) {
+ if (strcmp(sound[i], RC_EMPTY_SOUND) == 0)
+ sound[i][0] = 0;
+ }
+
+ entry = g_new(struct smartear_entry, 1);
+ entry->type = type;
+ entry->name = g_strdup(my_normalize(name));
+ entry->sound[EVENT_M] = g_strdup(sound[EVENT_M]);
+ entry->sound[EVENT_S] = g_strdup(sound[EVENT_S]);
+ entry->sound[EVENT_I] = g_strdup(sound[EVENT_I]);
+ entry->sound[EVENT_A] = g_strdup(sound[EVENT_A]);
+
+ sounds_list = g_slist_append(sounds_list, entry);
+
+ if (IS_DEFAULT(entry)) {
+ default_entry = *entry;
+ has_default = TRUE;
+ }
+ }
+ else
+ g_warning("smartear: rc2 syntax error: %s", buf);
+ }
+ else
+ g_warning("smartear: rc syntax error: %s", buf);
+ }
+ if (!has_default)
+ sounds_list = g_slist_append(sounds_list, sound_dup(&default_entry));
+
+ fclose(fp);
+}
+
+/*** Purple callbacks ***/
+
+static struct message_data *find_message_by_name(PurpleAccount *account, const char *pname)
+{
+ GSList *lp;
+ struct message_data *msg = NULL;
+ char *name = g_strdup(my_normalize(pname));
+
+ for (lp = messages_list; lp; lp = g_slist_next(lp)) {
+ msg = (struct message_data*)lp->data;
+ if (msg->account == account
+ && g_strcasecmp(msg->buddy, name) == 0)
+ break;
+ }
+
+ g_free(name);
+
+ if (lp)
+ return msg;
+ return 0;
+}
+
+static void message_timer_remove(struct message_data *msg)
+{
+ if (msg && msg->timer) {
+ g_source_remove(msg->timer->id);
+ g_free(msg->timer);
+ msg->timer = NULL;
+ }
+}
+
+static void message_free(struct message_data *msg)
+{
+ message_timer_remove(msg);
+ g_free(msg->buddy);
+ g_free(msg);
+}
+
+static void messagelist_free()
+{
+ GSList *lp;
+ for (lp = messages_list; lp; lp = g_slist_next(lp))
+ message_free((struct message_data*)lp->data);
+ if (messages_list) {
+ g_slist_free(messages_list);
+ messages_list = NULL;
+ }
+}
+
+static void on_smartear_clicked(PurpleBlistNode* node, gpointer data)
+{
+ struct smartear_entry tmp, *entry;
+ GSList *lp;
+
+ clear_selection();
+
+ if (!edit_win) {
+ edit_win = create_edit_win();
+ }
+ gtk_widget_show_all(edit_win);
+
+ tmp = default_entry;
+
+ if (!node) {
+ return;
+ }
+ else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
+ tmp.type = 'B';
+ tmp.name = ((PurpleBuddy*)node)->name;
+ purple_debug(PURPLE_DEBUG_INFO, "smartear", "adding buddy %s", tmp.name);
+ }
+ else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) {
+ tmp.type = 'B';
+ tmp.name = ((PurpleContact*)node)->alias;
+ if (!tmp.name) {
+ tmp.name = ((PurpleContact*)node)->priority->name;
+ }
+ purple_debug(PURPLE_DEBUG_INFO, "smartear", "adding contact %s", tmp.name);
+ }
+ else if (PURPLE_BLIST_NODE_IS_GROUP(node)) {
+ tmp.type = 'G';
+ tmp.name = ((PurpleGroup*)node)->name;
+ g_warning("group %p, %p %s", node, tmp.name, tmp.name);
+ purple_debug(PURPLE_DEBUG_INFO, "smartear", "adding group %s", tmp.name);
+ }
+ else {
+ return;
+ }
+
+ if ((lp = g_slist_find_custom(sounds_list, &tmp, (GCompareFunc)sound_cmp))) {
+ entry = (struct smartear_entry*)lp->data;
+ }
+ else {
+ entry = &tmp;
+ }
+
+ populate_edit_win(entry);
+}
+
+static void play_sound_alias(char *sound, PurpleAccount* account)
+{
+ struct smartear_entry tmp, *entry;
+ GSList *lp;
+
+ if (!sound || !*sound)
+ return;
+
+ /* sound aliases: mostly so you can put (Default) for sound, and it'll
+ * play that one */
+ tmp.type = 0;
+ tmp.name = sound;
+ if ((lp = g_slist_find_custom(sounds_list, &tmp, (GCompareFunc)sound_cmp))) {
+ entry = (struct smartear_entry*)lp->data;
+ play_sound_alias(entry->sound[EVENT_M], account);
+ }
+ else {
+ purple_sound_play_file(sound, account);
+ }
+}
+
+void play_matching_sound(PurpleBuddy *buddy, int event)
+{
+ GSList *lp;
+ struct smartear_entry *entry;
+ char *sound = NULL;
+ char *name = buddy ? g_strdup(my_normalize(buddy->name)) : NULL;
+ PurpleGroup *g = buddy ? purple_buddy_get_group(buddy) : NULL;
+
+ for (lp = sounds_list; lp; lp = g_slist_next(lp)) {
+ entry = (struct smartear_entry*)lp->data;
+ if (!entry->sound[event])
+ continue;
+
+ if (entry->type == 'B' && name
+ && g_strcasecmp(name, entry->name) == 0) {
+ sound = entry->sound[event];
+ /* found a buddy match.. this takes precedence, so stop */
+ break;
+ }
+ if (entry->type == 'G' && g
+ && g_strcasecmp(my_normalize(g->name), entry->name) == 0) {
+ sound = entry->sound[event];
+ /* keep going... buddy overrides group */
+ }
+ if (IS_DEFAULT(entry)) {
+ if (!sound)
+ sound = entry->sound[event];
+ /* keep going.. other 2 override default */
+ }
+ }
+ if (!IS_EMPTY(sound)) {
+ purple_debug(PURPLE_DEBUG_INFO, "smartear",
+ "found %s for %s on event %d\n", sound, name, event);
+ play_sound_alias(sound, purple_buddy_get_account(buddy));
+ }
+ else {
+ purple_debug(PURPLE_DEBUG_INFO, "smartear",
+ "no sound found for %s on event %d\n", name, event);
+ }
+ g_free(name);
+}
+
+static gint play_sound_timer_hook(gpointer data)
+{
+ struct message_data *msg = (struct message_data *)data;
+
+ if(!msg || !msg->timer) {
+ g_warning("smartear: timer called without being active!\n");
+ return FALSE;
+ }
+
+ play_matching_sound(purple_find_buddy(msg->account, msg->buddy), msg->timer->event);
+
+ g_free(msg->timer);
+ msg->timer = NULL;
+
+ return FALSE;
+}
+
+static gboolean on_im_recv(PurpleAccount *account, char *who, char *what, gint32 flags, void *junk)
+{
+ struct message_data *msg;
+ time_t now = time(0);
+ PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, who, account);
+ PidginConversation *gtkconv = conv ? PIDGIN_CONVERSATION(conv) : NULL;
+
+ /* FIXME: message list is never trimmed. However, if we DO trim it,
+ * we need to consider race conditions on the msg field of the timer_hook */
+
+ if ((msg = find_message_by_name(account, who))) {
+ /* only install a timer if there's no active timers and we've just
+ * sent a message. If we haven't just sent a message, then
+ * a beep will go off anyways when the IM arrives. */
+ if(smartear_timers && !msg->timer
+ && msg->last_sent + message_delay > now) {
+ msg->timer = g_new0(struct timer_data, 1);
+ msg->timer->event = EVENT_M;
+ msg->timer->id = g_timeout_add(message_delay*1000,
+ play_sound_timer_hook, msg);
+ }
+
+ if (msg->last_active + message_delay > now && conv) {
+ purple_debug(PURPLE_DEBUG_INFO, "smartear",
+ "received IM from %s, but only %d/%d seconds passed.\n",
+ who, now - msg->last_active, message_delay);
+ return FALSE;
+ }
+ }
+ else {
+ msg = g_new0(struct message_data, 1);
+ msg->account = account;
+ msg->buddy = g_strdup(my_normalize(who));
+ msg->timer = NULL;
+
+ messages_list = g_slist_append(messages_list, msg);
+ }
+
+ msg->last_active = now;
+
+ if (focused_quiet && gtkconv && GTK_WIDGET_HAS_FOCUS(gtkconv->entry))
+ return FALSE; /* don't play sounds for the focused convo */
+ if (gtkconv && !gtkconv->make_sound)
+ return FALSE;
+
+ play_matching_sound(purple_find_buddy(msg->account, msg->buddy), EVENT_M);
+
+ return FALSE;
+}
+
+static void on_im_send(PurpleAccount *account, char *who, char *what, void *junk)
+{
+ struct message_data *msg;
+ time_t now = time(0);
+
+ if ((msg = find_message_by_name(account, who))) {
+ message_timer_remove(msg);
+ }
+ else {
+ msg = g_new0(struct message_data, 1);
+ msg->account = account;
+ msg->buddy = g_strdup(my_normalize(who));
+ msg->timer = NULL;
+
+ messages_list = g_slist_append(messages_list, msg);
+ }
+
+ msg->last_active = now;
+ msg->last_sent = now;
+}
+
+static void on_buddy_signon(PurpleBuddy *buddy, void *data)
+{
+ play_matching_sound(buddy, EVENT_S);
+}
+
+static void on_buddy_back(PurpleBuddy *buddy, void *data)
+{
+ play_matching_sound(buddy, EVENT_A);
+}
+
+static void on_buddy_unidle(PurpleBuddy *buddy, void *data)
+{
+ play_matching_sound(buddy, EVENT_I);
+}
+
+static void on_signon(PurpleConnection *gc, void *m)
+{
+}
+
+static void on_signoff(PurpleConnection *gc, void *m)
+{
+ messagelist_free();
+}
+
+static void on_blist_node_extended_menu(PurpleBlistNode *node, GList **menu)
+{
+ PurpleMenuAction *menu_action;
+ menu_action = purple_menu_action_new(_("Edit SmartEar Entry"),
+ PURPLE_CALLBACK(on_smartear_clicked), NULL, NULL);
+ *menu = g_list_append(*menu, menu_action);
+}
+
+static gboolean purple_plugin_init(PurplePlugin *plugin)
+{
+ void *blist_handle = purple_blist_get_handle();
+ void *conv_handle = purple_conversations_get_handle();
+
+ config = NULL;
+
+ smartear_load();
+
+ purple_signal_connect(blist_handle, "blist-node-extended-menu",
+ plugin, PURPLE_CALLBACK(on_blist_node_extended_menu), NULL);
+
+ purple_signal_connect(blist_handle, "buddy-signed-on",
+ plugin, PURPLE_CALLBACK(on_buddy_signon), NULL);
+ purple_signal_connect(blist_handle, "buddy-back",
+ plugin, PURPLE_CALLBACK(on_buddy_back), NULL);
+ purple_signal_connect(blist_handle, "buddy-unidle",
+ plugin, PURPLE_CALLBACK(on_buddy_unidle), NULL);
+
+ purple_signal_connect(conv_handle, "received-im-msg",
+ plugin, PURPLE_CALLBACK(on_im_recv), NULL);
+ purple_signal_connect(conv_handle, "sent-im-msg",
+ plugin, PURPLE_CALLBACK(on_im_send), NULL);
+
+ purple_signal_connect(purple_connections_get_handle(), "signed-on",
+ plugin, PURPLE_CALLBACK(on_signon), NULL);
+ purple_signal_connect(purple_connections_get_handle(), "signed-off",
+ plugin, PURPLE_CALLBACK(on_signoff), NULL);
+
+ return TRUE;
+}
+
+static gboolean purple_plugin_remove(PurplePlugin *h)
+{
+ config = NULL;
+
+ soundlist_free();
+ messagelist_free();
+
+ return TRUE;
+}
+
+static GtkWidget *purple_plugin_config_gtk(PurplePlugin *plugin)
+{
+ config = create_config();
+
+ setup_list();
+ set_option_entries();
+
+ gtk_widget_show_all(config);
+
+ return config;
+}
+
+static PurplePluginUiInfo ui_info = {
+ purple_plugin_config_gtk,
+ 0 /* page_num (reserved) */
+};
+
+static PurplePluginInfo info =
+{
+ PURPLE_PLUGIN_MAGIC,
+ PURPLE_MAJOR_VERSION,
+ PURPLE_MINOR_VERSION,
+ PURPLE_PLUGIN_STANDARD,
+ PIDGIN_PLUGIN_TYPE,
+ 0,
+ NULL,
+ PURPLE_PRIORITY_DEFAULT,
+ SMARTEAR_PLUGIN_ID,
+ NULL,
+ PP_VERSION,
+ NULL,
+ NULL,
+ "Matt Perry <guy@fscked.org>",
+ PP_WEBSITE,
+ purple_plugin_init,
+ purple_plugin_remove,
+ NULL,
+ &ui_info,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static void init_plugin(PurplePlugin *plugin)
+{
+#ifdef ENABLE_NLS
+ bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
+ bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
+#endif
+
+ info.name= _("Smart Ear");
+ info.summary = _("Assign different sounds to different buddies and groups");
+ info.description =
+ _("Allows you to assign different sounds to play for different buddies "
+ "or whole groups of buddies. Smart Ear allows you to opt to play "
+ "sounds when a buddy sends you an IM, signs on, returns from away "
+ "or idle, or any combination of these, so you'll know by the sound "
+ "what the important people are doing.");
+}
+
+PURPLE_INIT_PLUGIN(smartear, init_plugin, info);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smartear/old-smartear.glade Sun Aug 19 04:42:58 2007 -0400
@@ -0,0 +1,1018 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkWindow" id="config">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">SmartEar Configuration</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="focus_on_map">True</property>
+ <property name="urgency_hint">False</property>
+
+ <child>
+ <widget class="GtkVBox" id="config_vbox">
+ <property name="height_request">640</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+ <signal name="destroy" handler="on_config_destroy"/>
+
+ <child>
+ <widget class="GtkFrame" id="frame1">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
+
+ <child>
+ <widget class="GtkTable" id="table1">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">2</property>
+ <property name="homogeneous">False</property>
+ <property name="row_spacing">10</property>
+ <property name="column_spacing">10</property>
+
+ <child>
+ <widget class="GtkLabel" id="label9">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Time delay between playing sounds for a particular buddy:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkSpinButton" id="delay_spin">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="climb_rate">1</property>
+ <property name="digits">0</property>
+ <property name="numeric">False</property>
+ <property name="update_policy">GTK_UPDATE_IF_VALID</property>
+ <property name="snap_to_ticks">False</property>
+ <property name="wrap">False</property>
+ <property name="adjustment">60 0 1000000 1 10 10</property>
+ <signal name="changed" handler="on_delay_changed"/>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options"></property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCheckButton" id="focus_but">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Don't play sounds for the conversation that has focus.</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_focus_toggled"/>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCheckButton" id="timer_but">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Also play sounds if you don't respond to a particular IM within a delay period.</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_timer_toggled"/>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Options</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkFrame" id="frame2">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
+
+ <child>
+ <widget class="GtkTable" id="table2">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">3</property>
+ <property name="homogeneous">False</property>
+ <property name="row_spacing">10</property>
+ <property name="column_spacing">10</property>
+
+ <child>
+ <widget class="GtkButton" id="delete_but">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-delete</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_delete_clicked"/>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options"></property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="new_but">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-new</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_new_clicked"/>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options"></property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">True</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">True</property>
+ <property name="fixed_height_mode">False</property>
+ <property name="hover_selection">False</property>
+ <property name="hover_expand">False</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="edit_but">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-properties</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_edit_clicked"/>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options"></property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Entries</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHButtonBox" id="hbuttonbox1">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_SPREAD</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="revert_but">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-revert-to-saved</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_revert_clicked"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="save_but">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-save</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_save_clicked"/>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkFileSelection" id="file_browse">
+ <property name="border_width">10</property>
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Select Sound</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="focus_on_map">True</property>
+ <property name="urgency_hint">False</property>
+ <property name="show_fileops">True</property>
+ <signal name="destroy" handler="on_file_browse_destroy"/>
+
+ <child internal-child="cancel_button">
+ <widget class="GtkButton" id="cancel_button1">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="gtk_widget_destroy" object="file_browse"/>
+ </widget>
+ </child>
+
+ <child internal-child="ok_button">
+ <widget class="GtkButton" id="ok_button1">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_browse_ok_clicked"/>
+ <signal name="clicked" handler="gtk_widget_destroy" object="file_browse"/>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkWindow" id="edit_win">
+ <property name="width_request">600</property>
+ <property name="height_request">300</property>
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Edit Entry</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="default_width">600</property>
+ <property name="default_height">300</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="focus_on_map">True</property>
+ <property name="urgency_hint">False</property>
+ <signal name="destroy" handler="on_edit_win_destroy"/>
+
+ <child>
+ <widget class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox1">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">5</property>
+
+ <child>
+ <widget class="GtkLabel" id="label29">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Name:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">1</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="name_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label30">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Type:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">1</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkOptionMenu" id="type_option">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="history">0</property>
+
+ <child>
+ <widget class="GtkMenu" id="menu1">
+
+ <child>
+ <widget class="GtkMenuItem" id="item_buddy">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Buddy</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="item_group">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Group</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">10</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHButtonBox" id="hbuttonbox2">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_SPREAD</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="applysave_but">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Apply and Save</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_apply_clicked"/>
+ <signal name="clicked" handler="on_save_clicked"/>
+ <signal name="clicked" handler="gtk_widget_destroy" object="edit_win"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="apply_but">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-apply</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_apply_clicked"/>
+ <signal name="clicked" handler="gtk_widget_destroy" object="edit_win"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="cancel_but">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-cancel</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="gtk_widget_destroy" object="edit_win"/>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkFrame" id="frame3">
+ <property name="border_width">5</property>
+ <property name="height_request">200</property>
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
+
+ <child>
+ <widget class="GtkTable" id="table5">
+ <property name="border_width">5</property>
+ <property name="width_request">600</property>
+ <property name="height_request">400</property>
+ <property name="visible">True</property>
+ <property name="n_rows">4</property>
+ <property name="n_columns">5</property>
+ <property name="homogeneous">False</property>
+ <property name="row_spacing">10</property>
+ <property name="column_spacing">10</property>
+
+ <child>
+ <widget class="GtkLabel" id="label31">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Play On IM:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options"></property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label34">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Play On Unaway:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options"></property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label33">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Play On Unidle:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options"></property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label32">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Play On Signon:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options"></property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="unaway_sound_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="unidle_sound_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="signon_sound_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="unaway_test_but">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Test</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_unaway_test_clicked"/>
+ </widget>
+ <packing>
+ <property name="left_attach">4</property>
+ <property name="right_attach">5</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options"></property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="unidle_test_but">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Test</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_unidle_test_clicked"/>
+ </widget>
+ <packing>
+ <property name="left_attach">4</property>
+ <property name="right_attach">5</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options"></property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="signon_test_but">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Test</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_signon_test_clicked"/>
+ </widget>
+ <packing>
+ <property name="left_attach">4</property>
+ <property name="right_attach">5</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options"></property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="unaway_browse_but">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-open</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_unaway_browse_clicked"/>
+ </widget>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="right_attach">4</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options"></property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="unidle_browse_but">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-open</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_unidle_browse_clicked"/>
+ </widget>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="right_attach">4</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options"></property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="signon_browse_but">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-open</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_signon_browse_clicked"/>
+ </widget>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="right_attach">4</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options"></property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="im_browse_but">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-open</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_im_browse_clicked"/>
+ </widget>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="right_attach">4</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options"></property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="im_sound_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="im_test_but">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Test</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_im_test_clicked"/>
+ </widget>
+ <packing>
+ <property name="left_attach">4</property>
+ <property name="right_attach">5</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options"></property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label24">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Sound Events</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+</glade-interface>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smartear/smartear.c Sun Aug 19 04:42:58 2007 -0400
@@ -0,0 +1,267 @@
+/*
+ * smartear.c - SmartEar plugin for libpurple
+ * Copyright (c) 2007 John Bailey <rekkanoryo@rekkanoryo.org>
+ *
+ * Original code copyright (c) 2003-2007 Matt Perry
+ *
+ * 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
+ *
+ * This plugin is a hidden plugin. It follows preferences set by other plugins
+ * which are specific to the libpurple UI in use. The GTK+ plugin for Pidgin
+ * and the GNT plugin for Finch will list this plugin as a dependency, causing
+ * libpurple to load this plugin.
+ */
+
+#define PURPLE_PLUGINS
+
+#ifdef HAVE_CONFIG_H
+# include "../pp_config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include "../common/pp_internal.h"
+
+/* libpurple headers */
+#include <blist.h>
+#include <debug.h>
+#include <plugin.h>
+#include <pluginpref.h>
+#include <sound.h>
+#include <signals.h>
+#include <version.h>
+
+/* Glib header */
+#include <glib.h>
+
+/* Enumerations */
+
+typedef enum {
+ SMARTEAR_EVENT_SIGNON,
+ SMARTEAR_EVENT_SIGNOFF,
+ SMARTEAR_EVENT_IDLECHG,
+ SMARTEAR_EVENT_RECEIVEDMSG,
+ SMARTEAR_EVENT_SENTMSG
+} SmartEarEvent;
+
+/* Helpers */
+
+static const char *
+smartear_event_get_setting_string(SmartEarEvent event)
+{
+ const char *setting = NULL;
+
+ switch(event) {
+ case SMARTEAR_EVENT_SIGNON:
+ setting = "signon_sound";
+ break;
+ case SMARTEAR_EVENT_SIGNOFF:
+ setting = "signoff_sound";
+ break;
+ case SMARTEAR_EVENT_IDLECHG:
+ setting = "idlechg_sound";
+ break;
+ case SMARTEAR_EVENT_RECEIVEDMSG:
+ setting = "receivedmsg_sound";
+ break;
+ case SMARTEAR_EVENT_SENTMSG:
+ setting = "sentmsg_sound";
+ break;
+ }
+
+ return setting;
+}
+
+static const char *
+smartear_sound_get_default(SmartEarEvent event)
+{
+ const char *prefname = NULL, *prefval = NULL;
+ char *prefpath = NULL;
+
+ prefname = smartear_event_get_setting_string(event);
+ prefpath = g_strdup_printf("/plugins/core/smartear/%s", prefname);
+ prefval = purple_prefs_get_string(prefpath);
+
+ g_free(prefpath);
+
+ return prefval;
+}
+
+static const char *
+smartear_sound_determine(const char *bfile, const char *cfile, const char *gfile, SmartEarEvent event)
+{
+ const char *pfile = NULL;
+
+ /* if the string is "(Default)" then set the pointer to NULL */
+ if(!g_ascii_strcasecmp(bfile, "(Default)"))
+ bfile = NULL;
+ if(!g_ascii_strcasecmp(cfile, "(Default)"))
+ cfile = NULL;
+ if(!g_ascii_strcasecmp(gfile, "(Default)"))
+ gfile = NULL;
+
+ /* determine the sound to play - if the pointer is NULL, try falling back
+ * to another sound - if no sound defined at any level, fall back to the
+ * default */
+ if(!bfile)
+ if(!cfile)
+ if(!gfile)
+ pfile = smartear_sound_get_default(event);
+ else
+ pfile = gfile;
+ else
+ pfile = cfile;
+ else
+ pfile = bfile;
+
+ return pfile;
+}
+
+static void
+smartear_sound_play(PurpleBuddy *buddy, PurpleAccount *account, SmartEarEvent event)
+{
+ const char *bfile = NULL, *cfile = NULL, *gfile = NULL, *pfile = NULL, *setting = NULL;
+ PurpleBlistNode *bnode = (PurpleBlistNode *)buddy,
+ *cnode = (PurpleBlistNode *)(bnode->parent),
+ *gnode = (PurpleBlistNode *)(cnode->parent);
+
+ /* get the setting string */
+ setting = smartear_event_get_setting_string(event);
+
+ /* grab the settings from each blist node in the hierarchy */
+ bfile = purple_blist_node_get_string(bnode, setting);
+ cfile = purple_blist_node_get_string(cnode, setting);
+ gfile = purple_blist_node_get_string(gnode, setting);
+
+ /* determine which sound to play */
+ pfile = smartear_sound_determine(bfile, cfile, gfile, event);
+
+ if(pfile)
+ purple_sound_play_file(pfile, account);
+}
+
+/* Callbacks */
+
+static void
+smartear_cb_sent_msg(PurpleAccount *account, const gchar *receiver, const gchar *message)
+{
+ PurpleBuddy *buddy = purple_find_buddy(account, receiver);
+
+ smartear_sound_play(buddy, account, SMARTEAR_EVENT_SENTMSG);
+}
+
+static void
+smartear_cb_received_msg(PurpleAccount *account, gchar *sender, char *message,
+ PurpleConversation *conv, PurpleMessageFlags flags)
+{
+ if(!(flags & PURPLE_MESSAGE_SYSTEM)) {
+ PurpleBuddy *buddy = purple_find_buddy(account, sender);
+
+ smartear_sound_play(buddy, account, SMARTEAR_EVENT_RECEIVEDMSG);
+ }
+}
+
+static void
+smartear_cb_idle(PurpleBuddy *buddy, gboolean wasidle, gboolean nowidle)
+{
+ smartear_sound_play(buddy, purple_buddy_get_account(buddy), SMARTEAR_EVENT_IDLECHG);
+}
+
+static void
+smartear_cb_signoff(PurpleBuddy *buddy)
+{
+ smartear_sound_play(buddy, purple_buddy_get_account(buddy), SMARTEAR_EVENT_SIGNOFF);
+}
+
+static void
+smartear_cb_signon(PurpleBuddy *buddy)
+{
+ smartear_sound_play(buddy, purple_buddy_get_account(buddy), SMARTEAR_EVENT_SIGNON);
+}
+
+/* Purple Plugin stuff */
+
+static gboolean
+smartear_load(PurplePlugin *plugin)
+{
+ void *blist_handle = purple_blist_get_handle();
+ void *conv_handle = purple_conversations_get_handle();
+
+ /* blist signals we need to detect the buddy's activities */
+ purple_signal_connect(blist_handle, "buddy-signed-on", plugin,
+ PURPLE_CALLBACK(smartear_cb_signon), NULL);
+ purple_signal_connect(blist_handle, "buddy-signed-off", plugin,
+ PURPLE_CALLBACK(smartear_cb_signoff), NULL);
+ purple_signal_connect(blist_handle, "buddy-idle-changed", plugin,
+ PURPLE_CALLBACK(smartear_cb_idle), NULL);
+
+ /* conv signals we need to detect activities */
+ purple_signal_connect(conv_handle, "received-im-msg", plugin,
+ PURPLE_CALLBACK(smartear_cb_received_msg), NULL);
+ purple_signal_connect(conv_handle, "sent-im-msg", plugin,
+ PURPLE_CALLBACK(smartear_cb_sent_msg), NULL);
+
+ return TRUE;
+}
+
+static gboolean
+smartear_unload(PurplePlugin *plugin)
+{
+ return TRUE;
+}
+
+PurplePluginInfo smartear_info =
+{
+ PURPLE_PLUGIN_MAGIC, /* Magic, my ass */
+ PURPLE_MAJOR_VERSION, /* libpurple major version */
+ PURPLE_MINOR_VERSION, /* libpurple minor version */
+ PURPLE_PLUGIN_STANDARD, /* plugin type - this is a normal plugin */
+ NULL, /* UI requirement - we're invisible! */
+ PURPLE_PLUGIN_FLAG_INVISIBLE, /* flags - we have none */
+ NULL, /* dependencies - we have none */
+ PURPLE_PRIORITY_DEFAULT, /* priority - nothing special here */
+ "core-plugin_pack-smartear", /* Plugin ID */
+ NULL, /* name - defined later for i18n */
+ PP_VERSION, /* plugin version - use plugin pack version */
+ NULL, /* summary - defined later for i18n */
+ NULL, /* description - defined later for i18n */
+ "John Bailey <rekkanoryo@rekkanoryo.org>", /* author */
+ PP_WEBSITE, /* plugin website - use plugin pack website */
+ smartear_load, /* plugin load - purple calls this when loading */
+ smartear_unload, /* plugin unload - purple calls this when unloading */
+ NULL, /* plugin destroy - we don't need one */
+ NULL, /* ui_info - we don't need this */
+ NULL, /* extra_info - we don't need this */
+ NULL, /* prefs_info - we don't need this yet */
+ NULL, /* actions - we don't have any */
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ NULL, /* reserved 3 */
+ NULL /* reserved 4 */
+};
+
+static void
+smartear_init(PurplePlugin *plugin)
+{
+#ifdef ENABLE_NLS
+ bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR);
+ bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
+#endif
+
+ smartear_info.name = _("Smart Ear - Hidden Core Plugin");
+ smartear_info.summary = _("The Core component of the Smart Ear plugins");
+ smartear_info.description = _("The Core component of the Smart Ear plugins");
+}
+
+PURPLE_INIT_PLUGIN(smartear, smartear_init, smartear_info)
--- a/switchspell/Makefile.am Sun Aug 19 04:05:05 2007 -0400
+++ b/switchspell/Makefile.am Sun Aug 19 04:42:58 2007 -0400
@@ -3,8 +3,7 @@
if HAVE_GTKSPELL
switchspelldir = $(PIDGIN_LIBDIR)
-switchspell_la_LDFLAGS = -module -avoid-version \
- $(GTKSPELL_LIBS)
+switchspell_la_LDFLAGS = -module -avoid-version
if HAVE_PIDGIN
@@ -15,7 +14,8 @@
switchspell_la_LIBADD = \
$(PIDGIN_LIBS) \
- $(GTK_LIBS)
+ $(GTK_LIBS) \
+ $(GTKSPELL_LIBS)
endif # PIDGIN