/* 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: November 9, 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 const int namesize = 256; //string size for artist and title static const int interval = 30 * 1000; //how often to check the winamp window (milleseconds) //these are all the strings that the plugin searches for static char artist_replace[] = "%ar%"; static char title_replace[] = "%so%"; static char start_songText[] = "(mi)"; static char end_songText[] = "(/mi)"; static char start_noSongText[] = "(ns)"; static char end_noSongText[] = "(/ns)"; static int timeoutint = 0; static GaimConnection* curgc; static char* prevInfo; 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*2]; 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 gboolean replaceText(char* text, char* replaceStr, char* replaceWith, int max) { char* pos = text; char* foundAt = strstr(text, replaceStr); char newString[max]; if(foundAt == NULL) return FALSE; int cur = 0; while(pos != foundAt && cur < max) { newString[cur] = *pos; pos++; cur++; } char* replacePos = replaceWith; while(*replacePos != '\0' && cur < max) { newString[cur] = *replacePos; replacePos++; cur++; } pos+=strlen(replaceStr); while(*pos != '\0' && cur < max) { newString[cur] = *pos; pos++; cur++; } newString[cur] = '\0'; strncpy(text, newString, max); return TRUE; } static void updateInfo(GaimConnection *gc) { GaimAccount* account; account = gaim_connection_get_account(gc); char curAcct[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 hideThis[maxLen]; char* hidepos; char* endhidepos; if(getSong(title, artist, namesize)) { //replace the appropriate text replaceText(curAcct, start_songText, "\0", maxLen); replaceText(curAcct, end_songText, "\0", maxLen); replaceText(curAcct, artist_replace, artist, maxLen); replaceText(curAcct, title_replace, title, maxLen); //hide the text that gets displayed when we're not listening hidepos = strstr(curAcct, start_noSongText); endhidepos = strstr(curAcct, end_noSongText); endhidepos+= strlen(end_noSongText); if(hidepos != NULL && endhidepos != NULL && endhidepos > hidepos) { int i = 0; while(hidepos != endhidepos && i < maxLen) { hideThis[i] = *hidepos; hidepos++; i++; } hideThis[i] = '\0'; replaceText(curAcct, hideThis, "\0", maxLen); } } else { //replace the appropriate text replaceText(curAcct, start_noSongText, "\0", maxLen); replaceText(curAcct, end_noSongText, "\0", maxLen); //hide the text that gets displayed when we're listening hidepos = strstr(curAcct, start_songText); endhidepos = strstr(curAcct, end_songText); endhidepos+= strlen(end_songText); if(hidepos != NULL && endhidepos != NULL && endhidepos > hidepos) { int i = 0; while(hidepos != endhidepos && i < maxLen) { hideThis[i] = *hidepos; hidepos++; i++; } hideThis[i] = '\0'; replaceText(curAcct, hideThis, "\0", maxLen); } } //this is so we don't update the server if we don't have to if(strcmp(curAcct, prevInfo) != 0) { serv_set_info(gc, curAcct); strncpy(prevInfo, curAcct, maxLen); } } } static gboolean callUpdateInfo(gpointer gc) { updateInfo((GaimConnection*) gc); return TRUE; } static gboolean callFirstUpdate(gpointer gc) { updateInfo((GaimConnection*) gc); return FALSE; } 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; //a slight delay is needed for the first update because gaim already updates the server when you sign on g_timeout_add(2200, callFirstUpdate, (gpointer)gc); 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); timeoutint = 0; } } static gboolean plugin_load(GaimPlugin *plugin) { prevInfo = (char*) malloc(sizeof(char) * maxLen); *prevInfo = '\0'; 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(prevInfo); 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.3.1", /**< 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)