/* Miranda plugin template, originally by Richard Hughes http://miranda-icq.sourceforge.net/ This file is placed in the public domain. Anybody is free to use or modify it as they wish with no restriction. There is no warranty. */ #include "Common.h" HINSTANCE hInst; int hLangpack; LIST XSN_Users(10, HandleKeySortT); HGENMENU hChangeSound = NULL; HANDLE hChangeSoundDlgList = NULL; BYTE isIgnoreSound = 0, isOwnSound = 0; PLUGININFOEX pluginInfo = { sizeof(PLUGININFOEX), __PLUGIN_NAME, PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), __DESCRIPTION, __AUTHOR, __AUTHOREMAIL, __COPYRIGHT, __AUTHORWEB, UNICODE_AWARE, // {08B86253-EC6E-4D09-B7A9-64ACDF0627B8} {0x8b86253, 0xec6e, 0x4d09, {0xb7, 0xa9, 0x64, 0xac, 0xdf, 0x6, 0x27, 0xb8}} }; BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { hInst = hinstDLL; return TRUE; } extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) { return &pluginInfo; } ///////////////////////////////////////////////////////////////////////////////////////// struct { int iStatus; const char *szName; const TCHAR *szInfo; } static selfSounds[] = { { ID_STATUS_OFFLINE, "SelfOffline", _T("Offline") }, { ID_STATUS_ONLINE, "SelfOnline", _T("Online") }, { ID_STATUS_AWAY, "SelfAway", _T("Away") }, { ID_STATUS_DND, "SelfDND", _T("Do Not Disturb") }, { ID_STATUS_NA, "SelfNA", _T("Not Available") }, { ID_STATUS_OCCUPIED, "SelfOccupied", _T("Occupied") }, { ID_STATUS_FREECHAT, "SelfFreeForChat", _T("Free For Chat") }, { ID_STATUS_INVISIBLE, "SelfInvisible", _T("Invisible") }, { ID_STATUS_ONTHEPHONE, "SelfOnThePhone", _T("On The Phone") }, { ID_STATUS_OUTTOLUNCH, "SelfOutToLunch", _T("Out To Lunch") } }; void InitSelfSounds() { // initializing self sounds for protocols int protoCount=0; PROTOACCOUNT** protos = 0; CallService(MS_PROTO_ENUMACCOUNTS, (WPARAM)&protoCount, (LPARAM)&protos); for (int i = 0; i < protoCount; i++) { for(int j = 0; j < SIZEOF(selfSounds); j++) { char namebuf[128]; mir_snprintf(namebuf, sizeof(namebuf), "%s%s", protos[i]->szModuleName, selfSounds[j].szName); TCHAR infobuf[256]; mir_sntprintf(infobuf, SIZEOF(infobuf), _T("%s [%s]"), TranslateT("Self status"), protos[i]->tszAccountName); SkinAddNewSoundExT(namebuf, infobuf, selfSounds[j].szInfo); } } } static int ProtoAck(WPARAM wParam, LPARAM lParam) { ACKDATA *ack = (ACKDATA*) lParam; if (ack != 0 && ack->szModule && ack->type == ACKTYPE_STATUS && ack->result == ACKRESULT_SUCCESS) { for(int i = 0; i < SIZEOF(selfSounds); i++) { if(selfSounds[i].iStatus == ack->lParam) { char buf[128]; _snprintf(buf, sizeof(buf), "%s%s", ack->szModule, selfSounds[i].szName); SkinPlaySound(buf); break; } } } return 0; } ///////////////////////////////////////////////////////////////////////////////////////// static bool isReceiveMessage(HANDLE hDbEvent) { DBEVENTINFO info = { sizeof(info) }; db_event_get(hDbEvent, &info); // i don't understand why it works and how it works, but it works correctly - practice way (методом тыка) // so, i think correct condition would be : eventType == EVENTTYPE_MESSAGE && info.flags & DBEF_READ, but it really isn't return !(((info.eventType != EVENTTYPE_MESSAGE) && !(info.flags & DBEF_READ)) || (info.flags & DBEF_SENT)); } static int ProcessEvent(WPARAM wParam, LPARAM lParam) { if (!isReceiveMessage(HANDLE(lParam))) return 0; isIgnoreSound = db_get_b((HCONTACT)wParam, SETTINGSNAME, SETTINGSIGNOREKEY, 0); DBVARIANT dbv; if ( !isIgnoreSound && !db_get_ts((HCONTACT)wParam, SETTINGSNAME, SETTINGSKEY, &dbv)) { TCHAR PlaySoundPath[MAX_PATH] = {0}; PathToAbsoluteT(dbv.ptszVal, PlaySoundPath); SkinPlaySoundFile(PlaySoundPath); db_free(&dbv); isOwnSound = 1; } return 0; } static int OnPlaySound(WPARAM wParam, LPARAM lParam) { if (isIgnoreSound) return 1; if (isOwnSound) { isOwnSound = 0; return 1; } return 0; } static int OnLoadInit(WPARAM wParam, LPARAM lParam) { CLISTMENUITEM mi = { sizeof(mi) }; mi.position = -0x7FFFFFFF; mi.flags = CMIF_TCHAR; mi.hIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); mi.ptszName = LPGENT("Custom contact sound"); mi.pszService = "XSoundNotify/ContactMenuCommand"; hChangeSound = Menu_AddContactMenuItem(&mi); InitSelfSounds(); return 0; } static int PrebuildContactMenu(WPARAM wParam, LPARAM lParam) { HCONTACT hContact = (HCONTACT)wParam; if (hContact) { char* szProto = GetContactProto(hContact); PROTOACCOUNT *pa = ProtoGetAccount(szProto); Menu_ShowItem(hChangeSound, IsSuitableProto(pa)); } return 0; } static int OnPreShutdown(WPARAM wParam, LPARAM lParam) { WindowList_Broadcast(hChangeSoundDlgList, WM_CLOSE, 0, 0); return 0; } extern "C" int __declspec(dllexport) Load() { mir_getLP(&pluginInfo); CreateServiceFunction("XSoundNotify/ContactMenuCommand", ShowDialog); hChangeSoundDlgList = WindowList_Create(); HookEvent(ME_PROTO_ACK, ProtoAck); HookEvent(ME_OPT_INITIALISE, OptInit); HookEvent(ME_DB_EVENT_ADDED, ProcessEvent); HookEvent(ME_SYSTEM_MODULESLOADED, OnLoadInit); HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PrebuildContactMenu); HookEvent(ME_SYSTEM_PRESHUTDOWN, OnPreShutdown); HookEvent(ME_SKIN_PLAYINGSOUND, OnPlaySound); return 0; } extern "C" int __declspec(dllexport) Unload(void) { WindowList_Destroy(hChangeSoundDlgList); return 0; }