/* MusicInfo plugin for gaim Displays whatever is currently playing in winamp in the user's profile in Gaim Written by Reuben Balik Copyright 2005 By Reuben Balik I'll add an official license later, but for now, please ask permission before using any of this code for any other project/product. Last Update: October 16, 2005 */ #include "internal.h" #include "connection.h" //#include "pluginpref.h" #include "signals.h" #include "version.h" #include "notify.h" #include #include static const int maxLen = 2048; //the maximum profile length (I'm not actually sure what the official max AIM profile size is) static int namesize = 256; //string size for artist and title static const int interval = 30 * 1000; //how often to check the winamp window (milleseconds) //the text that is output by the plugin: static const char before[] = "I am listening to "; static const char between[] = " by "; static const char after[] = "."; static const char default_replace[] = "%mi%"; //the string to search for during the first update static char* message; static char* replace_text; static int timeoutint = 0; static int messageLength; static GaimConnection* curgc; static gboolean getSong(char* title, char* artist, int len) { //next few lines copied off of the Winamp Forum HWND hwndWinamp = FindWindow("Winamp v1.x",NULL); char this_title[len]; int ret = GetWindowText(hwndWinamp,this_title,sizeof(this_title)); if(ret != 0) { if(strstr(this_title, "[Stopped]") != NULL) return FALSE; if(strstr(this_title, "[Paused]") != NULL) return FALSE; char temp[len]; char *firsthyphen, *secondhyphen, *period, *ptr; firsthyphen = strchr(this_title, '-'); if(firsthyphen == NULL) //when winamp starts up without playing it doesn't display the song name return FALSE; secondhyphen = strrchr(this_title, '-'); period = strchr(this_title, '.'); ptr = period+2; int count = 0; if(firsthyphen != secondhyphen) //there's two hyphens so we have an artist { while(ptr != firsthyphen && count < len) { temp[count] = *ptr; ptr++; count++; } temp[count-1] = '\0'; ptr+=2; strcpy(artist, temp); } else //no artist { strcpy(artist, "Unknown"); } count=0; while(ptr != secondhyphen && count < len) { temp[count] = *ptr; ptr++; count++; } temp[count-1] = '\0'; strcpy(title, temp); return TRUE; } else { return FALSE; } } static void updateInfo(GaimConnection *gc, gboolean forceMessage, gboolean updateServer) { GaimAccount* account; account = gaim_connection_get_account(gc); char curAcct[maxLen]; char newAcct[maxLen]; if(gaim_account_get_user_info(account) != NULL) { g_strlcpy(curAcct, gaim_account_get_user_info(account), sizeof(curAcct)); char title[namesize]; char artist[namesize]; char construct[messageLength]; if(!forceMessage) { if(getSong(title, artist, namesize)) //getSong returns true if we're actually listening to something { strcpy(construct, "\0"); strcat(construct, before); strcat(construct, title); strcat(construct, between); strcat(construct, artist); strcat(construct, after); } else { strcpy(construct, "I am not currently listening to any music."); } } char* pos = strstr(curAcct, replace_text); char* cur = curAcct; char* newcur = newAcct; int i, length; if(pos != NULL && strcmp(construct, message) != 0) { length = 0; if(!forceMessage) strcpy(message, construct); //copy the part before what is being replaced while(cur != pos) { *newcur = *cur; newcur++; cur++; length++; } //copy in the message for(i = 0; i < strlen(message); i++) { *newcur = message[i]; newcur++; } length+=i; //copy everything after the replace_text //first advance the pointer cur+=strlen(replace_text); //then copy the rest of the string while(*cur != '\0' && length < maxLen ) { *newcur = *cur; newcur++; cur++; length++; } *newcur = '\0'; gaim_account_set_user_info(account, newAcct); if(updateServer) serv_set_info(gc, newAcct); strcpy(replace_text, message); } } } static gboolean callUpdateInfo(gpointer gc) { updateInfo(gc, FALSE, TRUE); return TRUE; } static void online(GaimConnection *gc) { //doesn't run on two connections at once at the moment, but perhaps someday I can make it thread-safe if(timeoutint == 0) { curgc = gc; strcpy(replace_text, default_replace); updateInfo(gc, FALSE, TRUE); timeoutint = g_timeout_add(interval, callUpdateInfo, (gpointer)gc); } } static void signoff(GaimConnection *gc) { //this should only remove if the account signing off is the one that we're updating if(gc == curgc) { g_source_remove(timeoutint); //gaim_notify_info(gc, "removed", "timer removed", NULL); timeoutint = 0; strcpy(message, default_replace); updateInfo(gc, TRUE, FALSE); strcpy(replace_text, default_replace); } } static gboolean plugin_load(GaimPlugin *plugin) { //allocate memory for the strings messageLength = sizeof(char) *( (namesize * 2) + strlen(before) + strlen(between) + strlen(after) + 1 ); message = (char*) malloc(messageLength); strcpy(message, "\0"); replace_text = malloc(messageLength); gaim_signal_connect(gaim_connections_get_handle(), "signed-on", plugin, GAIM_CALLBACK(online), NULL); gaim_signal_connect(gaim_connections_get_handle(), "signing-off", plugin, GAIM_CALLBACK(signoff), NULL); return TRUE; } static gboolean plugin_unload(GaimPlugin *plugin) { free(message); free(replace_text); gaim_signal_disconnect(gaim_connections_get_handle(), "signed-on", plugin, GAIM_CALLBACK(online)); gaim_signal_disconnect(gaim_connections_get_handle(), "signing-off", plugin, GAIM_CALLBACK(signoff)); return TRUE; } static GaimPluginInfo info = { GAIM_PLUGIN_MAGIC, GAIM_MAJOR_VERSION, GAIM_MINOR_VERSION, GAIM_PLUGIN_STANDARD, /**< type */ NULL, /**< ui_requirement */ 0, /**< flags */ NULL, /**< dependencies */ GAIM_PRIORITY_DEFAULT, /**< priority */ "core-cybrguyrsb-musicinfo", /**< id */ N_("MusicInfo"), /**< name */ "0.2", /**< version */ /** summary */ N_("Displays the current song in Winamp in your user info"), /** description */ N_("Displays the current song in Winamp in your user info"), "Reuben Balik ", /**< author */ "http://www.ews.uiuc.edu/~rbalik2/musicinfo/", /**< homepage */ plugin_load, /**< load */ plugin_unload, /**< unload */ NULL, /**< destroy */ NULL, /**< ui_info */ NULL, /**< extra_info */ NULL, /**< prefs_info */ NULL }; static void init_plugin(GaimPlugin *plugin) { } GAIM_INIT_PLUGIN(mig, init_plugin, info)