Skip to content

Instantly share code, notes, and snippets.

@Munawwar Munawwar/popup_notify.c Secret
Created Oct 1, 2011

Embed
What would you like to do?
Pidgin popup_notify
/*
* Popup Mail Notification for Pidgin
*
* First taken from:
* Hello World Plugin
* Authors:
* Gary Kramlich, 2004 <grim@guifications.org>,
* John Bailey, 2007 <rekkanoryo@cpw.pidgin.im>
* GNU GPL2
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
/* config.h may define PURPLE_PLUGINS; protect the definition here so that we
* don't get complaints about redefinition when it's not necessary. */
#ifndef PURPLE_PLUGINS
# define PURPLE_PLUGINS
#endif
#include <glib.h>
/* This will prevent compiler errors in some instances and is better explained in the
* how-to documents on the wiki */
#ifndef G_GNUC_NULL_TERMINATED
# if __GNUC__ >= 4
# define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__))
# else
# define G_GNUC_NULL_TERMINATED
# endif
#endif
#include <string.h>
#include "debug.h"
#include "notify.h"
#include "gtkplugin.h"
#include "version.h"
#define PLUGIN_ID "gtk-mwr-popup_notify"
/* we're adding this here and assigning it in pn_plugin_load because we need
* a valid plugin handle for our call to purple_notify_message() in the
* plugin_action_test_cb() callback function */
//All global functions and variables will have pn_ (meaning "popup notify") prefix
PurplePlugin *pn_Plugin = NULL;
GtkWindow *pn_window=NULL;
GtkLabel *pn_label=NULL;
GtkButton *pn_rightArrowBtn=NULL;
struct pn_Mail {
char *subject;
char *from;
char *to;
char *url;
};
struct pn_MailList {
int index;
int count;
int recvCount;
GSList* list;
} pn_mailList; //Initialization done in pn_plugin_load
/*Prototypes*/
/*Event handlers*/
void rightArrowBtn_press_callback(GtkButton *button, gpointer user_data);
/*Constructors and destructors*/
static void pn_mailInfo_allocate(char **subjects, char **froms, char **tos, char **urls, guint count) {
if(pn_mailList.count>0 || subjects==NULL || froms==NULL || tos==NULL || urls==NULL) {
return;
}
pn_mailList.recvCount=count;
int i;
purple_debug_info(PLUGIN_ID, "Allocating space for %d mails...\n",count);
for(i=0; i<count; i++) {
if(!(subjects[i]==NULL || froms[i]==NULL || tos[i]==NULL || urls[i]==NULL)) {
struct pn_Mail *mail=(struct pn_Mail*)malloc(sizeof (struct pn_Mail));
purple_debug_info(PLUGIN_ID, "Allocating mail->subject for i=%d. ", i);
mail->subject=g_strdup(subjects[i]);
purple_debug_info(PLUGIN_ID, "Memory=%d\n", (int)mail->subject);
purple_debug_info(PLUGIN_ID, "Allocating mail->from for i=%d. ", i);
mail->from=g_strdup(froms[i]);
purple_debug_info(PLUGIN_ID, "Memory=%d\n", (int)mail->from);
purple_debug_info(PLUGIN_ID, "Allocating mail->to for i=%d. ", i);
mail->to=g_strdup(tos[i]);
purple_debug_info(PLUGIN_ID, "Memory=%d\n", (int)mail->to);
purple_debug_info(PLUGIN_ID, "Allocating mail->url for i=%d. ", i);
mail->url=g_strdup(urls[i]);
purple_debug_info(PLUGIN_ID, "Memory=%d\n", (int)mail->url);
pn_mailList.list = g_slist_append(pn_mailList.list, mail);
pn_mailList.count++;
}
if(subjects[i]==NULL && froms[i]==NULL && tos[i]==NULL && urls[i]==NULL) {
break;
}
}
purple_debug_info(PLUGIN_ID, "Allocation Done.\n");
}
static void pn_mailInfo_deallocate() {
if(pn_mailList.count>0) {
int i;
purple_debug_info(PLUGIN_ID, "Deallocating...\n");
for(i=0; i<pn_mailList.count; i++) {
struct pn_Mail *mail=(struct pn_Mail*)(g_slist_nth(pn_mailList.list,i)->data);
purple_debug_info(PLUGIN_ID, "Dellocating. mail->subject for i=%d. ", i);
purple_debug_info(PLUGIN_ID, "Memory=%d\n", (int)mail->subject);
g_free(mail->subject);
purple_debug_info(PLUGIN_ID, "Dellocating. mail->from for i=%d. ", i);
purple_debug_info(PLUGIN_ID, "Memory=%d\n",(int)mail->from);
g_free(mail->from);
purple_debug_info(PLUGIN_ID, "Dellocating. mail->to for i=%d. ", i);
purple_debug_info(PLUGIN_ID, "Memory=%d\n",(int)mail->to);
g_free(mail->to);
purple_debug_info(PLUGIN_ID, "Dellocating. mail->url for i=%d. ", i);
purple_debug_info(PLUGIN_ID, "Memory=%d\n",(int)mail->url);
g_free(mail->url);
}
pn_mailList.recvCount=0;
pn_mailList.count=0;
pn_mailList.index=-1;
g_slist_free(pn_mailList.list);
pn_mailList.list=NULL;
purple_debug_info(PLUGIN_ID, "Deallocation Done.\n");
}
}
static void pn_destroyWindow() {
if(pn_window!=NULL) {
gtk_widget_destroy((GtkWidget*)pn_window);
pn_window=NULL;
pn_label=NULL;
pn_rightArrowBtn=NULL;
pn_mailInfo_deallocate();
}
}
static void pn_createWindow() {
pn_window = (GtkWindow*) gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(pn_window,"New Mail");
//Set the border width of the pn_window.
gtk_container_set_border_width (GTK_CONTAINER(pn_window), 0);
gtk_window_set_type_hint (pn_window,GDK_WINDOW_TYPE_HINT_UTILITY);
gtk_window_set_gravity (pn_window,GDK_GRAVITY_SOUTH_EAST);
gtk_window_set_keep_above (pn_window, TRUE);
//Container elements
GtkBox *vbox = (GtkBox*) gtk_vbox_new(FALSE, 3); //TRUE = Allot equal spacing, 3px spacing between children
GtkBox *hbox = (GtkBox*) gtk_hbox_new(FALSE, 3);
//Create pn_label
pn_label = (GtkLabel*) gtk_label_new ("");
//Create Arrow
pn_rightArrowBtn = (GtkButton*) gtk_button_new();
GtkWidget* rightArrow = gtk_arrow_new(GTK_ARROW_RIGHT,GTK_SHADOW_OUT);
gtk_container_add(GTK_CONTAINER(pn_rightArrowBtn), rightArrow);
gtk_box_pack_start(hbox, (GtkWidget*)pn_rightArrowBtn, FALSE, FALSE, 0);
gtk_container_add(GTK_CONTAINER(vbox), (GtkWidget*)pn_label);
gtk_box_pack_end(vbox, (GtkWidget*)hbox, FALSE, FALSE, 0);
gtk_container_add(GTK_CONTAINER(pn_window), (GtkWidget*)vbox);
gtk_widget_set_size_request(rightArrow,30,30);
gtk_widget_set_size_request((GtkWidget*)pn_rightArrowBtn,30,30);
//Set button signal
g_signal_connect (pn_rightArrowBtn, "clicked", G_CALLBACK (rightArrowBtn_press_callback), NULL);
}
/*Helper functions*/
static void showWindow() {
gtk_widget_show_all((GtkWidget*)pn_window);
gtk_window_present(pn_window);
int window_width, window_height, offset=50;
gtk_window_get_size(pn_window, &window_width, &window_height);
gtk_window_move(pn_window, gdk_screen_width() - window_width, gdk_screen_height() - window_height - offset);
}
static void showMail(int index) {
if(index<0 || index>=pn_mailList.count) {
return;
}
struct pn_Mail *mail=(struct pn_Mail*)(g_slist_nth(pn_mailList.list,index)->data);
pn_mailList.index=index;
char msg[1000]="";
sprintf(msg, "New Mail %d/%d", index+1, pn_mailList.recvCount);
gtk_window_set_title(pn_window,msg);
sprintf(msg, "Acc: %s\nFrom %s\nSubject: %s", mail->to, mail->from, mail->subject);
gtk_label_set_text (pn_label,msg);
showWindow();
}
/*Even handlers*/
void rightArrowBtn_press_callback(GtkButton *button, gpointer user_data) {
if(pn_mailList.count>0) {
purple_debug_info(PLUGIN_ID, "rightArrowBtn_press_callback index=%d\n", (pn_mailList.index+1)%pn_mailList.count);
purple_debug_info(PLUGIN_ID, "rightArrowBtn_press_callback count=%d\n", pn_mailList.count);
showMail((pn_mailList.index+1)%pn_mailList.count);
}
}
/**************************************************************************
* Notify signals callbacks
**************************************************************************/
static void pn_notify_email_cb(char *subject, char *from, char *to, char *url) {
pn_destroyWindow(); //Destroy if exists
pn_createWindow();
char *subjects[1],*froms[1],*tos[1],*urls[1];
subjects[0]=subject;
froms[0]=from;
tos[0]=to;
urls[0]=url;
pn_mailInfo_allocate(subjects,froms,tos,urls,1);
showMail(0);
// char msg[1000]="";
// sprintf(msg, "Acc: %s\nFrom %s\nSubject: %s", to, from, subject);
// purple_notify_info(PLUGIN_ID,"New Mail",msg,"");
}
static void pn_notify_emails_cb(char **subjects, char **froms, char **tos, char **urls, guint count) {
pn_destroyWindow(); //Destroy if exists
pn_createWindow();
pn_mailInfo_allocate(subjects,froms,tos,urls,count);
showMail(0);
}
static gboolean pn_plugin_load(PurplePlugin * plugin) {
pn_Plugin = plugin; /* assign this here so we have a valid handle later */
/*Initialize global objects*/
pn_mailList.list=NULL;
pn_mailList.index=-1;
pn_mailList.count=0;
pn_mailList.recvCount=0;
//Some debug info
//purple_debug_info(PLUGIN_ID, "INFO level debug message. i = %d, f = %f, s = %s\n", i, f, s);
purple_debug_info(PLUGIN_ID,"Plugin loaded");
/* Notify signals */
void *notify_handle = purple_notify_get_handle();
purple_signal_connect(notify_handle, "displaying-email-notification", pn_Plugin, PURPLE_CALLBACK(pn_notify_email_cb), NULL);
purple_signal_connect(notify_handle, "displaying-emails-notification", pn_Plugin, PURPLE_CALLBACK(pn_notify_emails_cb), NULL);
return TRUE;
}
static gboolean pn_plugin_unload(PurplePlugin * plugin) {
pn_destroyWindow();
return TRUE;
}
static void pn_plugin_destroy(PurplePlugin *plugin) {
if(pn_window!=NULL) {
gtk_widget_destroy((GtkWidget*)pn_window);
/* Hope the OS will free memory :P*/
}
}
/* For specific notes on the meanings of each of these members, consult the C Plugin Howto
* on the website. */
static PurplePluginInfo info = {
PURPLE_PLUGIN_MAGIC,/* Plugin magic, this must always be
PURPLE_PLUGIN_MAGIC.
*/
PURPLE_MAJOR_VERSION,/* This is also defined in libpurple. It helps
libpurple's plugin system determine which
version of libpurple this plugin was
compiled for, and whether loading it will
cause problems.
*/
PURPLE_MINOR_VERSION, /* See previous */
PURPLE_PLUGIN_STANDARD,
PIDGIN_PLUGIN_TYPE, /* This field is the UI requirement. If you're
writing a core plugin, this must be NULL
and the plugin must not contain any UI
code. If you're writing a Pidgin plugin,
you need to use PIDGIN_PLUGIN_TYPE. If you
are writing a Finch plugin, you would use
FINCH_PLUGIN_TYPE.
*/
0, /* This field is for plugin flags. Currently,
the only flag available to plugins is
invisible (PURPLE_PLUGIN_FLAG_INVISIBLE).
It causes the plugin to NOT appear in the
list of plugins.
*/
NULL, /* This is a GList of plugin dependencies. In
other words, a GList of plugin id's that
your plugin depends on. Set this value to
NULL no matter what. If your plugin has
dependencies, set them at run-time in the
plugin_init function.
*/
PURPLE_PRIORITY_DEFAULT,/* This is the priority libpurple with give your
plugin. There are three possible values
for this field, PURPLE_PRIORITY_DEFAULT,
PURPLE_PRIORITY_HIGHEST, and
PURPLE_PRIORITY_LOWEST
*/
PLUGIN_ID, /* This is your plugin's id */
"Popup Notify", /* This is your plugin's name. This is what
will be displayed for your plugin in the UI.
*/
"1.0", /* This is the plugin version */
"Popup mail notification", /* This is the short summary of your plugin. */
"Popup mail notification", /* This is the description of your plugin. It
can be as long and as descriptive as you
like.
*/
"Munawwar Firoz <contact.munawwar@gmail.com>", /* Me name and email */
"http://munawwar.leadhoster.com", /* Website. Eh, At least the site exists :P */
pn_plugin_load, /* This is a pointer to a function for
libpurple to call when it is loading the
plugin. It should be of the type:
gboolean plugin_load(PurplePlugin *plugin)
Returning FALSE will stop the loading of the
plugin. Anything else would evaluate as
TRUE and the plugin will continue to load.
*/
pn_plugin_unload, /* Same as above except it is called when
libpurple tries to unload your plugin. It
should be of the type:
gboolean plugin_unload(PurplePlugin *plugin)
Returning TRUE will tell libpurple to
continue unloading while FALSE will stop
the unloading of your plugin.
*/
pn_plugin_destroy, /* Similar to the two above members, except
this is called when libpurple tries to
destory the plugin. This is generally only
called when for some reason or another the
plugin fails to probe correctly. It should
be of the type:
void plugin_destroy(PurplePlugin *plugin)
*/
NULL, /* This is a pointer to a UI-specific struct.
For a Pidgin plugin it will be a pointer to a
PidginPluginUiInfo struct, for example.
*/
NULL, /* This is a pointer to either a
PurplePluginLoaderInfo struct or a
PurplePluginProtocolInfo struct, and is
beyond the scope of this document.
*/
NULL, /* This is a pointer to a PurplePluginUiInfo
struct. It is a core/ui split way for
core plugins to have a UI configuration
frame. You can find an example of this
code in:
libpurple/plugins/pluginpref_example.c
*/
NULL, /* This is a function pointer where you can define
"plugin actions". The UI controls how
they're displayed. It should be of the
type:
GList *function_name(PurplePlugin *plugin,
gpointer context)
It must return a GList of
PurplePluginActions.
*/
NULL, /* This is a pointer reserved for future use.
We set it to NULL to indicate we don't
need it.
*/
NULL, /* This is a pointer reserved for future use.
We set it to NULL to indicate we don't
need it.
*/
NULL, /* This is a pointer reserved for future use.
We set it to NULL to indicate we don't
need it.
*/
NULL /* This is a pointer reserved for future use.
We set it to NULL to indicate we don't
need it.
*/
};
static void pn_init_plugin() {
}
PURPLE_INIT_PLUGIN (hello_world, pn_init_plugin, info)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.