pidgin: 884124c0: Add support to the Perl plugin loader fo...

datallah at pidgin.im datallah at pidgin.im
Wed Jul 30 00:01:11 EDT 2008


-----------------------------------------------------------------
Revision: 884124c06e81cdb91185699183edd48a03e0e6ac
Ancestor: 9e3f088fc7df07bdb891f336b152797fd4f1ff07
Author: datallah at pidgin.im
Date: 2008-07-30T03:51:26
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/884124c06e81cdb91185699183edd48a03e0e6ac

Modified files:
        libpurple/plugins/perl/common/Prefs.xs
        libpurple/plugins/perl/perl-handlers.c
        libpurple/plugins/perl/perl-handlers.h
        libpurple/plugins/perl/perl.c
        libpurple/plugins/perl/scripts/plugin_pref.pl

ChangeLog: 

Add support to the Perl plugin loader for listing for pref changes.
The Prefs Functions Test plugin (plugin_pref.pl) includes an example.
Fixes #6383

-------------- next part --------------
============================================================
--- libpurple/plugins/perl/common/Prefs.xs	360a65dfda64f723b76e7372a70c1b9f218acd7c
+++ libpurple/plugins/perl/common/Prefs.xs	edfcbd4bd9a29574af611d085c0d3c6f1cd751d2
@@ -1,4 +1,5 @@
 #include "module.h"
+#include "../perl-handlers.h"
 
 MODULE = Purple::Prefs  PACKAGE = Purple::Prefs  PREFIX = purple_prefs_
 PROTOTYPES: ENABLE
@@ -62,13 +63,28 @@ purple_prefs_destroy()
 void
 purple_prefs_destroy()
 
+guint
+purple_prefs_connect_callback(plugin, name, callback, data = 0);
+	Purple::Plugin plugin
+	const char *name
+	SV *callback
+	SV *data
+CODE:
+	RETVAL = purple_perl_prefs_connect_callback(plugin, name, callback, data);
+OUTPUT:
+	RETVAL
+
 void
-purple_prefs_disconnect_by_handle(handle)
-	void * handle
+purple_prefs_disconnect_by_handle(plugin)
+	Purple::Plugin plugin
+CODE:
+	purple_perl_pref_cb_clear_for_plugin(plugin);
 
 void
 purple_prefs_disconnect_callback(callback_id)
 	guint callback_id
+CODE:
+	purple_perl_prefs_disconnect_callback(callback_id);
 
 gboolean
 purple_prefs_exists(name)
============================================================
--- libpurple/plugins/perl/perl-handlers.c	fb326839b77e845bf979ee134461364d20505721
+++ libpurple/plugins/perl/perl-handlers.c	f4cc5f1a2bbbf1731b8b34d2eb8421d190125d10
@@ -8,6 +8,7 @@ static GList *timeout_handlers = NULL;
 static GList *cmd_handlers = NULL;
 static GList *signal_handlers = NULL;
 static GList *timeout_handlers = NULL;
+static GSList *pref_handlers = NULL;
 
 /* perl < 5.8.0 doesn't define PERL_MAGIC_ext */
 #ifndef PERL_MAGIC_ext
@@ -715,3 +716,141 @@ purple_perl_cmd_unregister(PurpleCmdId i
 	purple_cmd_unregister(id);
 	destroy_cmd_handler(handler);
 }
+
+static void
+perl_pref_cb(const char *name, PurplePrefType type, gconstpointer value,
+			 gpointer data)
+{
+	PurplePerlPrefsHandler *handler = data;
+	STRLEN na;
+
+	dSP;
+	ENTER;
+	SAVETMPS;
+	PUSHMARK(sp);
+	XPUSHs(sv_2mortal(newSVpv(name, 0)));
+
+	XPUSHs(sv_2mortal(newSViv(type)));
+
+	switch(type) {
+		case PURPLE_PREF_INT:
+			XPUSHs(sv_2mortal(newSViv(GPOINTER_TO_INT(value))));
+			break;
+		case PURPLE_PREF_BOOLEAN:
+			XPUSHs((GPOINTER_TO_INT(value) == FALSE) ? &PL_sv_no : &PL_sv_yes);
+			break;
+		case PURPLE_PREF_STRING:
+		case PURPLE_PREF_PATH:
+			XPUSHs(sv_2mortal(newSVGChar(value)));
+			break;
+		case PURPLE_PREF_STRING_LIST:
+		case PURPLE_PREF_PATH_LIST:
+			{
+				AV* av = newAV();
+				const GList *l = value;
+
+				/* Append stuff backward to preserve order */
+				while (l && l->next) l = l->next;
+				while (l) {
+					av_push(av, sv_2mortal(newSVGChar(l->data)));
+					l = l->prev;
+				}
+				XPUSHs(sv_2mortal(newRV_noinc((SV *) av)));
+			} break;
+		default:
+		case PURPLE_PREF_NONE:
+			XPUSHs(&PL_sv_undef);
+			break;
+	}
+
+	XPUSHs((SV *)handler->data);
+	PUTBACK;
+	call_sv(handler->callback, G_EVAL | G_VOID | G_DISCARD);
+	SPAGAIN;
+
+	if (SvTRUE(ERRSV)) {
+		purple_debug_error("perl",
+		                 "Perl prefs callback function exited abnormally: %s\n",
+		                 SvPV(ERRSV, na));
+	}
+
+	PUTBACK;
+	FREETMPS;
+	LEAVE;
+}
+
+guint
+purple_perl_prefs_connect_callback(PurplePlugin *plugin, const char *name,
+								   SV *callback, SV *data)
+{
+	PurplePerlPrefsHandler *handler;
+
+	if (plugin == NULL) {
+		croak("Invalid handle in adding perl prefs handler.\n");
+		return 0;
+	}
+
+	handler = g_new0(PurplePerlPrefsHandler, 1);
+
+	handler->plugin   = plugin;
+	handler->callback = (callback != NULL && callback != &PL_sv_undef
+	                     ? newSVsv(callback) : NULL);
+	handler->data     = (data != NULL && data != &PL_sv_undef
+	                     ? newSVsv(data) : NULL);
+
+	pref_handlers = g_slist_prepend(pref_handlers, handler);
+
+	handler->iotag = purple_prefs_connect_callback(plugin, name, perl_pref_cb, handler);
+
+	return handler->iotag;
+}
+
+static void
+destroy_prefs_handler(PurplePerlPrefsHandler *handler)
+{
+	pref_handlers = g_slist_remove(pref_handlers, handler);
+
+	if (handler->iotag > 0)
+		purple_prefs_disconnect_callback(handler->iotag);
+
+	if (handler->callback != NULL)
+		SvREFCNT_dec(handler->callback);
+
+	if (handler->data != NULL)
+		SvREFCNT_dec(handler->data);
+
+	g_free(handler);
+}
+
+void purple_perl_prefs_disconnect_callback(guint callback_id)
+{
+	GSList *l, *l_next;
+	PurplePerlPrefsHandler *handler;
+
+	for (l = pref_handlers; l != NULL; l = l_next) {
+		l_next = l->next;
+		handler = l->data;
+
+		if (handler->iotag == callback_id) {
+			destroy_prefs_handler(handler);
+			return;
+		}
+	}
+
+	purple_debug_info("perl", "No prefs handler found with handle %u.\n",
+	                  callback_id);
+}
+
+void purple_perl_pref_cb_clear_for_plugin(PurplePlugin *plugin)
+{
+	GSList *l, *l_next;
+	PurplePerlPrefsHandler *handler;
+
+	for (l = pref_handlers; l != NULL; l = l_next) {
+		l_next = l->next;
+		handler = l->data;
+
+		if (handler->plugin == plugin)
+			destroy_prefs_handler(handler);
+	}
+}
============================================================
--- libpurple/plugins/perl/perl-handlers.h	6b5188feb79bf5e40aad40526aa386985674ae9d
+++ libpurple/plugins/perl/perl-handlers.h	a4a40f9641594ba13824f16a8d23b29ae6d424a1
@@ -15,8 +15,8 @@ typedef struct
 	PurpleCmdId id;
 	SV *callback;
 	SV *data;
-	char *prpl_id;
-	char *cmd;
+	gchar *prpl_id;
+	gchar *cmd;
 	PurplePlugin *plugin;
 } PurplePerlCmdHandler;
 
@@ -31,7 +31,7 @@ typedef struct
 
 typedef struct
 {
-	char *signal;
+	gchar *signal;
 	SV *callback;
 	SV *data;
 	void *instance;
@@ -39,8 +39,17 @@ typedef struct
 
 } PurplePerlSignalHandler;
 
+typedef struct
+{
+	SV *callback;
+	SV *data;
+	PurplePlugin *plugin;
+	int iotag;
+
+} PurplePerlPrefsHandler;
+
 void purple_perl_plugin_action_cb(PurplePluginAction * gpa);
-GList *purple_perl_plugin_actions(PurplePlugin *plugin, gpointer context); 
+GList *purple_perl_plugin_actions(PurplePlugin *plugin, gpointer context);
 
 PurplePluginPrefFrame *purple_perl_get_plugin_frame(PurplePlugin *plugin);
 
@@ -69,4 +78,8 @@ void purple_perl_cmd_clear_for_plugin(Pu
 void purple_perl_cmd_unregister(PurpleCmdId id);
 void purple_perl_cmd_clear_for_plugin(PurplePlugin *plugin);
 
+guint purple_perl_prefs_connect_callback(PurplePlugin *plugin, const char *name, SV *callback, SV *data);
+void purple_perl_prefs_disconnect_callback(guint callback_id);
+void purple_perl_pref_cb_clear_for_plugin(PurplePlugin *plugin);
+
 #endif /* _PURPLE_PERL_HANDLERS_H_ */
============================================================
--- libpurple/plugins/perl/perl.c	ff81c8afd465331cc0a6e09359f5c34d4967d566
+++ libpurple/plugins/perl/perl.c	0bf5d2c08b10aaf860740cf62ec47bd890d0afd1
@@ -557,6 +557,7 @@ unload_perl_plugin(PurplePlugin *plugin)
 	purple_perl_cmd_clear_for_plugin(plugin);
 	purple_perl_signal_clear_for_plugin(plugin);
 	purple_perl_timeout_clear_for_plugin(plugin);
+	purple_perl_pref_cb_clear_for_plugin(plugin);
 
 	destroy_package(gps->package);
 
============================================================
--- libpurple/plugins/perl/scripts/plugin_pref.pl	104c0861c8286cbaab9c9b33aeaef439f5c7aced
+++ libpurple/plugins/perl/scripts/plugin_pref.pl	31fb2680668448d320c76212b8879c76150d3e89
@@ -44,8 +44,8 @@ sub foo {
 	$ppref = Purple::PluginPref->new_with_name_and_label(
 	    "/plugins/core/perl_test/choice", "Choice Preference");
 	$ppref->set_type(1);
-	$ppref->add_choice("ch0", $frame);
-	$ppref->add_choice("ch1", $frame);
+	$ppref->add_choice("ch0", "ch0-val");
+	$ppref->add_choice("ch1", "ch1-val");
 	$frame->add($ppref);
 	
 	$ppref = Purple::PluginPref->new_with_name_and_label(
@@ -56,12 +56,17 @@ sub foo {
 	return $frame;
 }
 
+sub pref_cb {
+	my ($pref, $type, $value, $data) = @_;
+	
+	print "pref changed: [$pref]($type)=$value data=$data\n";
+}
+
 sub plugin_init { 
 	
 	return %PLUGIN_INFO; 
 } 
 
-
 # This is the sub defined in %PLUGIN_INFO to be called when the plugin is loaded
 #	Note: The plugin has a reference to itself on top of the argument stack.
 sub plugin_load { 
@@ -75,8 +80,12 @@ sub plugin_load { 
 	Purple::Prefs::add_bool("/plugins/core/perl_test/bool", 1);	
 	Purple::Prefs::add_string("/plugins/core/perl_test/choice", "ch1");	
 	Purple::Prefs::add_string("/plugins/core/perl_test/text", "Foobar");	
-	
 
+	Purple::Prefs::connect_callback($plugin, "/plugins/core/perl_test", \&pref_cb, "none");
+	Purple::Prefs::connect_callback($plugin, "/plugins/core/perl_test/bool", \&pref_cb, "bool");
+	Purple::Prefs::connect_callback($plugin, "/plugins/core/perl_test/choice", \&pref_cb, "choice");
+	Purple::Prefs::connect_callback($plugin, "/plugins/core/perl_test/text", \&pref_cb, "text");
+
 	print "\n\n" . "#" x 80 . "\n\n";
 } 
 


More information about the Commits mailing list