Introducción
Pidgin es uno de los mejores clientes de mensajería en Windows (al menos hasta que Kopete para Win32 despegue :-P) pero, en cierto modo, es un subproducto de la versión "canónica" de linux; así modificar y reconstruir Pidgin en Windows es doloroso y parte de la funcionalidad (D-Bus, composición de tipos de letras) se ha caído.
Pidgin, a través de libpurple, soporta scripting. Uno de los tipos de plugin es "lopl" que define a los "meta-plugins" que se ocupan de cargar los scripts. En la rama oficial se incluyen cargadores para Perl, Tcl y toda la familia Mono. El tema del scripting está siendo revisado y una de las tareas con recompensa es reescribir las cabeceras o el api mismo para que se pueda generar de forma automática los bindings, por ejemplo usando SWIG.
Mientras el tema se aclara otra posibilidad que se nos ofrece es comandar a pidgin través de D-Bus. Muchos plugins pueden ser reescritos como programas externos conectados a través de D-Bus. La indexación en Google Desktop podría ser uno de ellos pero, por desgracia, en Windows pidgin no soporta D-Bus. Entonces ¿Qué opciones nos quedan?
Las opciones
El antiguo GaimDS está escrito en Python. Esto se hizo así por una serie de factores: no quería escribir :-D, el tipo al que se lo hice sabía Python, quizás podría aprovechar un ejemplo de Google y referencias en la documentación oficial (aunque al final descubrí que todo estaba obsoleto y tuve que ir a la parte de C) y, por aquel entonces, no había mucha diferencia en el soporte de los plugins de Perl y los de Python dentro de Gaim.
Con el tiempo Python en Gaim/Pidgin desapareció. Eliminada una opción, queda reescribirlo en Perl o Tcl,o escribir un plugin nativo en C. Descarto Mono porque, si ya es "bleeding edge" Mono en Pidgin+Linux, intuyo que en Windows debe ser como montar un puzzle de diez mil piezas con los ojos vendados :-) Enganchar .NET con Pidgin suena bien pero casi no hay documentación sobre Mono y ninguna referencia específica de .NET. Por la teoría de "si nadie lo ha hecho antes será por algo" sospecho que no debe ser sencillo :-)
Reescribir el plugin en C es la opción más segura pero también la más dolorosa. Para compilar Pidgin en Windows hace falta cygwin, mingw32 y un montón de trastos. El indexador necesita usar COM+ y Glib con un montón de código gcc-específico, y por experiencia sé que con esas cosas mingw32 es bastante puñetero (= no hace lo mismo que MSVC, las cabeceras cambian, errores en el enlazado). Además es horrendo el código C cuando pretendes usar interfaces.
Así pues la opción más razonable es rescribir las 80 líneas guarras de GaimDS en Perl y a correr. Bueno, pues eso es lo que no he hecho :-)
La chapuza
PidginDS está escrito en Python. Mi intención --- que seguramente se quedará en eso, en intención :-D --- es reescribirlo eventualmente en C pero, mientras tanto, he escrito un plugin que hace las veces de PyGaim: por un lado habla con libpurple y por otro, usando Python empotrado, con PidginDS. En frío no tiene mucho sentido meterse en ese berenjenal pero el código C para empotrar python es pequeño, puedo reusar casi todo el script original y además es un enfoque bastante flexible si quiero cambiar algo después: al ser los plugins nativos bibliotecas dinámicas, pidgin enlaza con ellos y tienes que salir del programa antes de poder reemplazarlos. Como aquí la funcionalidad está en un script python, esté lo puedo cambiar en caliente, puedo añadir código y probar cosas sin estar cerrando cada dos por tres. Para lo que pretende ser --- un prototipo de una versión en C --- el enfoque no es tan descabellado y lo he podido escribir en la décima parte de lo que he tardado en escribir hasta aquí :-)
Una de las consecuencias de "ser un subproducto" es que no hay "paquetes dev" de Pidgin en Windows. Para compilar los plugins te tienes que preparar tú el entorno y las mayores pegas han sido precisamente de construcción:
El código añadido en C y, obviando el esqueleto común a todos los plugins de Pidgin, se reduce a esto:
typedef enum { SENT=0, RECV=1 } gds_msg_event_t;
static const char *EVT_NAMES[] = {"sent_cb", "recv_cb"};
static PyObject *MODULE;
static char *GDSNAME = "pidginds";
static void
python_fn(PurpleAccount *account, const char *sender,
const char *buffer, gds_msg_event_t type) {
PyObject *args, *fn, *user, *buddy, *msg, *val;
fn = PyObject_GetAttrString(MODULE, EVT_NAMES[type]);
if (fn && PyCallable_Check(fn)) {
args = PyTuple_New(3); /* username, buddy, msg */
user = PyString_FromString(purple_account_get_username(account));
buddy = PyString_FromString(sender);
msg = PyString_FromString(buffer);
if (!(user && buddy && msg)) {
Py_DECREF(args);
return;
}
PyTuple_SetItem(args, 0, user);
PyTuple_SetItem(args, 1, buddy);
PyTuple_SetItem(args, 2, msg);
val = PyObject_CallObject(fn, args);
if (val) Py_DECREF(val);
Py_DECREF(fn);
}
}
... Qué es una forma simple de hacer llamadas a funciones en módulos python desde C. Un detalle feo es la inicialización de MODULE (el "import pidginds"). PyImport_Import/Ex no admite un path así que hay que modificar el sys.path primero para que encuentre el módulo, que estará en el directorio de plugins de pidgin. Hay muchas formas de hacerlo. La buena supongo que es leer del registro dónde se instaló pidgin y sacarlo de ahí. Yo simplemente lo he dejado fijo a "C:\\Program Files\\Pidgin\\plugins" con vistas a que a la larga (je) lo reescribiré en C.
Para compilarlo la forma más sencilla es aprovecharse del Makefile.mingw que hay en el subdirectorio de plugins, en libpurple. De todas formas en el zip está el dll compilado para python25.
Confesión y cierre
Esto lo he desempolvado después de tanto tiempo porque ahora sí tengo un ordenador con Windows y con Google Desktop. Hace poco compré un Dell (uno con muchos cores y mucha ram para programar en Java X-D) y venía, aparte de con Windows Vista, con el servicio de búsqueda desactivado y con Google Desktop instalado por defecto. Quizás ahora que lo uso le de más aire, lo ponga de bonito y lo suba a alguna parte pero no creo que caiga esa breva: funcionar funciona y a mí me resuelve la papeleta así que supongo que mi renovado interés ha durado los cinco minutos que le he dedicado a hacerlo andar de nuevo más lo que he tardado en escribir esto :-)
Por dar un poco pie a debate (aunque esto también lo dudo X-D) ¿vosotros también tenéis trastos de estos? Me refiero a programas y scripts tontos que una vez escribiste para "rascarte tu picor" pero por pereza no los pules ni los publicas.
Una vez escuché que como programador vales tanto como los programas que hayas acabado, no los que hayas empezado. Supongo que programar es divertido pero acabar programas es aburrido :-) Esto en cierto modo es la lacra del software libre: no se acaban los programas. Todo el mundo está dispuesto a añadir funcionalidades pero, a menos que haya un cheque de por medio nadie está dispuesto a hacer algo tan aburrido como pulir los detalles.