pidgin/purple-plugin-pack
propagate from branch 'org.guifications.plugins' (head 03abf61fc417f02c8a2888aa3783acb220fad2f8)
to branch 'org.guifications.plugins.smartear' (head 307f7650091160b2193a912c4cf8a24c5bebc414)
--- a/common/gtk_template.c Tue Oct 09 06:13:57 2007 -0400
+++ b/common/gtk_template.c Tue Oct 09 06:20:40 2007 -0400
@@ -67,6 +67,7 @@
--- a/configure.ac Tue Oct 09 06:13:57 2007 -0400
+++ b/configure.ac Tue Oct 09 06:20:40 2007 -0400
@@ -337,6 +337,7 @@
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smartear/Makefile.am Tue Oct 09 06:20:40 2007 -0400
@@ -0,0 +1,36 @@
+smarteardir = $(PIDGIN_LIBDIR) +smartear_la_LDFLAGS = -module -avoid-version +smartear_LTLIBRARIES = smartear.la +smartear_la_SOURCES = smartear.c +smartear_la_LIBADD = $(PURPLE_LIBS) +gtksmartear_LTLIBRARIES = gtksmartear.la +gtksmartear_la_SOURCES = gtksmartear.c +gtksmartear_la_LIBADD = $(PIDGIN_LIBS) +gntsmartear_LTLIBRARIES = gntsmartear.la +gntsmartear_la_SOURCES = gntsmartear.c +gntsmartear_la_LIBADD = $(FINCH_LIBS) + -DLIBDIR=\"$(PURPLE_LIBDIR)\" \ + -DDATADIR=\"$(PURPLE_DATADIR)\" \ + -DPIXMAPSDIR=\"$(PURPLE_PIXMAPSDIR)\" \ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smartear/gtksmartear.c Tue Oct 09 06:20:40 2007 -0400
@@ -0,0 +1,93 @@
+ * gktsmartear.c - GTK+ configuration UI plugin to accompany smartear. + * Copyright (C) 2007 John Bailey <rekkanoryo@rekkanoryo.org> + * 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 +# include "../pp_config.h" +/* Pack/Local headers */ +#include "../common/pp_internal.h" +#define PLUGIN_AUTHOR "John Bailey <rekkanoryo@rekkanoryo.org>" +plugin_load(PurplePlugin *plugin) { +plugin_unload(PurplePlugin *plugin) { +static PurplePluginInfo info = { + PURPLE_PLUGIN_MAGIC, /* Magic */ + PURPLE_MAJOR_VERSION, /* Purple Major Version */ + PURPLE_MINOR_VERSION, /* Purple Minor Version */ + PURPLE_PLUGIN_STANDARD, /* plugin type */ + PIDGIN_PLUGIN_TYPE, /* ui requirement */ + NULL, /* dependencies */ + PURPLE_PRIORITY_DEFAULT, /* priority */ + "gtk-plugin_pack-smartear", /* plugin id */ + PP_VERSION, /* version */ + NULL, /* description */ + PLUGIN_AUTHOR, /* author */ + PP_WEBSITE, /* website */ + plugin_load, /* load */ + plugin_unload, /* unload */ +init_plugin(PurplePlugin *plugin) { + bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + info.name = _(PLUGIN_NAME); + info.summary = _(PLUGIN_SUMMARY); + info.description = _(PLUGIN_DESCRIPTION); +PURPLE_INIT_PLUGIN(PLUGIN_STATIC_NAME, init_plugin, info) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smartear/interface.c Tue Oct 09 06:20:40 2007 -0400
@@ -0,0 +1,566 @@
+ * DO NOT EDIT THIS FILE - it is generated by Glade. +#include <gdk/gdkkeysyms.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 *config_vbox; + GtkObject *delay_spin_adj; + GtkWidget *scrolledwindow2; + GtkWidget *hbuttonbox1; + 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), + g_signal_connect ((gpointer) delay_spin, "changed", + G_CALLBACK (on_delay_changed), + g_signal_connect ((gpointer) focus_but, "toggled", + G_CALLBACK (on_focus_toggled), + g_signal_connect ((gpointer) timer_but, "toggled", + G_CALLBACK (on_timer_toggled), + g_signal_connect ((gpointer) delete_but, "clicked", + G_CALLBACK (on_delete_clicked), + g_signal_connect ((gpointer) new_but, "clicked", + G_CALLBACK (on_new_clicked), + g_signal_connect ((gpointer) edit_but, "clicked", + G_CALLBACK (on_edit_clicked), + g_signal_connect ((gpointer) revert_but, "clicked", + G_CALLBACK (on_revert_clicked), + g_signal_connect ((gpointer) save_but, "clicked", + G_CALLBACK (on_save_clicked), + /* 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"); +create_file_browse (void) + GtkWidget *file_browse; + 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), + g_signal_connect ((gpointer) ok_button1, "clicked", + G_CALLBACK (on_browse_ok_clicked), + 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"); + GtkWidget *type_option; + GtkWidget *hbuttonbox2; + GtkWidget *applysave_but; + 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; + 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), + g_signal_connect ((gpointer) applysave_but, "clicked", + G_CALLBACK (on_apply_clicked), + g_signal_connect ((gpointer) applysave_but, "clicked", + G_CALLBACK (on_save_clicked), + 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), + 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), + g_signal_connect ((gpointer) unidle_test_but, "clicked", + G_CALLBACK (on_unidle_test_clicked), + g_signal_connect ((gpointer) signon_test_but, "clicked", + G_CALLBACK (on_signon_test_clicked), + g_signal_connect ((gpointer) unaway_browse_but, "clicked", + G_CALLBACK (on_unaway_browse_clicked), + g_signal_connect ((gpointer) unidle_browse_but, "clicked", + G_CALLBACK (on_unidle_browse_clicked), + g_signal_connect ((gpointer) signon_browse_but, "clicked", + G_CALLBACK (on_signon_browse_clicked), + g_signal_connect ((gpointer) im_browse_but, "clicked", + G_CALLBACK (on_im_browse_clicked), + g_signal_connect ((gpointer) im_test_but, "clicked", + G_CALLBACK (on_im_test_clicked), + /* 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"); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smartear/make-interface.sh Tue Oct 09 06:20:40 2007 -0400
@@ -0,0 +1,25 @@
+# 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. +OUT=smartear-interface.c +# 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" + /gtk_widget_show.*config_vbox/d --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smartear/old-smartear-interface.c Tue Oct 09 06:20:40 2007 -0400
@@ -0,0 +1,546 @@
+# include "../pp_config.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 *config_vbox; + GtkObject *delay_spin_adj; + GtkWidget *scrolledwindow2; + GtkWidget *hbuttonbox1; + 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), + g_signal_connect ((gpointer) delay_spin, "changed", + G_CALLBACK (on_delay_changed), + g_signal_connect ((gpointer) focus_but, "toggled", + G_CALLBACK (on_focus_toggled), + g_signal_connect ((gpointer) timer_but, "toggled", + G_CALLBACK (on_timer_toggled), + g_signal_connect ((gpointer) delete_but, "clicked", + G_CALLBACK (on_delete_clicked), + g_signal_connect ((gpointer) new_but, "clicked", + G_CALLBACK (on_new_clicked), + g_signal_connect ((gpointer) edit_but, "clicked", + G_CALLBACK (on_edit_clicked), + g_signal_connect ((gpointer) revert_but, "clicked", + G_CALLBACK (on_revert_clicked), + g_signal_connect ((gpointer) save_but, "clicked", + G_CALLBACK (on_save_clicked), + /* 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"); +create_file_browse (void) + GtkWidget *file_browse; + 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), + g_signal_connect ((gpointer) ok_button1, "clicked", + G_CALLBACK (on_browse_ok_clicked), + 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"); + GtkWidget *type_option; + GtkWidget *hbuttonbox2; + GtkWidget *applysave_but; + 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; + 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), + g_signal_connect ((gpointer) applysave_but, "clicked", + G_CALLBACK (on_apply_clicked), + g_signal_connect ((gpointer) applysave_but, "clicked", + G_CALLBACK (on_save_clicked), + 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), + 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), + g_signal_connect ((gpointer) unidle_test_but, "clicked", + G_CALLBACK (on_unidle_test_clicked), + g_signal_connect ((gpointer) signon_test_but, "clicked", + G_CALLBACK (on_signon_test_clicked), + g_signal_connect ((gpointer) unaway_browse_but, "clicked", + G_CALLBACK (on_unaway_browse_clicked), + g_signal_connect ((gpointer) unidle_browse_but, "clicked", + G_CALLBACK (on_unidle_browse_clicked), + g_signal_connect ((gpointer) signon_browse_but, "clicked", + G_CALLBACK (on_signon_browse_clicked), + g_signal_connect ((gpointer) im_browse_but, "clicked", + G_CALLBACK (on_im_browse_clicked), + g_signal_connect ((gpointer) im_test_but, "clicked", + G_CALLBACK (on_im_test_clicked), + /* 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"); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smartear/old-smartear.c Tue Oct 09 06:20:40 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 +# include "../pp_config.h" +#include "../common/i18n.h" +#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. */ + char *sound[EVENT_NUM]; + PurpleAccount *account; + struct timer_data *timer; +enum { /* Treeview columns */ +#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 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), + g_warning ("smartear: Widget not found: %s", widget_name); +void on_delay_changed (GtkEditable *editable, gpointer user_data) + gchar *text = gtk_editable_get_chars(editable, 0, -1); + message_delay = atoi(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); +void on_cell_edited(GtkCellRendererText *cell, gchar *path, gchar *text, gpointer data) + gint col = GPOINTER_TO_INT(data); + struct smartear_entry *entry; + if (!gtk_tree_model_get_iter_from_string(treemodel, &iter, path)) + gtk_tree_model_get(treemodel, &iter, DATA_COL, &entry, -1); + entry->name = g_strdup(text); +void on_treeselect_changed(GtkTreeSelection *selection, gpointer data) +void on_new_clicked (GtkButton *button, gpointer user_data) + new_entry(sound_new_with_name("")); +void on_delete_clicked (GtkButton *button, gpointer user_data) + if (IS_DEFAULT(selected_entry)) + 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); +void on_edit_clicked (GtkButton *button, gpointer user_data) + 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) +void on_revert_clicked (GtkButton *button, gpointer user_data) + gtk_widget_destroy(edit_win); + gtk_list_store_clear(GTK_LIST_STORE(treemodel)); + populate_list(GTK_LIST_STORE(treemodel)); +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_entry = NULL; +void on_browse_clicked (GtkButton *button, gchar *user_data) + 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); +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) + gtk_editable_get_chars(GTK_EDITABLE(EFIND(user_data)), 0, -1); + play_sound_alias(text, NULL); +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; + entry = selected_entry; + g_free(entry->sound[0]); + g_free(entry->sound[1]); + g_free(entry->sound[2]); + g_free(entry->sound[3]); + gtk_editable_get_chars(GTK_EDITABLE(EFIND("name_entry")), 0, -1); + gtk_option_menu_get_history(GTK_OPTION_MENU(EFIND("type_option"))) == 0 + 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 ((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; + struct smartear_entry *copy = g_new(struct smartear_entry, 1); +void on_edit_win_destroy (GtkObject *object, gpointer user_data) + gtk_widget_set_sensitive(GTK_WIDGET(treeview), TRUE); +void on_config_destroy (GtkObject *object, gpointer user_data) +/*** Util Functions ***/ +static void new_entry(struct smartear_entry *entry) + GtkTreeViewColumn *name_column; + sounds_list = g_slist_append(sounds_list, entry); + gtk_list_store_insert_after(GTK_LIST_STORE(treemodel), &iter, &selected_iter); + 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); + 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); +static gboolean get_selection(void) + if (!gtk_tree_selection_get_selected(treeselect, &treemodel, &selected_iter)) + gtk_tree_model_get(treemodel, &selected_iter, DATA_COL, &selected_entry, -1); +void clear_selection(void) + 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]; + g_return_val_if_fail((input != NULL), NULL); + beg = str = g_strdup(input); + while (*str && i <= BUF_LEN) { +static struct smartear_entry *sound_new_with_name(gchar *name) + struct smartear_entry tmp = default_entry; + return sound_dup(&tmp); +static struct smartear_entry *sound_dup(struct smartear_entry *entry) + struct smartear_entry *edup = g_new(struct smartear_entry, 1); + 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]); +static void sound_free(struct smartear_entry *entry, int free_entry) + g_free(entry->sound[0]); + g_free(entry->sound[1]); + g_free(entry->sound[2]); + g_free(entry->sound[3]); +static void soundlist_free(void) + for (lp = sounds_list; lp; lp = g_slist_next(lp)) + sound_free((struct smartear_entry*)lp->data, TRUE); + g_slist_free(sounds_list); +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)) + if (!entry2 || IS_DEFAULT(entry2)) + /* 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); + 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) + list_set(GTK_LIST_STORE(treemodel), &selected_iter, selected_entry); +static gchar* get_basename(gchar *path) + static gchar base[BUF_LEN]; + if (!path || !path[0]) { + if ((p = strrchr(path, '/'))) { + strncpy(base, p, sizeof(base)); +/*** Init Functions ***/ +static void populate_list(GtkListStore *store) + 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) +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); + g_object_set(cell, "text", "", NULL); + 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) + treeview = GTK_TREE_VIEW(FIND("treeview")); + store = gtk_list_store_new(1, G_TYPE_POINTER); + 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); + cell = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_data_func(treeview, -1, "Type", + cell, render_type, 0, 0); + 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"; + struct smartear_entry *entry; + if (purple_user_dir()) { + g_snprintf(file, sizeof(file), "%s/smartear.rc", purple_user_dir()); + g_warning("couldn't open %s\n", file); + 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])); +static void smartear_load(void) + char file[BUF_LEN] = "smartear.rc - you have no home dir"; + struct smartear_entry *entry; + gboolean has_default = FALSE; + int rcfile_version = 1; + if (purple_user_dir()) { + g_snprintf(file, sizeof(file), "%s/smartear.rc", purple_user_dir()); + g_warning("smartear: couldn't open %s\n", file); + sounds_list = g_slist_append(sounds_list, sound_dup(&default_entry)); + while ((fgets(buf, sizeof(buf), fp))) { + if (sscanf(buf, "version %d", &tmp) == 1) + else if (sscanf(buf, "smarterear_timers %d", &tmp) == 1) + else if (sscanf(buf, "smartear_timers %d", &tmp) == 1) + else if (sscanf(buf, "delay %d", &tmp) == 1) + else if (sscanf(buf, "focused_quiet %d", &tmp) == 1) + else if (rcfile_version == 1) { + if (sscanf(buf, "%c {%[^}]} {%[^}]} {%[^}]}", + &type, name, flags, sound) == 4) { + if (type != 'G' && type != 'B') { + g_warning("smartear: rc no such type: %c", type); + entry = g_new(struct smartear_entry, 1); + 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; + g_warning("smartear: rc1 syntax error: %s", buf); + else if (rcfile_version == 2) { + char sound[EVENT_NUM][BUF_LEN]; + 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); + for (i = 0; i < EVENT_NUM; i++) { + if (strcmp(sound[i], RC_EMPTY_SOUND) == 0) + entry = g_new(struct smartear_entry, 1); + 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; + g_warning("smartear: rc2 syntax error: %s", buf); + g_warning("smartear: rc syntax error: %s", buf); + sounds_list = g_slist_append(sounds_list, sound_dup(&default_entry)); +/*** Purple callbacks ***/ +static struct message_data *find_message_by_name(PurpleAccount *account, const char *pname) + 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) +static void message_timer_remove(struct message_data *msg) + if (msg && msg->timer) { + g_source_remove(msg->timer->id); +static void message_free(struct message_data *msg) + message_timer_remove(msg); +static void messagelist_free() + for (lp = messages_list; lp; lp = g_slist_next(lp)) + message_free((struct message_data*)lp->data); + g_slist_free(messages_list); +static void on_smartear_clicked(PurpleBlistNode* node, gpointer data) + struct smartear_entry tmp, *entry; + edit_win = create_edit_win(); + gtk_widget_show_all(edit_win); + else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { + 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.name = ((PurpleContact*)node)->alias; + 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.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); + if ((lp = g_slist_find_custom(sounds_list, &tmp, (GCompareFunc)sound_cmp))) { + entry = (struct smartear_entry*)lp->data; + populate_edit_win(entry); +static void play_sound_alias(char *sound, PurpleAccount* account) + struct smartear_entry tmp, *entry; + /* sound aliases: mostly so you can put (Default) for sound, and it'll + 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); + purple_sound_play_file(sound, account); +void play_matching_sound(PurpleBuddy *buddy, int event) + struct smartear_entry *entry; + 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]) + if (entry->type == 'B' && name + && g_strcasecmp(name, entry->name) == 0) { + sound = entry->sound[event]; + /* found a buddy match.. this takes precedence, so stop */ + 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)) { + 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)); + purple_debug(PURPLE_DEBUG_INFO, "smartear", + "no sound found for %s on event %d\n", name, event); +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"); + play_matching_sound(purple_find_buddy(msg->account, msg->buddy), msg->timer->event); +static gboolean on_im_recv(PurpleAccount *account, char *who, char *what, gint32 flags, void *junk) + struct message_data *msg; + 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); + msg = g_new0(struct message_data, 1); + msg->account = account; + msg->buddy = g_strdup(my_normalize(who)); + 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) + play_matching_sound(purple_find_buddy(msg->account, msg->buddy), EVENT_M); +static void on_im_send(PurpleAccount *account, char *who, char *what, void *junk) + struct message_data *msg; + if ((msg = find_message_by_name(account, who))) { + message_timer_remove(msg); + msg = g_new0(struct message_data, 1); + msg->account = account; + msg->buddy = g_strdup(my_normalize(who)); + messages_list = g_slist_append(messages_list, msg); + msg->last_active = 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) +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(); + 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); +static gboolean purple_plugin_remove(PurplePlugin *h) +static GtkWidget *purple_plugin_config_gtk(PurplePlugin *plugin) + config = create_config(); + gtk_widget_show_all(config); +static PurplePluginUiInfo ui_info = { + purple_plugin_config_gtk, + 0 /* page_num (reserved) */ +static PurplePluginInfo info = + PURPLE_PLUGIN_STANDARD, + PURPLE_PRIORITY_DEFAULT, + "Matt Perry <guy@fscked.org>", +static void init_plugin(PurplePlugin *plugin) + bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + info.name= _("Smart Ear"); + info.summary = _("Assign different sounds to different buddies and groups"); + _("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 Tue Oct 09 06:20:40 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"> +<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> + <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"/> + <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> + <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> + <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> + <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> + <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"/> + <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> + <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"/> + <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> + <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"/> + <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> + <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> + <property name="type">label_item</property> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <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> + <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> + <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"/> + <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> + <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"/> + <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> + <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> + <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> + <property name="left_attach">0</property> + <property name="right_attach">3</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <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"/> + <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> + <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> + <property name="type">label_item</property> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + <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> + <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 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"/> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> +<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"/> + <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 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"/> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + <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> + <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> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + <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> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + <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> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <widget class="GtkOptionMenu" id="type_option"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="history">0</property> + <widget class="GtkMenu" id="menu1"> + <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 class="GtkMenuItem" id="item_group"> + <property name="visible">True</property> + <property name="label" translatable="yes">Group</property> + <property name="use_underline">True</property> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">10</property> + <property name="expand">False</property> + <property name="fill">True</property> + <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> + <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 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 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"/> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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"/> + <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> + <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"/> + <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> + <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"/> + <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> + <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"/> + <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> + <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"/> + <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> + <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"/> + <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> + <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"/> + <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> + <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> + <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> + <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"/> + <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> + <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> + <property name="type">label_item</property> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smartear/smartear.c Tue Oct 09 06:20:40 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 + * 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. +# include "../pp_config.h" +#endif /* HAVE_CONFIG_H */ +#include "../common/pp_internal.h" + SMARTEAR_EVENT_SIGNOFF, + SMARTEAR_EVENT_IDLECHG, + SMARTEAR_EVENT_RECEIVEDMSG, +smartear_event_get_setting_string(SmartEarEvent event) + const char *setting = NULL; + case SMARTEAR_EVENT_SIGNON: + setting = "signon_sound"; + case SMARTEAR_EVENT_SIGNOFF: + setting = "signoff_sound"; + case SMARTEAR_EVENT_IDLECHG: + setting = "idlechg_sound"; + case SMARTEAR_EVENT_RECEIVEDMSG: + setting = "receivedmsg_sound"; + case SMARTEAR_EVENT_SENTMSG: + setting = "sentmsg_sound"; +smartear_sound_get_default(SmartEarEvent event) + const char *prefname = NULL, *prefval = NULL; + prefname = smartear_event_get_setting_string(event); + prefpath = g_strdup_printf("/plugins/core/smartear/%s", prefname); + prefval = purple_prefs_get_string(prefpath); +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)")) + if(!g_ascii_strcasecmp(cfile, "(Default)")) + if(!g_ascii_strcasecmp(gfile, "(Default)")) + /* 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 + pfile = smartear_sound_get_default(event); +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); + purple_sound_play_file(pfile, account); +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); +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); +smartear_cb_idle(PurpleBuddy *buddy, gboolean wasidle, gboolean nowidle) + smartear_sound_play(buddy, purple_buddy_get_account(buddy), SMARTEAR_EVENT_IDLECHG); +smartear_cb_signoff(PurpleBuddy *buddy) + smartear_sound_play(buddy, purple_buddy_get_account(buddy), SMARTEAR_EVENT_SIGNOFF); +smartear_cb_signon(PurpleBuddy *buddy) + smartear_sound_play(buddy, purple_buddy_get_account(buddy), SMARTEAR_EVENT_SIGNON); +/* Purple Plugin stuff */ +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); +smartear_unload(PurplePlugin *plugin) +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 */ +smartear_init(PurplePlugin *plugin) + bindtextdomain(GETTEXT_PACKAGE, PP_LOCALEDIR); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + 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 Tue Oct 09 06:13:57 2007 -0400
+++ b/switchspell/Makefile.am Tue Oct 09 06:20:40 2007 -0400
@@ -3,8 +3,7 @@
switchspelldir = $(PIDGIN_LIBDIR)
-switchspell_la_LDFLAGS = -module -avoid-version \
+switchspell_la_LDFLAGS = -module -avoid-version @@ -15,7 +14,8 @@
switchspell_la_LIBADD = \